blob: 517def50771897cd7939bcc1626daa3d3fcfce86 [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000029
30******************************************************************/
31
Guido van Rossum66020991996-06-11 18:32:18 +000032/* Posix threads interface */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000033
Guido van Rossum66020991996-06-11 18:32:18 +000034#include <stdlib.h>
35#include <pthread.h>
36
Guido van Rossum1a623111996-08-08 18:53:41 +000037
Guido van Rossumd6353e21997-05-13 17:51:13 +000038/* try to determine what version of the Pthread Standard is installed.
39 * this is important, since all sorts of parameter types changed from
40 * draft to draft and there are several (incompatible) drafts in
41 * common use. these macros are a start, at least.
42 * 12 May 1997 -- david arnold <davida@pobox.com>
43 */
44
45#if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
46/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
47# define PY_PTHREAD_D4
48
49#elif defined(__osf__) && defined (__alpha)
50/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
51# if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
52# define PY_PTHREAD_D4
53# else
54# define PY_PTHREAD_STD
55# endif
56
57#elif defined(_AIX)
Guido van Rossum1a623111996-08-08 18:53:41 +000058/* SCHED_BG_NP is defined if using AIX DCE pthreads
59 * but it is unsupported by AIX 4 pthreads. Default
60 * attributes for AIX 4 pthreads equal to NULL. For
61 * AIX DCE pthreads they should be left unchanged.
62 */
Guido van Rossumd6353e21997-05-13 17:51:13 +000063# if !defined(SCHED_BG_NP)
64# define PY_PTHREAD_STD
65# else
66# define PY_PTHREAD_D7
67# endif
68
69#elif defined(__unix) && defined(__sparc)
70# define PY_PTHREAD_STD
Guido van Rossumc8fba8e1997-05-15 12:24:53 +000071#elif defined(__linux)
72# define PY_PTHREAD_STD
Guido van Rossumd6353e21997-05-13 17:51:13 +000073
Guido van Rossum1a623111996-08-08 18:53:41 +000074#endif
75
Guido van Rossumd6353e21997-05-13 17:51:13 +000076
77/* set default attribute object for different versions */
78
79#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
80# define pthread_attr_default pthread_attr_default
81# define pthread_mutexattr_default pthread_mutexattr_default
82# define pthread_condattr_default pthread_condattr_default
83#elif defined(PY_PTHREAD_STD)
84# define pthread_attr_default ((pthread_attr_t *)NULL)
85# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
86# define pthread_condattr_default ((pthread_condattr_t *)NULL)
Guido van Rossum1a623111996-08-08 18:53:41 +000087#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000088
Guido van Rossumd6353e21997-05-13 17:51:13 +000089
Guido van Rossumb98b1b31994-05-11 08:42:04 +000090/* A pthread mutex isn't sufficient to model the Python lock type
91 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
92 * following are undefined:
93 * -> a thread tries to lock a mutex it already has locked
94 * -> a thread tries to unlock a mutex locked by a different thread
95 * pthread mutexes are designed for serializing threads over short pieces
96 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000097 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000098 *
99 * The pthread_lock struct implements a Python lock as a "locked?" bit
100 * and a <condition, mutex> pair. In general, if the bit can be acquired
101 * instantly, it is, else the pair is used to block the thread until the
102 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000103 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000104
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000105typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000106 char locked; /* 0=unlocked, 1=locked */
107 /* a <cond, mutex> pair to handle an acquire of a locked lock */
108 pthread_cond_t lock_released;
109 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000110} pthread_lock;
111
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000112#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
113
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000114/*
115 * Initialization.
116 */
117static void _init_thread _P0()
118{
119}
120
121/*
122 * Thread support.
123 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000124
125
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000126int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
127{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000128 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +0000129 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000130 dprintf(("start_new_thread called\n"));
131 if (!initialized)
132 init_thread();
Guido van Rossumd6353e21997-05-13 17:51:13 +0000133
134 success = pthread_create(&th,
135#if defined(PY_PTHREAD_D4)
136 pthread_attr_default,
137 (pthread_startroutine_t)func,
138 (pthread_addr_t)arg
139#elif defined(PY_PTHREAD_D7)
140 pthread_attr_default,
141 func,
142 arg
143#elif defined(PY_PTHREAD_STD)
144 (pthread_attr_t*)NULL,
145 (void* (*)_P((void *)))func,
146 (void *)arg
147#endif
148 );
149
150 if (success >= 0) {
151#if defined(PY_THREAD_D4) || defined(PY_PTHREAD_D7)
152 pthread_detach(&th);
153#elif defined(PY_PTHREAD_STD)
Guido van Rossumf4806c21997-04-30 19:59:22 +0000154 pthread_detach(th);
Guido van Rossumd6353e21997-05-13 17:51:13 +0000155#endif
156 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000157 return success < 0 ? 0 : 1;
158}
159
Guido van Rossume944da81994-05-23 12:43:41 +0000160long get_thread_ident _P0()
161{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000162 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000163 if (!initialized)
164 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000165 /* Jump through some hoops for Alpha OSF/1 */
166 threadid = pthread_self();
167 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000168}
169
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000170static void do_exit_thread _P1(no_cleanup, int no_cleanup)
171{
172 dprintf(("exit_thread called\n"));
173 if (!initialized)
174 if (no_cleanup)
175 _exit(0);
176 else
177 exit(0);
178}
179
180void exit_thread _P0()
181{
182 do_exit_thread(0);
183}
184
185void _exit_thread _P0()
186{
187 do_exit_thread(1);
188}
189
190#ifndef NO_EXIT_PROG
191static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
192{
193 dprintf(("exit_prog(%d) called\n", status));
194 if (!initialized)
195 if (no_cleanup)
196 _exit(status);
197 else
198 exit(status);
199}
200
201void exit_prog _P1(status, int status)
202{
203 do_exit_prog(status, 0);
204}
205
206void _exit_prog _P1(status, int status)
207{
208 do_exit_prog(status, 1);
209}
210#endif /* NO_EXIT_PROG */
211
212/*
213 * Lock support.
214 */
215type_lock allocate_lock _P0()
216{
217 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000218 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000219
220 dprintf(("allocate_lock called\n"));
221 if (!initialized)
222 init_thread();
223
224 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000225 if (lock) {
226 lock->locked = 0;
227
228 status = pthread_mutex_init(&lock->mut,
229 pthread_mutexattr_default);
230 CHECK_STATUS("pthread_mutex_init");
231
232 status = pthread_cond_init(&lock->lock_released,
233 pthread_condattr_default);
234 CHECK_STATUS("pthread_cond_init");
235
236 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000237 free((void *)lock);
238 lock = 0;
239 }
240 }
241
242 dprintf(("allocate_lock() -> %lx\n", (long)lock));
243 return (type_lock) lock;
244}
245
246void free_lock _P1(lock, type_lock lock)
247{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000248 pthread_lock *thelock = (pthread_lock *)lock;
249 int status, error = 0;
250
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000251 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000252
253 status = pthread_mutex_destroy( &thelock->mut );
254 CHECK_STATUS("pthread_mutex_destroy");
255
256 status = pthread_cond_destroy( &thelock->lock_released );
257 CHECK_STATUS("pthread_cond_destroy");
258
259 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000260}
261
262int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
263{
264 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000265 pthread_lock *thelock = (pthread_lock *)lock;
266 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000267
268 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000269
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000270 status = pthread_mutex_lock( &thelock->mut );
271 CHECK_STATUS("pthread_mutex_lock[1]");
272 success = thelock->locked == 0;
273 if (success) thelock->locked = 1;
274 status = pthread_mutex_unlock( &thelock->mut );
275 CHECK_STATUS("pthread_mutex_unlock[1]");
276
277 if ( !success && waitflag ) {
278 /* continue trying until we get the lock */
279
280 /* mut must be locked by me -- part of the condition
281 * protocol */
282 status = pthread_mutex_lock( &thelock->mut );
283 CHECK_STATUS("pthread_mutex_lock[2]");
284 while ( thelock->locked ) {
285 status = pthread_cond_wait(&thelock->lock_released,
286 &thelock->mut);
287 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000288 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000289 thelock->locked = 1;
290 status = pthread_mutex_unlock( &thelock->mut );
291 CHECK_STATUS("pthread_mutex_unlock[2]");
292 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000293 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000294 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000295 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
296 return success;
297}
298
299void release_lock _P1(lock, type_lock lock)
300{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000301 pthread_lock *thelock = (pthread_lock *)lock;
302 int status, error = 0;
303
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000304 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000305
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000306 status = pthread_mutex_lock( &thelock->mut );
307 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000308
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000309 thelock->locked = 0;
310
311 status = pthread_mutex_unlock( &thelock->mut );
312 CHECK_STATUS("pthread_mutex_unlock[3]");
313
314 /* wake up someone (anyone, if any) waiting on the lock */
315 status = pthread_cond_signal( &thelock->lock_released );
316 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000317}
318
319/*
320 * Semaphore support.
321 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000322
323struct semaphore {
324 pthread_mutex_t mutex;
325 pthread_cond_t cond;
326 int value;
327};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000328
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000329type_sema allocate_sema _P1(value, int value)
330{
Guido van Rossum7af81301997-01-17 21:06:41 +0000331 struct semaphore *sema;
332 int status, error = 0;
333
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000334 dprintf(("allocate_sema called\n"));
335 if (!initialized)
336 init_thread();
337
Guido van Rossum7af81301997-01-17 21:06:41 +0000338 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
339 if (sema != NULL) {
340 sema->value = value;
341 status = pthread_mutex_init(&sema->mutex,
342 pthread_mutexattr_default);
343 CHECK_STATUS("pthread_mutex_init");
344 status = pthread_cond_init(&sema->cond,
345 pthread_condattr_default);
346 CHECK_STATUS("pthread_cond_init");
347 if (error) {
348 free((void *) sema);
349 sema = NULL;
350 }
351 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000352 dprintf(("allocate_sema() -> %lx\n", (long) sema));
353 return (type_sema) sema;
354}
355
356void free_sema _P1(sema, type_sema sema)
357{
Guido van Rossum7af81301997-01-17 21:06:41 +0000358 int status, error = 0;
359 struct semaphore *thesema = (struct semaphore *) sema;
360
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000361 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000362 status = pthread_cond_destroy(&thesema->cond);
363 CHECK_STATUS("pthread_cond_destroy");
364 status = pthread_mutex_destroy(&thesema->mutex);
365 CHECK_STATUS("pthread_mutex_destroy");
366 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000367}
368
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000369int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000370{
Guido van Rossum7af81301997-01-17 21:06:41 +0000371 int status, error = 0, success;
372 struct semaphore *thesema = (struct semaphore *) sema;
373
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000374 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000375 status = pthread_mutex_lock(&thesema->mutex);
376 CHECK_STATUS("pthread_mutex_lock");
377 if (waitflag) {
378 while (!error && thesema->value <= 0) {
379 status = pthread_cond_wait(&thesema->cond,
380 &thesema->mutex);
381 CHECK_STATUS("pthread_cond_wait");
382 }
383 }
384 if (error)
385 success = 0;
386 else if (thesema->value > 0) {
387 thesema->value--;
388 success = 1;
389 }
390 else
391 success = 0;
392 status = pthread_mutex_unlock(&thesema->mutex);
393 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000394 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000395 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000396}
397
398void up_sema _P1(sema, type_sema sema)
399{
Guido van Rossum7af81301997-01-17 21:06:41 +0000400 int status, error = 0;
401 struct semaphore *thesema = (struct semaphore *) sema;
402
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000403 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000404 status = pthread_mutex_lock(&thesema->mutex);
405 CHECK_STATUS("pthread_mutex_lock");
406 thesema->value++;
407 status = pthread_cond_signal(&thesema->cond);
408 CHECK_STATUS("pthread_cond_signal");
409 status = pthread_mutex_unlock(&thesema->mutex);
410 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000411}