Move setting of ioready 'wait' earlier in call chain, to
[python/dscho.git] / Python / thread_pthread.h
blobe30982fc4f8be5c8977ed2841ac84bbc498f1940
2 /* Posix threads interface */
4 #include <stdlib.h>
5 #include <string.h>
6 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
7 #define destructor xxdestructor
8 #endif
9 #include <pthread.h>
10 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
11 #undef destructor
12 #endif
13 #include <signal.h>
15 /* The POSIX spec says that implementations supporting the sem_*
16 family of functions must indicate this by defining
17 _POSIX_SEMAPHORES. */
18 #ifdef _POSIX_SEMAPHORES
19 #include <semaphore.h>
20 #include <errno.h>
21 #endif
24 /* try to determine what version of the Pthread Standard is installed.
25 * this is important, since all sorts of parameter types changed from
26 * draft to draft and there are several (incompatible) drafts in
27 * common use. these macros are a start, at least.
28 * 12 May 1997 -- david arnold <davida@pobox.com>
31 #if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
32 /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
33 # define PY_PTHREAD_D4
34 # error Systems with PY_PTHREAD_D4 are unsupported. See README.
36 #elif defined(__osf__) && defined (__alpha)
37 /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
38 # if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
39 # define PY_PTHREAD_D4
40 # error Systems with PY_PTHREAD_D4 are unsupported. See README.
41 # else
42 # define PY_PTHREAD_STD
43 # endif
45 #elif defined(_AIX)
46 /* SCHED_BG_NP is defined if using AIX DCE pthreads
47 * but it is unsupported by AIX 4 pthreads. Default
48 * attributes for AIX 4 pthreads equal to NULL. For
49 * AIX DCE pthreads they should be left unchanged.
51 # if !defined(SCHED_BG_NP)
52 # define PY_PTHREAD_STD
53 # else
54 # define PY_PTHREAD_D7
55 # error Systems with PY_PTHREAD_D7 are unsupported. See README.
56 # endif
58 #elif defined(__DGUX)
59 # define PY_PTHREAD_D6
60 # error Systems with PY_PTHREAD_D6 are unsupported. See README.
62 #elif defined(__hpux) && defined(_DECTHREADS_)
63 # define PY_PTHREAD_D4
64 # error Systems with PY_PTHREAD_D4 are unsupported. See README.
66 #else /* Default case */
67 # define PY_PTHREAD_STD
69 #endif
71 #ifdef USE_GUSI
72 /* The Macintosh GUSI I/O library sets the stackspace to
73 ** 20KB, much too low. We up it to 64K.
75 #define THREAD_STACK_SIZE 0x10000
76 #endif
79 /* set default attribute object for different versions */
81 #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
82 #if !defined(pthread_attr_default)
83 # define pthread_attr_default pthread_attr_default
84 #endif
85 #if !defined(pthread_mutexattr_default)
86 # define pthread_mutexattr_default pthread_mutexattr_default
87 #endif
88 #if !defined(pthread_condattr_default)
89 # define pthread_condattr_default pthread_condattr_default
90 #endif
91 #elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
92 #if !defined(pthread_attr_default)
93 # define pthread_attr_default ((pthread_attr_t *)NULL)
94 #endif
95 #if !defined(pthread_mutexattr_default)
96 # define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
97 #endif
98 #if !defined(pthread_condattr_default)
99 # define pthread_condattr_default ((pthread_condattr_t *)NULL)
100 #endif
101 #endif
104 /* Whether or not to use semaphores directly rather than emulating them with
105 * mutexes and condition variables:
107 #if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES)
108 # define USE_SEMAPHORES
109 #else
110 # undef USE_SEMAPHORES
111 #endif
114 /* On platforms that don't use standard POSIX threads pthread_sigmask()
115 * isn't present. DEC threads uses sigprocmask() instead as do most
116 * other UNIX International compliant systems that don't have the full
117 * pthread implementation.
119 #ifdef HAVE_PTHREAD_SIGMASK
120 # define SET_THREAD_SIGMASK pthread_sigmask
121 #else
122 # define SET_THREAD_SIGMASK sigprocmask
123 #endif
126 /* A pthread mutex isn't sufficient to model the Python lock type
127 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
128 * following are undefined:
129 * -> a thread tries to lock a mutex it already has locked
130 * -> a thread tries to unlock a mutex locked by a different thread
131 * pthread mutexes are designed for serializing threads over short pieces
132 * of code anyway, so wouldn't be an appropriate implementation of
133 * Python's locks regardless.
135 * The pthread_lock struct implements a Python lock as a "locked?" bit
136 * and a <condition, mutex> pair. In general, if the bit can be acquired
137 * instantly, it is, else the pair is used to block the thread until the
138 * bit is cleared. 9 May 1994 tim@ksr.com
141 typedef struct {
142 char locked; /* 0=unlocked, 1=locked */
143 /* a <cond, mutex> pair to handle an acquire of a locked lock */
144 pthread_cond_t lock_released;
145 pthread_mutex_t mut;
146 } pthread_lock;
148 #define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
151 * Initialization.
154 #ifdef _HAVE_BSDI
155 static
156 void _noop(void)
160 static void
161 PyThread__init_thread(void)
163 /* DO AN INIT BY STARTING THE THREAD */
164 static int dummy = 0;
165 pthread_t thread1;
166 pthread_create(&thread1, NULL, (void *) _noop, &dummy);
167 pthread_join(thread1, NULL);
170 #else /* !_HAVE_BSDI */
172 static void
173 PyThread__init_thread(void)
175 #if defined(_AIX) && defined(__GNUC__)
176 pthread_init();
177 #endif
180 #endif /* !_HAVE_BSDI */
183 * Thread support.
187 long
188 PyThread_start_new_thread(void (*func)(void *), void *arg)
190 pthread_t th;
191 int success;
192 sigset_t oldmask, newmask;
193 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
194 pthread_attr_t attrs;
195 #endif
196 dprintf(("PyThread_start_new_thread called\n"));
197 if (!initialized)
198 PyThread_init_thread();
200 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
201 pthread_attr_init(&attrs);
202 #endif
203 #ifdef THREAD_STACK_SIZE
204 pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
205 #endif
206 #ifdef PTHREAD_SYSTEM_SCHED_SUPPORTED
207 pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
208 #endif
210 /* Mask all signals in the current thread before creating the new
211 * thread. This causes the new thread to start with all signals
212 * blocked.
214 sigfillset(&newmask);
215 SET_THREAD_SIGMASK(SIG_BLOCK, &newmask, &oldmask);
217 success = pthread_create(&th,
218 #if defined(PY_PTHREAD_D4)
219 pthread_attr_default,
220 (pthread_startroutine_t)func,
221 (pthread_addr_t)arg
222 #elif defined(PY_PTHREAD_D6)
223 pthread_attr_default,
224 (void* (*)(void *))func,
226 #elif defined(PY_PTHREAD_D7)
227 pthread_attr_default,
228 func,
230 #elif defined(PY_PTHREAD_STD)
231 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
232 &attrs,
233 #else
234 (pthread_attr_t*)NULL,
235 #endif
236 (void* (*)(void *))func,
237 (void *)arg
238 #endif
241 /* Restore signal mask for original thread */
242 SET_THREAD_SIGMASK(SIG_SETMASK, &oldmask, NULL);
244 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
245 pthread_attr_destroy(&attrs);
246 #endif
247 if (success == 0) {
248 #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
249 pthread_detach(&th);
250 #elif defined(PY_PTHREAD_STD)
251 pthread_detach(th);
252 #endif
254 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
255 return (long) th;
256 #else
257 return (long) *(long *) &th;
258 #endif
261 /* XXX This implementation is considered (to quote Tim Peters) "inherently
262 hosed" because:
263 - It does not guanrantee the promise that a non-zero integer is returned.
264 - The cast to long is inherently unsafe.
265 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
266 latter return statement (for Alpha OSF/1) are any longer necessary.
268 long
269 PyThread_get_thread_ident(void)
271 volatile pthread_t threadid;
272 if (!initialized)
273 PyThread_init_thread();
274 /* Jump through some hoops for Alpha OSF/1 */
275 threadid = pthread_self();
276 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
277 return (long) threadid;
278 #else
279 return (long) *(long *) &threadid;
280 #endif
283 static void
284 do_PyThread_exit_thread(int no_cleanup)
286 dprintf(("PyThread_exit_thread called\n"));
287 if (!initialized) {
288 if (no_cleanup)
289 _exit(0);
290 else
291 exit(0);
295 void
296 PyThread_exit_thread(void)
298 do_PyThread_exit_thread(0);
301 void
302 PyThread__exit_thread(void)
304 do_PyThread_exit_thread(1);
307 #ifndef NO_EXIT_PROG
308 static void
309 do_PyThread_exit_prog(int status, int no_cleanup)
311 dprintf(("PyThread_exit_prog(%d) called\n", status));
312 if (!initialized)
313 if (no_cleanup)
314 _exit(status);
315 else
316 exit(status);
319 void
320 PyThread_exit_prog(int status)
322 do_PyThread_exit_prog(status, 0);
325 void
326 PyThread__exit_prog(int status)
328 do_PyThread_exit_prog(status, 1);
330 #endif /* NO_EXIT_PROG */
332 #ifdef USE_SEMAPHORES
335 * Lock support.
338 PyThread_type_lock
339 PyThread_allocate_lock(void)
341 sem_t *lock;
342 int status, error = 0;
344 dprintf(("PyThread_allocate_lock called\n"));
345 if (!initialized)
346 PyThread_init_thread();
348 lock = (sem_t *)malloc(sizeof(sem_t));
350 if (lock) {
351 status = sem_init(lock,0,1);
352 CHECK_STATUS("sem_init");
354 if (error) {
355 free((void *)lock);
356 lock = NULL;
360 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
361 return (PyThread_type_lock)lock;
364 void
365 PyThread_free_lock(PyThread_type_lock lock)
367 sem_t *thelock = (sem_t *)lock;
368 int status, error = 0;
370 dprintf(("PyThread_free_lock(%p) called\n", lock));
372 if (!thelock)
373 return;
375 status = sem_destroy(thelock);
376 CHECK_STATUS("sem_destroy");
378 free((void *)thelock);
382 * As of February 2002, Cygwin thread implementations mistakenly report error
383 * codes in the return value of the sem_ calls (like the pthread_ functions).
384 * Correct implementations return -1 and put the code in errno. This supports
385 * either.
387 static int
388 fix_status(int status)
390 return (status == -1) ? errno : status;
393 int
394 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
396 int success;
397 sem_t *thelock = (sem_t *)lock;
398 int status, error = 0;
400 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
402 do {
403 if (waitflag)
404 status = fix_status(sem_wait(thelock));
405 else
406 status = fix_status(sem_trywait(thelock));
407 } while (status == EINTR); /* Retry if interrupted by a signal */
409 if (waitflag) {
410 CHECK_STATUS("sem_wait");
411 } else if (status != EAGAIN) {
412 CHECK_STATUS("sem_trywait");
415 success = (status == 0) ? 1 : 0;
417 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
418 return success;
421 void
422 PyThread_release_lock(PyThread_type_lock lock)
424 sem_t *thelock = (sem_t *)lock;
425 int status, error = 0;
427 dprintf(("PyThread_release_lock(%p) called\n", lock));
429 status = sem_post(thelock);
430 CHECK_STATUS("sem_post");
433 #else /* USE_SEMAPHORES */
436 * Lock support.
438 PyThread_type_lock
439 PyThread_allocate_lock(void)
441 pthread_lock *lock;
442 int status, error = 0;
444 dprintf(("PyThread_allocate_lock called\n"));
445 if (!initialized)
446 PyThread_init_thread();
448 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
449 memset((void *)lock, '\0', sizeof(pthread_lock));
450 if (lock) {
451 lock->locked = 0;
453 status = pthread_mutex_init(&lock->mut,
454 pthread_mutexattr_default);
455 CHECK_STATUS("pthread_mutex_init");
457 status = pthread_cond_init(&lock->lock_released,
458 pthread_condattr_default);
459 CHECK_STATUS("pthread_cond_init");
461 if (error) {
462 free((void *)lock);
463 lock = 0;
467 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
468 return (PyThread_type_lock) lock;
471 void
472 PyThread_free_lock(PyThread_type_lock lock)
474 pthread_lock *thelock = (pthread_lock *)lock;
475 int status, error = 0;
477 dprintf(("PyThread_free_lock(%p) called\n", lock));
479 status = pthread_mutex_destroy( &thelock->mut );
480 CHECK_STATUS("pthread_mutex_destroy");
482 status = pthread_cond_destroy( &thelock->lock_released );
483 CHECK_STATUS("pthread_cond_destroy");
485 free((void *)thelock);
488 int
489 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
491 int success;
492 pthread_lock *thelock = (pthread_lock *)lock;
493 int status, error = 0;
495 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
497 status = pthread_mutex_lock( &thelock->mut );
498 CHECK_STATUS("pthread_mutex_lock[1]");
499 success = thelock->locked == 0;
500 if (success) thelock->locked = 1;
501 status = pthread_mutex_unlock( &thelock->mut );
502 CHECK_STATUS("pthread_mutex_unlock[1]");
504 if ( !success && waitflag ) {
505 /* continue trying until we get the lock */
507 /* mut must be locked by me -- part of the condition
508 * protocol */
509 status = pthread_mutex_lock( &thelock->mut );
510 CHECK_STATUS("pthread_mutex_lock[2]");
511 while ( thelock->locked ) {
512 status = pthread_cond_wait(&thelock->lock_released,
513 &thelock->mut);
514 CHECK_STATUS("pthread_cond_wait");
516 thelock->locked = 1;
517 status = pthread_mutex_unlock( &thelock->mut );
518 CHECK_STATUS("pthread_mutex_unlock[2]");
519 success = 1;
521 if (error) success = 0;
522 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
523 return success;
526 void
527 PyThread_release_lock(PyThread_type_lock lock)
529 pthread_lock *thelock = (pthread_lock *)lock;
530 int status, error = 0;
532 dprintf(("PyThread_release_lock(%p) called\n", lock));
534 status = pthread_mutex_lock( &thelock->mut );
535 CHECK_STATUS("pthread_mutex_lock[3]");
537 thelock->locked = 0;
539 status = pthread_mutex_unlock( &thelock->mut );
540 CHECK_STATUS("pthread_mutex_unlock[3]");
542 /* wake up someone (anyone, if any) waiting on the lock */
543 status = pthread_cond_signal( &thelock->lock_released );
544 CHECK_STATUS("pthread_cond_signal");
547 #endif /* USE_SEMAPHORES */