Mercurial > cpython-lru_cache-weakref
view Python/thread_pthread.h @ 46453:981df13aab20
Merged revisions 61440-61441,61443,61445-61448,61451-61452,61455-61457,61459-61464,61466-61467,61469-61470,61476-61477,61479,61481-61482,61485,61487,61490,61493-61494,61497,61499-61502,61505-61506,61508,61511-61514,61519,61521-61522,61530-61531,61533-61537,61541-61555,61557-61558,61561-61562,61566-61569,61572-61574,61578-61579,61583-61584,61588-61589,61592,61594,61598-61601,61603-61604,61607-61612,61617,61619-61620,61624,61626,61628-61630,61635-61638,61640-61643,61645,61648,61653-61655,61659-61662,61664,61666,61668-61671,61673,61675,61679-61680,61682,61685-61686,61689-61695,61697-61699,61701-61703,61706,61710,61713,61717,61723,61726-61730,61736,61738,61740,61742,61745-61752,61754-61760,61762-61764,61768,61770-61772,61774-61775,61784-61787,61789-61792,61794-61795,61797-61806,61808-61809,61811-61812,61814-61819,61824,61826-61833,61835-61840,61843-61845,61848,61850,61854-61862,61865-61866,61868,61872-61873,61876-61877,61883-61888,61890-61891,61893-61899,61901-61903,61905-61912,61914,61917,61920-61921,61927,61930,61932-61934,61939,61941-61942,61944-61951,61955,61960-61963,61980,61982-61983,61991,61994-61996,62001-62003,62008-62010,62016-62017,62022,62024,62027,62031-62034,62041,62045-62046,62055-62058,62060-62066,62068-62074,62076-62079,62081-62083,62086-62089,62092-62094,62098,62101,62104,62106-62109,62115-62122,62124-62125,62128,62130,62132,62134-62135,62137,62139-62140,62144,62146,62151,62155,62157,62162-62166,62171-62172,62175-62176,62178,62181-62186,62188-62192,62196,62200-62203,62206,62211-62213,62215-62218,62222,62224-62226,62228,62232,62236,62240-62245,62248,62250-62254,62256-62258,62262,62264-62265,62267-62270,62272-62276,62280-62288,62291-62292,62299-62301,62307,62312,62316-62318,62322-62331,62333-62337,62339-62344,62346-62348 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62323 | brett.cannon | 2008-04-13 10:09:43 -0700 (Sun, 13 Apr 2008) | 3 lines
Add an explicit check for output in a test to try to diagnose a failure on
Windows.
........
r62324 | brett.cannon | 2008-04-13 10:41:31 -0700 (Sun, 13 Apr 2008) | 3 lines
Fix spliting on colons on Windows machines with a file path by limiting the
number of splits.
........
r62329 | benjamin.peterson | 2008-04-13 13:35:56 -0700 (Sun, 13 Apr 2008) | 2 lines
#2627 Let it be known what pgen generates
........
r62330 | benjamin.peterson | 2008-04-13 13:40:03 -0700 (Sun, 13 Apr 2008) | 2 lines
Added an ignore file for Bazaar #2510
........
r62331 | georg.brandl | 2008-04-13 13:50:29 -0700 (Sun, 13 Apr 2008) | 2 lines
Improve -X error message.
........
r62334 | andrew.kuchling | 2008-04-13 15:39:12 -0700 (Sun, 13 Apr 2008) | 1 line
Add example
........
r62340 | amaury.forgeotdarc | 2008-04-14 12:55:40 -0700 (Mon, 14 Apr 2008) | 2 lines
Update project files for all Windows supported compilers
........
r62341 | amaury.forgeotdarc | 2008-04-14 13:07:48 -0700 (Mon, 14 Apr 2008) | 6 lines
Correct a refleak found by "regrtest.py -R:: test_structmembers"
Some other minor updates in _warnings.c:
- make a function static
- rename a shadowing local variable
........
r62347 | andrew.kuchling | 2008-04-14 19:24:15 -0700 (Mon, 14 Apr 2008) | 1 line
Various items; begin writing the SSL section
........
r62348 | neal.norwitz | 2008-04-14 20:46:21 -0700 (Mon, 14 Apr 2008) | 1 line
Prevent namespace pollution, add static for internal functions
........
| author | Neal Norwitz <nnorwitz@gmail.com> |
|---|---|
| date | Tue, 15 Apr 2008 06:43:13 +0000 |
| parents | 654c380cf8b9 |
| children | f197407bdba2 798e0d0c7246 |
line wrap: on
line source
/* Posix threads interface */ #include <stdlib.h> #include <string.h> #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #define destructor xxdestructor #endif #include <pthread.h> #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #undef destructor #endif #include <signal.h> /* The POSIX spec requires that use of pthread_attr_setstacksize be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */ #ifdef _POSIX_THREAD_ATTR_STACKSIZE #ifndef THREAD_STACK_SIZE #define THREAD_STACK_SIZE 0 /* use default stack size */ #endif /* for safety, ensure a viable minimum stacksize */ #define THREAD_STACK_MIN 0x8000 /* 32kB */ #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ #ifdef THREAD_STACK_SIZE #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined" #endif #endif /* The POSIX spec says that implementations supporting the sem_* family of functions must indicate this by defining _POSIX_SEMAPHORES. */ #ifdef _POSIX_SEMAPHORES /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so we need to add 0 to make it work there as well. */ #if (_POSIX_SEMAPHORES+0) == -1 #define HAVE_BROKEN_POSIX_SEMAPHORES #else #include <semaphore.h> #include <errno.h> #endif #endif /* Before FreeBSD 5.4, system scope threads was very limited resource in default setting. So the process scope is preferred to get enough number of threads to work. */ #ifdef __FreeBSD__ #include <osreldate.h> #if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101 #undef PTHREAD_SYSTEM_SCHED_SUPPORTED #endif #endif #if !defined(pthread_attr_default) # define pthread_attr_default ((pthread_attr_t *)NULL) #endif #if !defined(pthread_mutexattr_default) # define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL) #endif #if !defined(pthread_condattr_default) # define pthread_condattr_default ((pthread_condattr_t *)NULL) #endif /* 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) # define USE_SEMAPHORES #else # undef USE_SEMAPHORES #endif /* On platforms that don't use standard POSIX threads pthread_sigmask() * isn't present. DEC threads uses sigprocmask() instead as do most * other UNIX International compliant systems that don't have the full * pthread implementation. */ #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) # define SET_THREAD_SIGMASK pthread_sigmask #else # define SET_THREAD_SIGMASK sigprocmask #endif /* 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: * -> a thread tries to lock a mutex it already has locked * -> a thread tries to unlock a mutex locked by a different thread * pthread mutexes are designed for serializing threads over short pieces * of code anyway, so wouldn't be an appropriate implementation of * Python's locks regardless. * * The pthread_lock struct implements a Python lock as a "locked?" bit * and a <condition, mutex> pair. In general, if the bit can be acquired * instantly, it is, else the pair is used to block the thread until the * bit is cleared. 9 May 1994 tim@ksr.com */ typedef struct { char locked; /* 0=unlocked, 1=locked */ /* a <cond, mutex> pair to handle an acquire of a locked lock */ pthread_cond_t lock_released; pthread_mutex_t mut; } pthread_lock; #define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; } /* * Initialization. */ #ifdef _HAVE_BSDI static void _noop(void) { } static void PyThread__init_thread(void) { /* DO AN INIT BY STARTING THE THREAD */ static int dummy = 0; pthread_t thread1; pthread_create(&thread1, NULL, (void *) _noop, &dummy); pthread_join(thread1, NULL); } #else /* !_HAVE_BSDI */ static void PyThread__init_thread(void) { #if defined(_AIX) && defined(__GNUC__) pthread_init(); #endif } #endif /* !_HAVE_BSDI */ /* * Thread support. */ long PyThread_start_new_thread(void (*func)(void *), void *arg) { pthread_t th; int status; #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) pthread_attr_t attrs; #endif #if defined(THREAD_STACK_SIZE) size_t tss; #endif dprintf(("PyThread_start_new_thread called\n")); if (!initialized) PyThread_init_thread(); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) if (pthread_attr_init(&attrs) != 0) return -1; #endif #if defined(THREAD_STACK_SIZE) tss = (_pythread_stacksize != 0) ? _pythread_stacksize : THREAD_STACK_SIZE; if (tss != 0) { if (pthread_attr_setstacksize(&attrs, tss) != 0) { pthread_attr_destroy(&attrs); return -1; } } #endif #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); #endif status = pthread_create(&th, #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) &attrs, #else (pthread_attr_t*)NULL, #endif (void* (*)(void *))func, (void *)arg ); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) pthread_attr_destroy(&attrs); #endif if (status != 0) return -1; pthread_detach(th); #if SIZEOF_PTHREAD_T <= SIZEOF_LONG return (long) th; #else return (long) *(long *) &th; #endif } /* XXX This implementation is considered (to quote Tim Peters) "inherently hosed" because: - It does not guarantee the promise that a non-zero integer is returned. - The cast to long is inherently unsafe. - It is not clear that the 'volatile' (for AIX?) and ugly casting in the latter return statement (for Alpha OSF/1) are any longer necessary. */ long PyThread_get_thread_ident(void) { volatile pthread_t threadid; if (!initialized) PyThread_init_thread(); /* Jump through some hoops for Alpha OSF/1 */ threadid = pthread_self(); #if SIZEOF_PTHREAD_T <= SIZEOF_LONG return (long) threadid; #else return (long) *(long *) &threadid; #endif } static void do_PyThread_exit_thread(int no_cleanup) { dprintf(("PyThread_exit_thread called\n")); if (!initialized) { if (no_cleanup) _exit(0); else exit(0); } } void PyThread_exit_thread(void) { do_PyThread_exit_thread(0); } void PyThread__exit_thread(void) { do_PyThread_exit_thread(1); } #ifndef NO_EXIT_PROG static void do_PyThread_exit_prog(int status, int no_cleanup) { dprintf(("PyThread_exit_prog(%d) called\n", status)); if (!initialized) if (no_cleanup) _exit(status); else exit(status); } void PyThread_exit_prog(int status) { do_PyThread_exit_prog(status, 0); } void PyThread__exit_prog(int status) { do_PyThread_exit_prog(status, 1); } #endif /* NO_EXIT_PROG */ #ifdef USE_SEMAPHORES /* * Lock support. */ PyThread_type_lock PyThread_allocate_lock(void) { sem_t *lock; int status, error = 0; dprintf(("PyThread_allocate_lock called\n")); if (!initialized) PyThread_init_thread(); lock = (sem_t *)malloc(sizeof(sem_t)); if (lock) { status = sem_init(lock,0,1); CHECK_STATUS("sem_init"); if (error) { free((void *)lock); lock = NULL; } } dprintf(("PyThread_allocate_lock() -> %p\n", lock)); return (PyThread_type_lock)lock; } void PyThread_free_lock(PyThread_type_lock lock) { sem_t *thelock = (sem_t *)lock; int status, error = 0; dprintf(("PyThread_free_lock(%p) called\n", lock)); if (!thelock) return; status = sem_destroy(thelock); CHECK_STATUS("sem_destroy"); free((void *)thelock); } /* * As of February 2002, Cygwin thread implementations mistakenly report error * codes in the return value of the sem_ calls (like the pthread_ functions). * Correct implementations return -1 and put the code in errno. This supports * either. */ static int fix_status(int status) { return (status == -1) ? errno : status; } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { int success; sem_t *thelock = (sem_t *)lock; int status, error = 0; dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); do { if (waitflag) status = fix_status(sem_wait(thelock)); else status = fix_status(sem_trywait(thelock)); } while (status == EINTR); /* Retry if interrupted by a signal */ if (waitflag) { CHECK_STATUS("sem_wait"); } else if (status != EAGAIN) { CHECK_STATUS("sem_trywait"); } success = (status == 0) ? 1 : 0; dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); return success; } void PyThread_release_lock(PyThread_type_lock lock) { sem_t *thelock = (sem_t *)lock; int status, error = 0; dprintf(("PyThread_release_lock(%p) called\n", lock)); status = sem_post(thelock); CHECK_STATUS("sem_post"); } #else /* USE_SEMAPHORES */ /* * Lock support. */ PyThread_type_lock PyThread_allocate_lock(void) { pthread_lock *lock; int status, error = 0; dprintf(("PyThread_allocate_lock called\n")); if (!initialized) PyThread_init_thread(); lock = (pthread_lock *) malloc(sizeof(pthread_lock)); if (lock) { memset((void *)lock, '\0', sizeof(pthread_lock)); lock->locked = 0; status = pthread_mutex_init(&lock->mut, pthread_mutexattr_default); CHECK_STATUS("pthread_mutex_init"); status = pthread_cond_init(&lock->lock_released, pthread_condattr_default); CHECK_STATUS("pthread_cond_init"); if (error) { free((void *)lock); lock = 0; } } dprintf(("PyThread_allocate_lock() -> %p\n", lock)); return (PyThread_type_lock) lock; } void PyThread_free_lock(PyThread_type_lock lock) { pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; dprintf(("PyThread_free_lock(%p) called\n", lock)); status = pthread_mutex_destroy( &thelock->mut ); CHECK_STATUS("pthread_mutex_destroy"); status = pthread_cond_destroy( &thelock->lock_released ); CHECK_STATUS("pthread_cond_destroy"); free((void *)thelock); } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { int success; pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; 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 ( !success && waitflag ) { /* continue trying until we get the lock */ /* mut must be locked by me -- part of the condition * protocol */ while ( thelock->locked ) { status = pthread_cond_wait(&thelock->lock_released, &thelock->mut); CHECK_STATUS("pthread_cond_wait"); } success = 1; } if (success) thelock->locked = 1; status = pthread_mutex_unlock( &thelock->mut ); CHECK_STATUS("pthread_mutex_unlock[1]"); if (error) success = 0; dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); return success; } void PyThread_release_lock(PyThread_type_lock lock) { pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; dprintf(("PyThread_release_lock(%p) called\n", lock)); status = pthread_mutex_lock( &thelock->mut ); CHECK_STATUS("pthread_mutex_lock[3]"); thelock->locked = 0; status = pthread_mutex_unlock( &thelock->mut ); CHECK_STATUS("pthread_mutex_unlock[3]"); /* wake up someone (anyone, if any) waiting on the lock */ status = pthread_cond_signal( &thelock->lock_released ); CHECK_STATUS("pthread_cond_signal"); } #endif /* USE_SEMAPHORES */ /* set the thread stack size. * Return 0 if size is valid, -1 if size is invalid, * -2 if setting stack size is not supported. */ static int _pythread_pthread_set_stacksize(size_t size) { #if defined(THREAD_STACK_SIZE) pthread_attr_t attrs; size_t tss_min; int rc = 0; #endif /* set to default */ if (size == 0) { _pythread_stacksize = 0; return 0; } #if defined(THREAD_STACK_SIZE) #if defined(PTHREAD_STACK_MIN) tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN : THREAD_STACK_MIN; #else tss_min = THREAD_STACK_MIN; #endif if (size >= tss_min) { /* validate stack size by setting thread attribute */ if (pthread_attr_init(&attrs) == 0) { rc = pthread_attr_setstacksize(&attrs, size); pthread_attr_destroy(&attrs); if (rc == 0) { _pythread_stacksize = size; return 0; } } } return -1; #else return -2; #endif } #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
