Update version number and release date.
[python/dscho.git] / Python / thread_pthread.h
blob2e594fe922e16a679a74f217418105fd4feb76c8
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 status;
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 status = 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 (status != 0)
248 return -1;
250 #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
251 pthread_detach(&th);
252 #elif defined(PY_PTHREAD_STD)
253 pthread_detach(th);
254 #endif
256 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
257 return (long) th;
258 #else
259 return (long) *(long *) &th;
260 #endif
263 /* XXX This implementation is considered (to quote Tim Peters) "inherently
264 hosed" because:
265 - It does not guanrantee the promise that a non-zero integer is returned.
266 - The cast to long is inherently unsafe.
267 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
268 latter return statement (for Alpha OSF/1) are any longer necessary.
270 long
271 PyThread_get_thread_ident(void)
273 volatile pthread_t threadid;
274 if (!initialized)
275 PyThread_init_thread();
276 /* Jump through some hoops for Alpha OSF/1 */
277 threadid = pthread_self();
278 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
279 return (long) threadid;
280 #else
281 return (long) *(long *) &threadid;
282 #endif
285 static void
286 do_PyThread_exit_thread(int no_cleanup)
288 dprintf(("PyThread_exit_thread called\n"));
289 if (!initialized) {
290 if (no_cleanup)
291 _exit(0);
292 else
293 exit(0);
297 void
298 PyThread_exit_thread(void)
300 do_PyThread_exit_thread(0);
303 void
304 PyThread__exit_thread(void)
306 do_PyThread_exit_thread(1);
309 #ifndef NO_EXIT_PROG
310 static void
311 do_PyThread_exit_prog(int status, int no_cleanup)
313 dprintf(("PyThread_exit_prog(%d) called\n", status));
314 if (!initialized)
315 if (no_cleanup)
316 _exit(status);
317 else
318 exit(status);
321 void
322 PyThread_exit_prog(int status)
324 do_PyThread_exit_prog(status, 0);
327 void
328 PyThread__exit_prog(int status)
330 do_PyThread_exit_prog(status, 1);
332 #endif /* NO_EXIT_PROG */
334 #ifdef USE_SEMAPHORES
337 * Lock support.
340 PyThread_type_lock
341 PyThread_allocate_lock(void)
343 sem_t *lock;
344 int status, error = 0;
346 dprintf(("PyThread_allocate_lock called\n"));
347 if (!initialized)
348 PyThread_init_thread();
350 lock = (sem_t *)malloc(sizeof(sem_t));
352 if (lock) {
353 status = sem_init(lock,0,1);
354 CHECK_STATUS("sem_init");
356 if (error) {
357 free((void *)lock);
358 lock = NULL;
362 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
363 return (PyThread_type_lock)lock;
366 void
367 PyThread_free_lock(PyThread_type_lock lock)
369 sem_t *thelock = (sem_t *)lock;
370 int status, error = 0;
372 dprintf(("PyThread_free_lock(%p) called\n", lock));
374 if (!thelock)
375 return;
377 status = sem_destroy(thelock);
378 CHECK_STATUS("sem_destroy");
380 free((void *)thelock);
384 * As of February 2002, Cygwin thread implementations mistakenly report error
385 * codes in the return value of the sem_ calls (like the pthread_ functions).
386 * Correct implementations return -1 and put the code in errno. This supports
387 * either.
389 static int
390 fix_status(int status)
392 return (status == -1) ? errno : status;
395 int
396 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
398 int success;
399 sem_t *thelock = (sem_t *)lock;
400 int status, error = 0;
402 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
404 do {
405 if (waitflag)
406 status = fix_status(sem_wait(thelock));
407 else
408 status = fix_status(sem_trywait(thelock));
409 } while (status == EINTR); /* Retry if interrupted by a signal */
411 if (waitflag) {
412 CHECK_STATUS("sem_wait");
413 } else if (status != EAGAIN) {
414 CHECK_STATUS("sem_trywait");
417 success = (status == 0) ? 1 : 0;
419 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
420 return success;
423 void
424 PyThread_release_lock(PyThread_type_lock lock)
426 sem_t *thelock = (sem_t *)lock;
427 int status, error = 0;
429 dprintf(("PyThread_release_lock(%p) called\n", lock));
431 status = sem_post(thelock);
432 CHECK_STATUS("sem_post");
435 #else /* USE_SEMAPHORES */
438 * Lock support.
440 PyThread_type_lock
441 PyThread_allocate_lock(void)
443 pthread_lock *lock;
444 int status, error = 0;
446 dprintf(("PyThread_allocate_lock called\n"));
447 if (!initialized)
448 PyThread_init_thread();
450 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
451 memset((void *)lock, '\0', sizeof(pthread_lock));
452 if (lock) {
453 lock->locked = 0;
455 status = pthread_mutex_init(&lock->mut,
456 pthread_mutexattr_default);
457 CHECK_STATUS("pthread_mutex_init");
459 status = pthread_cond_init(&lock->lock_released,
460 pthread_condattr_default);
461 CHECK_STATUS("pthread_cond_init");
463 if (error) {
464 free((void *)lock);
465 lock = 0;
469 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
470 return (PyThread_type_lock) lock;
473 void
474 PyThread_free_lock(PyThread_type_lock lock)
476 pthread_lock *thelock = (pthread_lock *)lock;
477 int status, error = 0;
479 dprintf(("PyThread_free_lock(%p) called\n", lock));
481 status = pthread_mutex_destroy( &thelock->mut );
482 CHECK_STATUS("pthread_mutex_destroy");
484 status = pthread_cond_destroy( &thelock->lock_released );
485 CHECK_STATUS("pthread_cond_destroy");
487 free((void *)thelock);
490 int
491 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
493 int success;
494 pthread_lock *thelock = (pthread_lock *)lock;
495 int status, error = 0;
497 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
499 status = pthread_mutex_lock( &thelock->mut );
500 CHECK_STATUS("pthread_mutex_lock[1]");
501 success = thelock->locked == 0;
503 if ( !success && waitflag ) {
504 /* continue trying until we get the lock */
506 /* mut must be locked by me -- part of the condition
507 * protocol */
508 while ( thelock->locked ) {
509 status = pthread_cond_wait(&thelock->lock_released,
510 &thelock->mut);
511 CHECK_STATUS("pthread_cond_wait");
513 success = 1;
515 if (success) thelock->locked = 1;
516 status = pthread_mutex_unlock( &thelock->mut );
517 CHECK_STATUS("pthread_mutex_unlock[1]");
519 if (error) success = 0;
520 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
521 return success;
524 void
525 PyThread_release_lock(PyThread_type_lock lock)
527 pthread_lock *thelock = (pthread_lock *)lock;
528 int status, error = 0;
530 dprintf(("PyThread_release_lock(%p) called\n", lock));
532 status = pthread_mutex_lock( &thelock->mut );
533 CHECK_STATUS("pthread_mutex_lock[3]");
535 thelock->locked = 0;
537 status = pthread_mutex_unlock( &thelock->mut );
538 CHECK_STATUS("pthread_mutex_unlock[3]");
540 /* wake up someone (anyone, if any) waiting on the lock */
541 status = pthread_cond_signal( &thelock->lock_released );
542 CHECK_STATUS("pthread_cond_signal");
545 #endif /* USE_SEMAPHORES */