Author: Alex Gaynor <alex.gay...@gmail.com> Branch: Changeset: r72259:50a337a2e4f2 Date: 2014-06-27 16:41 -0700 http://bitbucket.org/pypy/pypy/changeset/50a337a2e4f2/
Log: merged upstream diff --git a/rpython/translator/c/src/thread_gil.c b/rpython/translator/c/src/thread_gil.c --- a/rpython/translator/c/src/thread_gil.c +++ b/rpython/translator/c/src/thread_gil.c @@ -38,15 +38,14 @@ long rpy_fastgil = 1; long rpy_waiting_threads = -42; /* GIL not initialized */ -static mutex_t mutex_gil_stealer; -static mutex_t mutex_gil; +static mutex1_t mutex_gil_stealer; +static mutex2_t mutex_gil; void RPyGilAllocate(void) { assert(RPY_FASTGIL_LOCKED(rpy_fastgil)); - mutex_init(&mutex_gil_stealer); - mutex_init(&mutex_gil); - mutex_lock(&mutex_gil); + mutex1_init(&mutex_gil_stealer); + mutex2_init_locked(&mutex_gil); rpy_waiting_threads = 0; } @@ -80,14 +79,15 @@ first-in-first-out order, this will nicely give the threads a round-robin chance. */ - mutex_lock(&mutex_gil_stealer); + mutex1_lock(&mutex_gil_stealer); + mutex2_loop_start(&mutex_gil); /* We are now the stealer thread. Steals! */ while (1) { /* Sleep for one interval of time. We may be woken up earlier if 'mutex_gil' is released. */ - if (mutex_lock_timeout(&mutex_gil, 0.0001)) { /* 0.1 ms... */ + if (mutex2_lock_timeout(&mutex_gil, 0.0001)) { /* 0.1 ms... */ /* We arrive here if 'mutex_gil' was recently released and we just relocked it. */ @@ -107,7 +107,8 @@ /* Otherwise, loop back. */ } atomic_decrement(&rpy_waiting_threads); - mutex_unlock(&mutex_gil_stealer); + mutex2_loop_stop(&mutex_gil); + mutex1_unlock(&mutex_gil_stealer); RESTORE_ERRNO(); } @@ -140,7 +141,7 @@ /* Explicitly release the 'mutex_gil'. */ - mutex_unlock(&mutex_gil); + mutex2_unlock(&mutex_gil); /* Now nobody has got the GIL, because 'mutex_gil' is released (but rpy_fastgil is still locked). Call RPyGilAcquire(). It will diff --git a/rpython/translator/c/src/thread_nt.c b/rpython/translator/c/src/thread_nt.c --- a/rpython/translator/c/src/thread_nt.c +++ b/rpython/translator/c/src/thread_nt.c @@ -196,33 +196,46 @@ /* GIL code */ /************************************************************/ -typedef HANDLE mutex_t; /* a semaphore, on Windows */ +typedef HANDLE mutex2_t; /* a semaphore, on Windows */ static void gil_fatal(const char *msg) { fprintf(stderr, "Fatal error in the GIL: %s\n", msg); abort(); } -static inline void mutex_init(mutex_t *mutex) { +static inline void mutex2_init(mutex2_t *mutex) { *mutex = CreateSemaphore(NULL, 1, 1, NULL); if (*mutex == NULL) gil_fatal("CreateSemaphore failed"); } -static inline void mutex_lock(mutex_t *mutex) { +static inline void mutex2_lock(mutex2_t *mutex) { WaitForSingleObject(*mutex, INFINITE); } -static inline void mutex_unlock(mutex_t *mutex) { +static inline void mutex2_unlock(mutex2_t *mutex) { ReleaseSemaphore(*mutex, 1, NULL); } -static inline int mutex_lock_timeout(mutex_t *mutex, double delay) +static inline void mutex2_init_locked(mutex2_t *mutex) { + mutex2_init(mutex); + mutex2_lock(mutex); +} + +static inline void mutex2_loop_start(mutex2_t *mutex) { } +static inline void mutex2_loop_stop(mutex2_t *mutex) { } + +static inline int mutex2_lock_timeout(mutex2_t *mutex, double delay) { DWORD result = WaitForSingleObject(*mutex, (DWORD)(delay * 1000.0 + 0.999)); return (result != WAIT_TIMEOUT); } +#define mutex1_t mutex2_t +#define mutex1_init mutex2_init +#define mutex1_lock mutex2_lock +#define mutex1_unlock mutex2_unlock + #ifdef _M_IA64 /* On Itanium, use 'acquire' memory ordering semantics */ #define lock_test_and_set(ptr, value) InterlockedExchangeAcquire(ptr, value) diff --git a/rpython/translator/c/src/thread_pthread.c b/rpython/translator/c/src/thread_pthread.c --- a/rpython/translator/c/src/thread_pthread.c +++ b/rpython/translator/c/src/thread_pthread.c @@ -479,7 +479,7 @@ #define ASSERT_STATUS(call) \ if (call != 0) { \ - fprintf(stderr, "Fatal error: " #call "\n"); \ + perror("Fatal error: " #call); \ abort(); \ } @@ -495,27 +495,42 @@ t->tv_nsec = nsec; } -typedef pthread_mutex_t mutex_t; +typedef pthread_mutex_t mutex1_t; -static inline void mutex_init(mutex_t *mutex) { +static inline void mutex1_init(mutex1_t *mutex) { ASSERT_STATUS(pthread_mutex_init(mutex, pthread_mutexattr_default)); } -static inline void mutex_lock(mutex_t *mutex) { +static inline void mutex1_lock(mutex1_t *mutex) { ASSERT_STATUS(pthread_mutex_lock(mutex)); } -static inline void mutex_unlock(mutex_t *mutex) { +static inline void mutex1_unlock(mutex1_t *mutex) { ASSERT_STATUS(pthread_mutex_unlock(mutex)); } -static inline int mutex_lock_timeout(mutex_t *mutex, double delay) { + +/************************************************************/ +#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 +/************************************************************/ +/* NB. the test above should cover two features: clock_gettime() and + pthread_mutex_timedlock(). It's unclear that there is a measurable + benefit in using pthread_mutex_timedlock(), but there is certainly + one in using clock_gettime(). */ + +#define mutex2_t mutex1_t +#define mutex2_init mutex1_init +#define mutex2_lock mutex1_lock +#define mutex2_unlock mutex1_unlock + +static inline void mutex2_init_locked(mutex2_t *mutex) { + mutex2_init(mutex); + mutex2_lock(mutex); +} + +static inline void mutex2_loop_start(mutex2_t *mutex) { } +static inline void mutex2_loop_stop(mutex2_t *mutex) { } + +static inline int mutex2_lock_timeout(mutex2_t *mutex, double delay) { struct timespec t; -#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 clock_gettime(CLOCK_REALTIME, &t); -#else - struct timeval tv; - RPY_GETTIMEOFDAY(&tv); - t.tv_sec = tv.tv_sec; - t.tv_nsec = tv.tv_usec * 1000 + 999; -#endif timespec_add(&t, delay); int error_from_timedlock = pthread_mutex_timedlock(mutex, &t); if (error_from_timedlock == ETIMEDOUT) @@ -523,6 +538,58 @@ ASSERT_STATUS(error_from_timedlock); return 1; } + +/************************************************************/ +#else +/************************************************************/ + +typedef struct { + char locked; + pthread_mutex_t mut; + pthread_cond_t cond; +} mutex2_t; + +static inline void mutex2_init_locked(mutex2_t *mutex) { + mutex->locked = 1; + ASSERT_STATUS(pthread_mutex_init(&mutex->mut, pthread_mutexattr_default)); + ASSERT_STATUS(pthread_cond_init(&mutex->cond, pthread_condattr_default)); +} +static inline void mutex2_unlock(mutex2_t *mutex) { + ASSERT_STATUS(pthread_mutex_lock(&mutex->mut)); + mutex->locked = 0; + ASSERT_STATUS(pthread_mutex_unlock(&mutex->mut)); + ASSERT_STATUS(pthread_cond_signal(&mutex->cond)); +} +static inline void mutex2_loop_start(mutex2_t *mutex) { + ASSERT_STATUS(pthread_mutex_lock(&mutex->mut)); +} +static inline void mutex2_loop_stop(mutex2_t *mutex) { + ASSERT_STATUS(pthread_mutex_unlock(&mutex->mut)); +} +static inline int mutex2_lock_timeout(mutex2_t *mutex, double delay) { + if (mutex->locked) { + struct timespec t; + struct timeval tv; + RPY_GETTIMEOFDAY(&tv); + t.tv_sec = tv.tv_sec; + t.tv_nsec = tv.tv_usec * 1000 + 999; + timespec_add(&t, delay); + int error_from_timedwait = pthread_cond_timedwait( + &mutex->cond, &mutex->mut, &t); + if (error_from_timedwait != ETIMEDOUT) { + ASSERT_STATUS(error_from_timedwait); + } + } + int result = !mutex->locked; + mutex->locked = 1; + return result; +} + +/************************************************************/ +#endif /* _POSIX_TIMERS */ +/************************************************************/ + + #define lock_test_and_set(ptr, value) __sync_lock_test_and_set(ptr, value) #define atomic_increment(ptr) __sync_fetch_and_add(ptr, 1) #define atomic_decrement(ptr) __sync_fetch_and_sub(ptr, 1) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit