blob: 7170c8a81202d024ac0f2910ec1c0e25c90bf690 [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001
Guido van Rossum66020991996-06-11 18:32:18 +00002/* Posix threads interface */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00003
Guido van Rossum66020991996-06-11 18:32:18 +00004#include <stdlib.h>
Guido van Rossum9e46e561998-10-07 16:39:47 +00005#include <string.h>
Guido van Rossum66020991996-06-11 18:32:18 +00006#include <pthread.h>
Guido van Rossum80230992001-10-12 21:49:17 +00007#include <signal.h>
Guido van Rossum66020991996-06-11 18:32:18 +00008
Guido van Rossum1a623111996-08-08 18:53:41 +00009
Guido van Rossumd6353e21997-05-13 17:51:13 +000010/* try to determine what version of the Pthread Standard is installed.
11 * this is important, since all sorts of parameter types changed from
12 * draft to draft and there are several (incompatible) drafts in
13 * common use. these macros are a start, at least.
14 * 12 May 1997 -- david arnold <davida@pobox.com>
15 */
16
17#if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
18/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
19# define PY_PTHREAD_D4
20
21#elif defined(__osf__) && defined (__alpha)
22/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
23# if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
24# define PY_PTHREAD_D4
25# else
26# define PY_PTHREAD_STD
27# endif
28
29#elif defined(_AIX)
Guido van Rossum1a623111996-08-08 18:53:41 +000030/* SCHED_BG_NP is defined if using AIX DCE pthreads
31 * but it is unsupported by AIX 4 pthreads. Default
32 * attributes for AIX 4 pthreads equal to NULL. For
33 * AIX DCE pthreads they should be left unchanged.
34 */
Guido van Rossumd6353e21997-05-13 17:51:13 +000035# if !defined(SCHED_BG_NP)
36# define PY_PTHREAD_STD
37# else
38# define PY_PTHREAD_D7
39# endif
40
Guido van Rossum64f91051997-05-22 20:41:59 +000041#elif defined(__DGUX)
42# define PY_PTHREAD_D6
Guido van Rossum46ff1901997-06-02 22:25:45 +000043
Guido van Rossum532246e1998-05-14 21:01:27 +000044#elif defined(__hpux) && defined(_DECTHREADS_)
Guido van Rossum89df70b1998-05-07 13:28:23 +000045# define PY_PTHREAD_D4
46
Guido van Rossum46ff1901997-06-02 22:25:45 +000047#else /* Default case */
48# define PY_PTHREAD_STD
49
Guido van Rossum1a623111996-08-08 18:53:41 +000050#endif
51
Jack Jansenc51395d2001-08-29 15:24:53 +000052#ifdef USE_GUSI
53/* The Macintosh GUSI I/O library sets the stackspace to
54** 20KB, much too low. We up it to 64K.
55*/
56#define THREAD_STACK_SIZE 0x10000
57#endif
58
Guido van Rossumd6353e21997-05-13 17:51:13 +000059
60/* set default attribute object for different versions */
61
62#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
63# define pthread_attr_default pthread_attr_default
64# define pthread_mutexattr_default pthread_mutexattr_default
65# define pthread_condattr_default pthread_condattr_default
Guido van Rossum64f91051997-05-22 20:41:59 +000066#elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
Guido van Rossumd6353e21997-05-13 17:51:13 +000067# define pthread_attr_default ((pthread_attr_t *)NULL)
68# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
69# define pthread_condattr_default ((pthread_condattr_t *)NULL)
Guido van Rossum1a623111996-08-08 18:53:41 +000070#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000071
Guido van Rossumd6353e21997-05-13 17:51:13 +000072
Guido van Rossum80230992001-10-12 21:49:17 +000073/* On platforms that don't use standard POSIX threads pthread_sigmask()
74 * isn't present. DEC threads uses sigprocmask() instead as do most
75 * other UNIX International compliant systems that don't have the full
76 * pthread implementation.
77 */
Martin v. Löwis69c0ff32001-10-15 14:34:42 +000078#ifdef HAVE_PTHREAD_SIGMASK
Guido van Rossum80230992001-10-12 21:49:17 +000079# define SET_THREAD_SIGMASK pthread_sigmask
80#else
81# define SET_THREAD_SIGMASK sigprocmask
82#endif
83
84
Guido van Rossumb98b1b31994-05-11 08:42:04 +000085/* A pthread mutex isn't sufficient to model the Python lock type
86 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
87 * following are undefined:
88 * -> a thread tries to lock a mutex it already has locked
89 * -> a thread tries to unlock a mutex locked by a different thread
90 * pthread mutexes are designed for serializing threads over short pieces
91 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000092 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000093 *
94 * The pthread_lock struct implements a Python lock as a "locked?" bit
95 * and a <condition, mutex> pair. In general, if the bit can be acquired
96 * instantly, it is, else the pair is used to block the thread until the
97 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000098 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000099
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000100typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000101 char locked; /* 0=unlocked, 1=locked */
102 /* a <cond, mutex> pair to handle an acquire of a locked lock */
103 pthread_cond_t lock_released;
104 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000105} pthread_lock;
106
Guido van Rossum9e46e561998-10-07 16:39:47 +0000107#define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000108
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000109/*
110 * Initialization.
111 */
Guido van Rossum9e46e561998-10-07 16:39:47 +0000112
113#ifdef _HAVE_BSDI
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000114static
115void _noop(void)
Guido van Rossum9e46e561998-10-07 16:39:47 +0000116{
117}
118
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000119static void
120PyThread__init_thread(void)
Guido van Rossum9e46e561998-10-07 16:39:47 +0000121{
122 /* DO AN INIT BY STARTING THE THREAD */
123 static int dummy = 0;
124 pthread_t thread1;
125 pthread_create(&thread1, NULL, (void *) _noop, &dummy);
126 pthread_join(thread1, NULL);
127}
128
129#else /* !_HAVE_BSDI */
130
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000131static void
132PyThread__init_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000133{
Guido van Rossumd21744a1998-09-10 03:04:40 +0000134#if defined(_AIX) && defined(__GNUC__)
135 pthread_init();
136#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000137}
138
Guido van Rossum9e46e561998-10-07 16:39:47 +0000139#endif /* !_HAVE_BSDI */
140
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000141/*
142 * Thread support.
143 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000144
145
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000146int
147PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000148{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000149 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +0000150 int success;
Guido van Rossum80230992001-10-12 21:49:17 +0000151 sigset_t oldmask, newmask;
Guido van Rossumd0b69ec2001-09-10 14:10:54 +0000152#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
Jack Jansenc51395d2001-08-29 15:24:53 +0000153 pthread_attr_t attrs;
154#endif
Guido van Rossum65d5b571998-12-21 19:32:43 +0000155 dprintf(("PyThread_start_new_thread called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000156 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000157 PyThread_init_thread();
Guido van Rossumd6353e21997-05-13 17:51:13 +0000158
Guido van Rossumd0b69ec2001-09-10 14:10:54 +0000159#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
Jack Jansenc51395d2001-08-29 15:24:53 +0000160 pthread_attr_init(&attrs);
Guido van Rossumd0b69ec2001-09-10 14:10:54 +0000161#endif
162#ifdef THREAD_STACK_SIZE
Jack Jansenc51395d2001-08-29 15:24:53 +0000163 pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
164#endif
Guido van Rossumd0b69ec2001-09-10 14:10:54 +0000165#ifdef PTHREAD_SYSTEM_SCHED_SUPPORTED
166 pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
167#endif
Guido van Rossum80230992001-10-12 21:49:17 +0000168
169 /* Mask all signals in the current thread before creating the new
170 * thread. This causes the new thread to start with all signals
171 * blocked.
172 */
173 sigfillset(&newmask);
174 SET_THREAD_SIGMASK(SIG_BLOCK, &newmask, &oldmask);
175
Guido van Rossumd6353e21997-05-13 17:51:13 +0000176 success = pthread_create(&th,
177#if defined(PY_PTHREAD_D4)
178 pthread_attr_default,
179 (pthread_startroutine_t)func,
180 (pthread_addr_t)arg
Guido van Rossum64f91051997-05-22 20:41:59 +0000181#elif defined(PY_PTHREAD_D6)
182 pthread_attr_default,
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000183 (void* (*)(void *))func,
Guido van Rossum64f91051997-05-22 20:41:59 +0000184 arg
Guido van Rossumd6353e21997-05-13 17:51:13 +0000185#elif defined(PY_PTHREAD_D7)
186 pthread_attr_default,
187 func,
188 arg
189#elif defined(PY_PTHREAD_STD)
Guido van Rossumd0b69ec2001-09-10 14:10:54 +0000190#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
Jack Jansenc51395d2001-08-29 15:24:53 +0000191 &attrs,
192#else
Guido van Rossumd6353e21997-05-13 17:51:13 +0000193 (pthread_attr_t*)NULL,
Jack Jansenc51395d2001-08-29 15:24:53 +0000194#endif
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000195 (void* (*)(void *))func,
Guido van Rossumd6353e21997-05-13 17:51:13 +0000196 (void *)arg
197#endif
198 );
Guido van Rossum80230992001-10-12 21:49:17 +0000199
200 /* Restore signal mask for original thread */
201 SET_THREAD_SIGMASK(SIG_SETMASK, &oldmask, NULL);
202
Jack Jansenc51395d2001-08-29 15:24:53 +0000203#ifdef THREAD_STACK_SIZE
204 pthread_attr_destroy(&attrs);
205#endif
Guido van Rossum701f25e1999-03-15 20:27:53 +0000206 if (success == 0) {
Guido van Rossuma74d0e41998-09-04 13:38:32 +0000207#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
Guido van Rossumd6353e21997-05-13 17:51:13 +0000208 pthread_detach(&th);
209#elif defined(PY_PTHREAD_STD)
Guido van Rossumf4806c21997-04-30 19:59:22 +0000210 pthread_detach(th);
Guido van Rossumd6353e21997-05-13 17:51:13 +0000211#endif
212 }
Guido van Rossum701f25e1999-03-15 20:27:53 +0000213 return success != 0 ? 0 : 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000214}
215
Trent Mick635f6fb2000-08-23 21:33:05 +0000216/* XXX This implementation is considered (to quote Tim Peters) "inherently
217 hosed" because:
218 - It does not guanrantee the promise that a non-zero integer is returned.
219 - The cast to long is inherently unsafe.
220 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
221 latter return statement (for Alpha OSF/1) are any longer necessary.
222*/
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000223long
224PyThread_get_thread_ident(void)
Guido van Rossume944da81994-05-23 12:43:41 +0000225{
Guido van Rossum44ee4791998-08-27 19:21:53 +0000226 volatile pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000227 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000228 PyThread_init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000229 /* Jump through some hoops for Alpha OSF/1 */
230 threadid = pthread_self();
Trent Mick635f6fb2000-08-23 21:33:05 +0000231#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
232 return (long) threadid;
233#else
Guido van Rossum2565bff1995-01-09 17:50:47 +0000234 return (long) *(long *) &threadid;
Trent Mick635f6fb2000-08-23 21:33:05 +0000235#endif
Guido van Rossume944da81994-05-23 12:43:41 +0000236}
237
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000238static void
239do_PyThread_exit_thread(int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000240{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000241 dprintf(("PyThread_exit_thread called\n"));
Guido van Rossum730806d1998-04-10 22:27:42 +0000242 if (!initialized) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000243 if (no_cleanup)
244 _exit(0);
245 else
246 exit(0);
Guido van Rossum730806d1998-04-10 22:27:42 +0000247 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000248}
249
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000250void
251PyThread_exit_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000252{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000253 do_PyThread_exit_thread(0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000254}
255
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000256void
257PyThread__exit_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000258{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000259 do_PyThread_exit_thread(1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000260}
261
262#ifndef NO_EXIT_PROG
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000263static void
264do_PyThread_exit_prog(int status, int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000265{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000266 dprintf(("PyThread_exit_prog(%d) called\n", status));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000267 if (!initialized)
268 if (no_cleanup)
269 _exit(status);
270 else
271 exit(status);
272}
273
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000274void
275PyThread_exit_prog(int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000276{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000277 do_PyThread_exit_prog(status, 0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000278}
279
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000280void
281PyThread__exit_prog(int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000282{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000283 do_PyThread_exit_prog(status, 1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000284}
285#endif /* NO_EXIT_PROG */
286
287/*
288 * Lock support.
289 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000290PyThread_type_lock
291PyThread_allocate_lock(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000292{
293 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000294 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000295
Guido van Rossum65d5b571998-12-21 19:32:43 +0000296 dprintf(("PyThread_allocate_lock called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000297 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000298 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000299
300 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossum9e46e561998-10-07 16:39:47 +0000301 memset((void *)lock, '\0', sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000302 if (lock) {
303 lock->locked = 0;
304
305 status = pthread_mutex_init(&lock->mut,
306 pthread_mutexattr_default);
307 CHECK_STATUS("pthread_mutex_init");
308
309 status = pthread_cond_init(&lock->lock_released,
310 pthread_condattr_default);
311 CHECK_STATUS("pthread_cond_init");
312
313 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000314 free((void *)lock);
315 lock = 0;
316 }
317 }
318
Fred Drakea44d3532000-06-30 15:01:00 +0000319 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum65d5b571998-12-21 19:32:43 +0000320 return (PyThread_type_lock) lock;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000321}
322
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000323void
324PyThread_free_lock(PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000325{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000326 pthread_lock *thelock = (pthread_lock *)lock;
327 int status, error = 0;
328
Fred Drakea44d3532000-06-30 15:01:00 +0000329 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000330
331 status = pthread_mutex_destroy( &thelock->mut );
332 CHECK_STATUS("pthread_mutex_destroy");
333
334 status = pthread_cond_destroy( &thelock->lock_released );
335 CHECK_STATUS("pthread_cond_destroy");
336
337 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000338}
339
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000340int
341PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000342{
343 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000344 pthread_lock *thelock = (pthread_lock *)lock;
345 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000346
Fred Drakea44d3532000-06-30 15:01:00 +0000347 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000348
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000349 status = pthread_mutex_lock( &thelock->mut );
350 CHECK_STATUS("pthread_mutex_lock[1]");
351 success = thelock->locked == 0;
352 if (success) thelock->locked = 1;
353 status = pthread_mutex_unlock( &thelock->mut );
354 CHECK_STATUS("pthread_mutex_unlock[1]");
355
356 if ( !success && waitflag ) {
357 /* continue trying until we get the lock */
358
359 /* mut must be locked by me -- part of the condition
360 * protocol */
361 status = pthread_mutex_lock( &thelock->mut );
362 CHECK_STATUS("pthread_mutex_lock[2]");
363 while ( thelock->locked ) {
364 status = pthread_cond_wait(&thelock->lock_released,
365 &thelock->mut);
366 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000367 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000368 thelock->locked = 1;
369 status = pthread_mutex_unlock( &thelock->mut );
370 CHECK_STATUS("pthread_mutex_unlock[2]");
371 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000372 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000373 if (error) success = 0;
Fred Drakea44d3532000-06-30 15:01:00 +0000374 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000375 return success;
376}
377
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000378void
379PyThread_release_lock(PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000380{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000381 pthread_lock *thelock = (pthread_lock *)lock;
382 int status, error = 0;
383
Fred Drakea44d3532000-06-30 15:01:00 +0000384 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000385
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000386 status = pthread_mutex_lock( &thelock->mut );
387 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000388
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000389 thelock->locked = 0;
390
391 status = pthread_mutex_unlock( &thelock->mut );
392 CHECK_STATUS("pthread_mutex_unlock[3]");
393
394 /* wake up someone (anyone, if any) waiting on the lock */
395 status = pthread_cond_signal( &thelock->lock_released );
396 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000397}
398
399/*
400 * Semaphore support.
401 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000402
403struct semaphore {
404 pthread_mutex_t mutex;
405 pthread_cond_t cond;
406 int value;
407};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000408
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000409PyThread_type_sema
410PyThread_allocate_sema(int value)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000411{
Guido van Rossum7af81301997-01-17 21:06:41 +0000412 struct semaphore *sema;
413 int status, error = 0;
414
Guido van Rossum65d5b571998-12-21 19:32:43 +0000415 dprintf(("PyThread_allocate_sema called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000416 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000417 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000418
Guido van Rossum7af81301997-01-17 21:06:41 +0000419 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
420 if (sema != NULL) {
421 sema->value = value;
422 status = pthread_mutex_init(&sema->mutex,
423 pthread_mutexattr_default);
424 CHECK_STATUS("pthread_mutex_init");
425 status = pthread_cond_init(&sema->cond,
426 pthread_condattr_default);
427 CHECK_STATUS("pthread_cond_init");
428 if (error) {
429 free((void *) sema);
430 sema = NULL;
431 }
432 }
Fred Drakea44d3532000-06-30 15:01:00 +0000433 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum65d5b571998-12-21 19:32:43 +0000434 return (PyThread_type_sema) sema;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000435}
436
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000437void
438PyThread_free_sema(PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000439{
Guido van Rossum7af81301997-01-17 21:06:41 +0000440 int status, error = 0;
441 struct semaphore *thesema = (struct semaphore *) sema;
442
Fred Drakea44d3532000-06-30 15:01:00 +0000443 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000444 status = pthread_cond_destroy(&thesema->cond);
445 CHECK_STATUS("pthread_cond_destroy");
446 status = pthread_mutex_destroy(&thesema->mutex);
447 CHECK_STATUS("pthread_mutex_destroy");
448 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000449}
450
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000451int
452PyThread_down_sema(PyThread_type_sema sema, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000453{
Guido van Rossum7af81301997-01-17 21:06:41 +0000454 int status, error = 0, success;
455 struct semaphore *thesema = (struct semaphore *) sema;
456
Fred Drakea44d3532000-06-30 15:01:00 +0000457 dprintf(("PyThread_down_sema(%p, %d) called\n", sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000458 status = pthread_mutex_lock(&thesema->mutex);
459 CHECK_STATUS("pthread_mutex_lock");
460 if (waitflag) {
461 while (!error && thesema->value <= 0) {
462 status = pthread_cond_wait(&thesema->cond,
463 &thesema->mutex);
464 CHECK_STATUS("pthread_cond_wait");
465 }
466 }
467 if (error)
468 success = 0;
469 else if (thesema->value > 0) {
470 thesema->value--;
471 success = 1;
472 }
473 else
474 success = 0;
475 status = pthread_mutex_unlock(&thesema->mutex);
476 CHECK_STATUS("pthread_mutex_unlock");
Fred Drakea44d3532000-06-30 15:01:00 +0000477 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000478 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000479}
480
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000481void
482PyThread_up_sema(PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000483{
Guido van Rossum7af81301997-01-17 21:06:41 +0000484 int status, error = 0;
485 struct semaphore *thesema = (struct semaphore *) sema;
486
Fred Drakea44d3532000-06-30 15:01:00 +0000487 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000488 status = pthread_mutex_lock(&thesema->mutex);
489 CHECK_STATUS("pthread_mutex_lock");
490 thesema->value++;
491 status = pthread_cond_signal(&thesema->cond);
492 CHECK_STATUS("pthread_cond_signal");
493 status = pthread_mutex_unlock(&thesema->mutex);
494 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000495}