blob: 6b97e8d14b040e0f94020135b07efe50cb5b8aaf [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
71
Guido van Rossum1a623111996-08-08 18:53:41 +000072#endif
73
Guido van Rossumd6353e21997-05-13 17:51:13 +000074
75/* set default attribute object for different versions */
76
77#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
78# define pthread_attr_default pthread_attr_default
79# define pthread_mutexattr_default pthread_mutexattr_default
80# define pthread_condattr_default pthread_condattr_default
81#elif defined(PY_PTHREAD_STD)
82# define pthread_attr_default ((pthread_attr_t *)NULL)
83# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
84# define pthread_condattr_default ((pthread_condattr_t *)NULL)
Guido van Rossum1a623111996-08-08 18:53:41 +000085#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000086
Guido van Rossumd6353e21997-05-13 17:51:13 +000087
Guido van Rossumb98b1b31994-05-11 08:42:04 +000088/* A pthread mutex isn't sufficient to model the Python lock type
89 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
90 * following are undefined:
91 * -> a thread tries to lock a mutex it already has locked
92 * -> a thread tries to unlock a mutex locked by a different thread
93 * pthread mutexes are designed for serializing threads over short pieces
94 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000095 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000096 *
97 * The pthread_lock struct implements a Python lock as a "locked?" bit
98 * and a <condition, mutex> pair. In general, if the bit can be acquired
99 * instantly, it is, else the pair is used to block the thread until the
100 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000101 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000102
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000103typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000104 char locked; /* 0=unlocked, 1=locked */
105 /* a <cond, mutex> pair to handle an acquire of a locked lock */
106 pthread_cond_t lock_released;
107 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000108} pthread_lock;
109
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000110#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
111
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000112/*
113 * Initialization.
114 */
115static void _init_thread _P0()
116{
117}
118
119/*
120 * Thread support.
121 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000122
123
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000124int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
125{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000126 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +0000127 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000128 dprintf(("start_new_thread called\n"));
129 if (!initialized)
130 init_thread();
Guido van Rossumd6353e21997-05-13 17:51:13 +0000131
132 success = pthread_create(&th,
133#if defined(PY_PTHREAD_D4)
134 pthread_attr_default,
135 (pthread_startroutine_t)func,
136 (pthread_addr_t)arg
137#elif defined(PY_PTHREAD_D7)
138 pthread_attr_default,
139 func,
140 arg
141#elif defined(PY_PTHREAD_STD)
142 (pthread_attr_t*)NULL,
143 (void* (*)_P((void *)))func,
144 (void *)arg
145#endif
146 );
147
148 if (success >= 0) {
149#if defined(PY_THREAD_D4) || defined(PY_PTHREAD_D7)
150 pthread_detach(&th);
151#elif defined(PY_PTHREAD_STD)
Guido van Rossumf4806c21997-04-30 19:59:22 +0000152 pthread_detach(th);
Guido van Rossumd6353e21997-05-13 17:51:13 +0000153#endif
154 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000155 return success < 0 ? 0 : 1;
156}
157
Guido van Rossume944da81994-05-23 12:43:41 +0000158long get_thread_ident _P0()
159{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000160 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000161 if (!initialized)
162 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000163 /* Jump through some hoops for Alpha OSF/1 */
164 threadid = pthread_self();
165 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000166}
167
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000168static void do_exit_thread _P1(no_cleanup, int no_cleanup)
169{
170 dprintf(("exit_thread called\n"));
171 if (!initialized)
172 if (no_cleanup)
173 _exit(0);
174 else
175 exit(0);
176}
177
178void exit_thread _P0()
179{
180 do_exit_thread(0);
181}
182
183void _exit_thread _P0()
184{
185 do_exit_thread(1);
186}
187
188#ifndef NO_EXIT_PROG
189static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
190{
191 dprintf(("exit_prog(%d) called\n", status));
192 if (!initialized)
193 if (no_cleanup)
194 _exit(status);
195 else
196 exit(status);
197}
198
199void exit_prog _P1(status, int status)
200{
201 do_exit_prog(status, 0);
202}
203
204void _exit_prog _P1(status, int status)
205{
206 do_exit_prog(status, 1);
207}
208#endif /* NO_EXIT_PROG */
209
210/*
211 * Lock support.
212 */
213type_lock allocate_lock _P0()
214{
215 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000216 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000217
218 dprintf(("allocate_lock called\n"));
219 if (!initialized)
220 init_thread();
221
222 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000223 if (lock) {
224 lock->locked = 0;
225
226 status = pthread_mutex_init(&lock->mut,
227 pthread_mutexattr_default);
228 CHECK_STATUS("pthread_mutex_init");
229
230 status = pthread_cond_init(&lock->lock_released,
231 pthread_condattr_default);
232 CHECK_STATUS("pthread_cond_init");
233
234 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000235 free((void *)lock);
236 lock = 0;
237 }
238 }
239
240 dprintf(("allocate_lock() -> %lx\n", (long)lock));
241 return (type_lock) lock;
242}
243
244void free_lock _P1(lock, type_lock lock)
245{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000246 pthread_lock *thelock = (pthread_lock *)lock;
247 int status, error = 0;
248
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000249 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000250
251 status = pthread_mutex_destroy( &thelock->mut );
252 CHECK_STATUS("pthread_mutex_destroy");
253
254 status = pthread_cond_destroy( &thelock->lock_released );
255 CHECK_STATUS("pthread_cond_destroy");
256
257 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000258}
259
260int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
261{
262 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000263 pthread_lock *thelock = (pthread_lock *)lock;
264 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000265
266 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000267
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000268 status = pthread_mutex_lock( &thelock->mut );
269 CHECK_STATUS("pthread_mutex_lock[1]");
270 success = thelock->locked == 0;
271 if (success) thelock->locked = 1;
272 status = pthread_mutex_unlock( &thelock->mut );
273 CHECK_STATUS("pthread_mutex_unlock[1]");
274
275 if ( !success && waitflag ) {
276 /* continue trying until we get the lock */
277
278 /* mut must be locked by me -- part of the condition
279 * protocol */
280 status = pthread_mutex_lock( &thelock->mut );
281 CHECK_STATUS("pthread_mutex_lock[2]");
282 while ( thelock->locked ) {
283 status = pthread_cond_wait(&thelock->lock_released,
284 &thelock->mut);
285 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000286 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000287 thelock->locked = 1;
288 status = pthread_mutex_unlock( &thelock->mut );
289 CHECK_STATUS("pthread_mutex_unlock[2]");
290 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000291 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000292 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000293 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
294 return success;
295}
296
297void release_lock _P1(lock, type_lock lock)
298{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000299 pthread_lock *thelock = (pthread_lock *)lock;
300 int status, error = 0;
301
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000302 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000303
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000304 status = pthread_mutex_lock( &thelock->mut );
305 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000306
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000307 thelock->locked = 0;
308
309 status = pthread_mutex_unlock( &thelock->mut );
310 CHECK_STATUS("pthread_mutex_unlock[3]");
311
312 /* wake up someone (anyone, if any) waiting on the lock */
313 status = pthread_cond_signal( &thelock->lock_released );
314 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000315}
316
317/*
318 * Semaphore support.
319 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000320
321struct semaphore {
322 pthread_mutex_t mutex;
323 pthread_cond_t cond;
324 int value;
325};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000326
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000327type_sema allocate_sema _P1(value, int value)
328{
Guido van Rossum7af81301997-01-17 21:06:41 +0000329 struct semaphore *sema;
330 int status, error = 0;
331
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000332 dprintf(("allocate_sema called\n"));
333 if (!initialized)
334 init_thread();
335
Guido van Rossum7af81301997-01-17 21:06:41 +0000336 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
337 if (sema != NULL) {
338 sema->value = value;
339 status = pthread_mutex_init(&sema->mutex,
340 pthread_mutexattr_default);
341 CHECK_STATUS("pthread_mutex_init");
342 status = pthread_cond_init(&sema->cond,
343 pthread_condattr_default);
344 CHECK_STATUS("pthread_cond_init");
345 if (error) {
346 free((void *) sema);
347 sema = NULL;
348 }
349 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000350 dprintf(("allocate_sema() -> %lx\n", (long) sema));
351 return (type_sema) sema;
352}
353
354void free_sema _P1(sema, type_sema sema)
355{
Guido van Rossum7af81301997-01-17 21:06:41 +0000356 int status, error = 0;
357 struct semaphore *thesema = (struct semaphore *) sema;
358
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000359 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000360 status = pthread_cond_destroy(&thesema->cond);
361 CHECK_STATUS("pthread_cond_destroy");
362 status = pthread_mutex_destroy(&thesema->mutex);
363 CHECK_STATUS("pthread_mutex_destroy");
364 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000365}
366
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000367int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000368{
Guido van Rossum7af81301997-01-17 21:06:41 +0000369 int status, error = 0, success;
370 struct semaphore *thesema = (struct semaphore *) sema;
371
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000372 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000373 status = pthread_mutex_lock(&thesema->mutex);
374 CHECK_STATUS("pthread_mutex_lock");
375 if (waitflag) {
376 while (!error && thesema->value <= 0) {
377 status = pthread_cond_wait(&thesema->cond,
378 &thesema->mutex);
379 CHECK_STATUS("pthread_cond_wait");
380 }
381 }
382 if (error)
383 success = 0;
384 else if (thesema->value > 0) {
385 thesema->value--;
386 success = 1;
387 }
388 else
389 success = 0;
390 status = pthread_mutex_unlock(&thesema->mutex);
391 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000392 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000393 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000394}
395
396void up_sema _P1(sema, type_sema sema)
397{
Guido van Rossum7af81301997-01-17 21:06:41 +0000398 int status, error = 0;
399 struct semaphore *thesema = (struct semaphore *) sema;
400
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000401 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000402 status = pthread_mutex_lock(&thesema->mutex);
403 CHECK_STATUS("pthread_mutex_lock");
404 thesema->value++;
405 status = pthread_cond_signal(&thesema->cond);
406 CHECK_STATUS("pthread_cond_signal");
407 status = pthread_mutex_unlock(&thesema->mutex);
408 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000409}