blob: 0e2ca11b388ef02d1f7aba945f0aa9382ec6e183 [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#ifdef _AIX
38
39#ifndef SCHED_BG_NP
40/* SCHED_BG_NP is defined if using AIX DCE pthreads
41 * but it is unsupported by AIX 4 pthreads. Default
42 * attributes for AIX 4 pthreads equal to NULL. For
43 * AIX DCE pthreads they should be left unchanged.
44 */
45#define pthread_attr_default NULL
46#define pthread_mutexattr_default NULL
47#define pthread_condattr_default NULL
48#endif
49
50#else
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000051#define pthread_attr_default ((pthread_attr_t *)0)
52#define pthread_mutexattr_default ((pthread_mutexattr_t *)0)
53#define pthread_condattr_default ((pthread_condattr_t *)0)
Guido van Rossum1a623111996-08-08 18:53:41 +000054#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000055
Guido van Rossumb98b1b31994-05-11 08:42:04 +000056/* A pthread mutex isn't sufficient to model the Python lock type
57 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
58 * following are undefined:
59 * -> a thread tries to lock a mutex it already has locked
60 * -> a thread tries to unlock a mutex locked by a different thread
61 * pthread mutexes are designed for serializing threads over short pieces
62 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000063 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000064 *
65 * The pthread_lock struct implements a Python lock as a "locked?" bit
66 * and a <condition, mutex> pair. In general, if the bit can be acquired
67 * instantly, it is, else the pair is used to block the thread until the
68 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000069 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000070
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000071typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +000072 char locked; /* 0=unlocked, 1=locked */
73 /* a <cond, mutex> pair to handle an acquire of a locked lock */
74 pthread_cond_t lock_released;
75 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000076} pthread_lock;
77
Guido van Rossumb98b1b31994-05-11 08:42:04 +000078#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
79
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000080/*
81 * Initialization.
82 */
83static void _init_thread _P0()
84{
85}
86
87/*
88 * Thread support.
89 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000090
91
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000092int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
93{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000094 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +000095 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000096 dprintf(("start_new_thread called\n"));
97 if (!initialized)
98 init_thread();
Guido van Rossum66020991996-06-11 18:32:18 +000099 success = pthread_create(&th, pthread_attr_default,
100 (void* (*) _P((void *)))func, arg);
Guido van Rossumf4806c21997-04-30 19:59:22 +0000101 if (success >= 0)
102 pthread_detach(th);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000103 return success < 0 ? 0 : 1;
104}
105
Guido van Rossume944da81994-05-23 12:43:41 +0000106long get_thread_ident _P0()
107{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000108 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000109 if (!initialized)
110 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000111 /* Jump through some hoops for Alpha OSF/1 */
112 threadid = pthread_self();
113 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000114}
115
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000116static void do_exit_thread _P1(no_cleanup, int no_cleanup)
117{
118 dprintf(("exit_thread called\n"));
119 if (!initialized)
120 if (no_cleanup)
121 _exit(0);
122 else
123 exit(0);
124}
125
126void exit_thread _P0()
127{
128 do_exit_thread(0);
129}
130
131void _exit_thread _P0()
132{
133 do_exit_thread(1);
134}
135
136#ifndef NO_EXIT_PROG
137static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
138{
139 dprintf(("exit_prog(%d) called\n", status));
140 if (!initialized)
141 if (no_cleanup)
142 _exit(status);
143 else
144 exit(status);
145}
146
147void exit_prog _P1(status, int status)
148{
149 do_exit_prog(status, 0);
150}
151
152void _exit_prog _P1(status, int status)
153{
154 do_exit_prog(status, 1);
155}
156#endif /* NO_EXIT_PROG */
157
158/*
159 * Lock support.
160 */
161type_lock allocate_lock _P0()
162{
163 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000164 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000165
166 dprintf(("allocate_lock called\n"));
167 if (!initialized)
168 init_thread();
169
170 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000171 if (lock) {
172 lock->locked = 0;
173
174 status = pthread_mutex_init(&lock->mut,
175 pthread_mutexattr_default);
176 CHECK_STATUS("pthread_mutex_init");
177
178 status = pthread_cond_init(&lock->lock_released,
179 pthread_condattr_default);
180 CHECK_STATUS("pthread_cond_init");
181
182 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000183 free((void *)lock);
184 lock = 0;
185 }
186 }
187
188 dprintf(("allocate_lock() -> %lx\n", (long)lock));
189 return (type_lock) lock;
190}
191
192void free_lock _P1(lock, type_lock lock)
193{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000194 pthread_lock *thelock = (pthread_lock *)lock;
195 int status, error = 0;
196
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000197 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000198
199 status = pthread_mutex_destroy( &thelock->mut );
200 CHECK_STATUS("pthread_mutex_destroy");
201
202 status = pthread_cond_destroy( &thelock->lock_released );
203 CHECK_STATUS("pthread_cond_destroy");
204
205 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000206}
207
208int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
209{
210 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000211 pthread_lock *thelock = (pthread_lock *)lock;
212 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000213
214 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000215
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000216 status = pthread_mutex_lock( &thelock->mut );
217 CHECK_STATUS("pthread_mutex_lock[1]");
218 success = thelock->locked == 0;
219 if (success) thelock->locked = 1;
220 status = pthread_mutex_unlock( &thelock->mut );
221 CHECK_STATUS("pthread_mutex_unlock[1]");
222
223 if ( !success && waitflag ) {
224 /* continue trying until we get the lock */
225
226 /* mut must be locked by me -- part of the condition
227 * protocol */
228 status = pthread_mutex_lock( &thelock->mut );
229 CHECK_STATUS("pthread_mutex_lock[2]");
230 while ( thelock->locked ) {
231 status = pthread_cond_wait(&thelock->lock_released,
232 &thelock->mut);
233 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000234 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000235 thelock->locked = 1;
236 status = pthread_mutex_unlock( &thelock->mut );
237 CHECK_STATUS("pthread_mutex_unlock[2]");
238 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000239 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000240 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000241 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
242 return success;
243}
244
245void release_lock _P1(lock, type_lock lock)
246{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000247 pthread_lock *thelock = (pthread_lock *)lock;
248 int status, error = 0;
249
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000250 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000251
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000252 status = pthread_mutex_lock( &thelock->mut );
253 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000254
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000255 thelock->locked = 0;
256
257 status = pthread_mutex_unlock( &thelock->mut );
258 CHECK_STATUS("pthread_mutex_unlock[3]");
259
260 /* wake up someone (anyone, if any) waiting on the lock */
261 status = pthread_cond_signal( &thelock->lock_released );
262 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000263}
264
265/*
266 * Semaphore support.
267 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000268
269struct semaphore {
270 pthread_mutex_t mutex;
271 pthread_cond_t cond;
272 int value;
273};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000274
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000275type_sema allocate_sema _P1(value, int value)
276{
Guido van Rossum7af81301997-01-17 21:06:41 +0000277 struct semaphore *sema;
278 int status, error = 0;
279
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000280 dprintf(("allocate_sema called\n"));
281 if (!initialized)
282 init_thread();
283
Guido van Rossum7af81301997-01-17 21:06:41 +0000284 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
285 if (sema != NULL) {
286 sema->value = value;
287 status = pthread_mutex_init(&sema->mutex,
288 pthread_mutexattr_default);
289 CHECK_STATUS("pthread_mutex_init");
290 status = pthread_cond_init(&sema->cond,
291 pthread_condattr_default);
292 CHECK_STATUS("pthread_cond_init");
293 if (error) {
294 free((void *) sema);
295 sema = NULL;
296 }
297 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000298 dprintf(("allocate_sema() -> %lx\n", (long) sema));
299 return (type_sema) sema;
300}
301
302void free_sema _P1(sema, type_sema sema)
303{
Guido van Rossum7af81301997-01-17 21:06:41 +0000304 int status, error = 0;
305 struct semaphore *thesema = (struct semaphore *) sema;
306
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000307 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000308 status = pthread_cond_destroy(&thesema->cond);
309 CHECK_STATUS("pthread_cond_destroy");
310 status = pthread_mutex_destroy(&thesema->mutex);
311 CHECK_STATUS("pthread_mutex_destroy");
312 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000313}
314
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000315int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000316{
Guido van Rossum7af81301997-01-17 21:06:41 +0000317 int status, error = 0, success;
318 struct semaphore *thesema = (struct semaphore *) sema;
319
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000320 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000321 status = pthread_mutex_lock(&thesema->mutex);
322 CHECK_STATUS("pthread_mutex_lock");
323 if (waitflag) {
324 while (!error && thesema->value <= 0) {
325 status = pthread_cond_wait(&thesema->cond,
326 &thesema->mutex);
327 CHECK_STATUS("pthread_cond_wait");
328 }
329 }
330 if (error)
331 success = 0;
332 else if (thesema->value > 0) {
333 thesema->value--;
334 success = 1;
335 }
336 else
337 success = 0;
338 status = pthread_mutex_unlock(&thesema->mutex);
339 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000340 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000341 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000342}
343
344void up_sema _P1(sema, type_sema sema)
345{
Guido van Rossum7af81301997-01-17 21:06:41 +0000346 int status, error = 0;
347 struct semaphore *thesema = (struct semaphore *) sema;
348
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000349 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000350 status = pthread_mutex_lock(&thesema->mutex);
351 CHECK_STATUS("pthread_mutex_lock");
352 thesema->value++;
353 status = pthread_cond_signal(&thesema->cond);
354 CHECK_STATUS("pthread_cond_signal");
355 status = pthread_mutex_unlock(&thesema->mutex);
356 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000357}