diff options
Diffstat (limited to 'Python/thread_pthread.h')
| -rw-r--r-- | Python/thread_pthread.h | 205 |
1 files changed, 42 insertions, 163 deletions
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index ffc791c..44e2552 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -18,6 +18,18 @@ #ifndef THREAD_STACK_SIZE #define THREAD_STACK_SIZE 0 /* use default stack size */ #endif + +#if (defined(__APPLE__) || defined(__FreeBSD__)) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 + /* The default stack size for new threads on OSX is small enough that + * we'll get hard crashes instead of 'maximum recursion depth exceeded' + * exceptions. + * + * The default stack size below is the minimal stack size where a + * simple recursive function doesn't cause a hard crash. + */ +#undef THREAD_STACK_SIZE +#define THREAD_STACK_SIZE 0x400000 +#endif /* for safety, ensure a viable minimum stacksize */ #define THREAD_STACK_MIN 0x8000 /* 32kB */ #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ @@ -64,8 +76,7 @@ /* Whether or not to use semaphores directly rather than emulating them with * mutexes and condition variables: */ -#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \ - defined(HAVE_SEM_TIMEDWAIT)) +#if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) # define USE_SEMAPHORES #else # undef USE_SEMAPHORES @@ -84,26 +95,6 @@ #endif -/* We assume all modern POSIX systems have gettimeofday() */ -#ifdef GETTIMEOFDAY_NO_TZ -#define GETTIMEOFDAY(ptv) gettimeofday(ptv) -#else -#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL) -#endif - -#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \ -do { \ - struct timeval tv; \ - GETTIMEOFDAY(&tv); \ - tv.tv_usec += microseconds % 1000000; \ - tv.tv_sec += microseconds / 1000000; \ - tv.tv_sec += tv.tv_usec / 1000000; \ - tv.tv_usec %= 1000000; \ - ts.tv_sec = tv.tv_sec; \ - ts.tv_nsec = tv.tv_usec * 1000; \ -} while(0) - - /* A pthread mutex isn't sufficient to model the Python lock type * because, according to Draft 5 of the docs (P1003.4a/D5), both of the * following are undefined: @@ -316,56 +307,31 @@ fix_status(int status) return (status == -1) ? errno : status; } -PyLockStatus -PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, - int intr_flag) +int +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - PyLockStatus success; + int success; sem_t *thelock = (sem_t *)lock; int status, error = 0; - struct timespec ts; - dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", - lock, microseconds, intr_flag)); + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (microseconds > 0) - MICROSECONDS_TO_TIMESPEC(microseconds, ts); do { - if (microseconds > 0) - status = fix_status(sem_timedwait(thelock, &ts)); - else if (microseconds == 0) - status = fix_status(sem_trywait(thelock)); - else + if (waitflag) status = fix_status(sem_wait(thelock)); - /* Retry if interrupted by a signal, unless the caller wants to be - notified. */ - } while (!intr_flag && status == EINTR); - - /* Don't check the status if we're stopping because of an interrupt. */ - if (!(intr_flag && status == EINTR)) { - if (microseconds > 0) { - if (status != ETIMEDOUT) - CHECK_STATUS("sem_timedwait"); - } - else if (microseconds == 0) { - if (status != EAGAIN) - CHECK_STATUS("sem_trywait"); - } - else { - CHECK_STATUS("sem_wait"); - } - } + else + status = fix_status(sem_trywait(thelock)); + } while (status == EINTR); /* Retry if interrupted by a signal */ - if (status == 0) { - success = PY_LOCK_ACQUIRED; - } else if (intr_flag && status == EINTR) { - success = PY_LOCK_INTR; - } else { - success = PY_LOCK_FAILURE; + if (waitflag) { + CHECK_STATUS("sem_wait"); + } else if (status != EAGAIN) { + CHECK_STATUS("sem_trywait"); } - dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", - lock, microseconds, intr_flag, success)); + success = (status == 0) ? 1 : 0; + + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); return success; } @@ -404,12 +370,6 @@ PyThread_allocate_lock(void) status = pthread_mutex_init(&lock->mut, pthread_mutexattr_default); CHECK_STATUS("pthread_mutex_init"); - /* Mark the pthread mutex underlying a Python mutex as - pure happens-before. We can't simply mark the - Python-level mutex as a mutex because it can be - acquired and released in different threads, which - will cause errors. */ - _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut); status = pthread_cond_init(&lock->lock_released, pthread_condattr_default); @@ -442,69 +402,37 @@ PyThread_free_lock(PyThread_type_lock lock) free((void *)thelock); } -PyLockStatus -PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, - int intr_flag) +int +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - PyLockStatus success; + int success; pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; - dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", - lock, microseconds, intr_flag)); + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); status = pthread_mutex_lock( &thelock->mut ); CHECK_STATUS("pthread_mutex_lock[1]"); + success = thelock->locked == 0; - if (thelock->locked == 0) { - success = PY_LOCK_ACQUIRED; - } else if (microseconds == 0) { - success = PY_LOCK_FAILURE; - } else { - struct timespec ts; - if (microseconds > 0) - MICROSECONDS_TO_TIMESPEC(microseconds, ts); + if ( !success && waitflag ) { /* continue trying until we get the lock */ /* mut must be locked by me -- part of the condition * protocol */ - success = PY_LOCK_FAILURE; - while (success == PY_LOCK_FAILURE) { - if (microseconds > 0) { - status = pthread_cond_timedwait( - &thelock->lock_released, - &thelock->mut, &ts); - if (status == ETIMEDOUT) - break; - CHECK_STATUS("pthread_cond_timed_wait"); - } - else { - status = pthread_cond_wait( - &thelock->lock_released, - &thelock->mut); - CHECK_STATUS("pthread_cond_wait"); - } - - if (intr_flag && status == 0 && thelock->locked) { - /* We were woken up, but didn't get the lock. We probably received - * a signal. Return PY_LOCK_INTR to allow the caller to handle - * it and retry. */ - success = PY_LOCK_INTR; - break; - } else if (status == 0 && !thelock->locked) { - success = PY_LOCK_ACQUIRED; - } else { - success = PY_LOCK_FAILURE; - } + while ( thelock->locked ) { + status = pthread_cond_wait(&thelock->lock_released, + &thelock->mut); + CHECK_STATUS("pthread_cond_wait"); } + success = 1; } - if (success == PY_LOCK_ACQUIRED) thelock->locked = 1; + if (success) thelock->locked = 1; status = pthread_mutex_unlock( &thelock->mut ); CHECK_STATUS("pthread_mutex_unlock[1]"); - if (error) success = PY_LOCK_FAILURE; - dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", - lock, microseconds, intr_flag, success)); + if (error) success = 0; + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); return success; } @@ -531,12 +459,6 @@ PyThread_release_lock(PyThread_type_lock lock) #endif /* USE_SEMAPHORES */ -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0); -} - /* set the thread stack size. * Return 0 if size is valid, -1 if size is invalid, * -2 if setting stack size is not supported. @@ -581,46 +503,3 @@ _pythread_pthread_set_stacksize(size_t size) } #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) - -#define Py_HAVE_NATIVE_TLS - -int -PyThread_create_key(void) -{ - pthread_key_t key; - int fail = pthread_key_create(&key, NULL); - return fail ? -1 : key; -} - -void -PyThread_delete_key(int key) -{ - pthread_key_delete(key); -} - -void -PyThread_delete_key_value(int key) -{ - pthread_setspecific(key, NULL); -} - -int -PyThread_set_key_value(int key, void *value) -{ - int fail; - void *oldValue = pthread_getspecific(key); - if (oldValue != NULL) - return 0; - fail = pthread_setspecific(key, value); - return fail ? -1 : 0; -} - -void * -PyThread_get_key_value(int key) -{ - return pthread_getspecific(key); -} - -void -PyThread_ReInitTLS(void) -{} |
