blob: a43a2f81d687ba7b2b41e3e334802bbf20808003 [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
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum66020991996-06-11 18:32:18 +000025/* Posix threads interface */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000026
Guido van Rossum66020991996-06-11 18:32:18 +000027#include <stdlib.h>
28#include <pthread.h>
29
Guido van Rossum1a623111996-08-08 18:53:41 +000030#ifdef _AIX
31
32#ifndef SCHED_BG_NP
33/* SCHED_BG_NP is defined if using AIX DCE pthreads
34 * but it is unsupported by AIX 4 pthreads. Default
35 * attributes for AIX 4 pthreads equal to NULL. For
36 * AIX DCE pthreads they should be left unchanged.
37 */
38#define pthread_attr_default NULL
39#define pthread_mutexattr_default NULL
40#define pthread_condattr_default NULL
41#endif
42
43#else
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000044#define pthread_attr_default ((pthread_attr_t *)0)
45#define pthread_mutexattr_default ((pthread_mutexattr_t *)0)
46#define pthread_condattr_default ((pthread_condattr_t *)0)
Guido van Rossum1a623111996-08-08 18:53:41 +000047#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000048
Guido van Rossumb98b1b31994-05-11 08:42:04 +000049/* A pthread mutex isn't sufficient to model the Python lock type
50 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
51 * following are undefined:
52 * -> a thread tries to lock a mutex it already has locked
53 * -> a thread tries to unlock a mutex locked by a different thread
54 * pthread mutexes are designed for serializing threads over short pieces
55 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000056 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000057 *
58 * The pthread_lock struct implements a Python lock as a "locked?" bit
59 * and a <condition, mutex> pair. In general, if the bit can be acquired
60 * instantly, it is, else the pair is used to block the thread until the
61 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000062 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000063
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000064typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +000065 char locked; /* 0=unlocked, 1=locked */
66 /* a <cond, mutex> pair to handle an acquire of a locked lock */
67 pthread_cond_t lock_released;
68 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000069} pthread_lock;
70
Guido van Rossumb98b1b31994-05-11 08:42:04 +000071#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
72
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000073/*
74 * Initialization.
75 */
76static void _init_thread _P0()
77{
78}
79
80/*
81 * Thread support.
82 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000083
84
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000085int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
86{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000087 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +000088 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000089 dprintf(("start_new_thread called\n"));
90 if (!initialized)
91 init_thread();
Guido van Rossum66020991996-06-11 18:32:18 +000092 success = pthread_create(&th, pthread_attr_default,
93 (void* (*) _P((void *)))func, arg);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000094 return success < 0 ? 0 : 1;
95}
96
Guido van Rossume944da81994-05-23 12:43:41 +000097long get_thread_ident _P0()
98{
Guido van Rossum2565bff1995-01-09 17:50:47 +000099 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000100 if (!initialized)
101 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000102 /* Jump through some hoops for Alpha OSF/1 */
103 threadid = pthread_self();
104 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000105}
106
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000107static void do_exit_thread _P1(no_cleanup, int no_cleanup)
108{
109 dprintf(("exit_thread called\n"));
110 if (!initialized)
111 if (no_cleanup)
112 _exit(0);
113 else
114 exit(0);
115}
116
117void exit_thread _P0()
118{
119 do_exit_thread(0);
120}
121
122void _exit_thread _P0()
123{
124 do_exit_thread(1);
125}
126
127#ifndef NO_EXIT_PROG
128static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
129{
130 dprintf(("exit_prog(%d) called\n", status));
131 if (!initialized)
132 if (no_cleanup)
133 _exit(status);
134 else
135 exit(status);
136}
137
138void exit_prog _P1(status, int status)
139{
140 do_exit_prog(status, 0);
141}
142
143void _exit_prog _P1(status, int status)
144{
145 do_exit_prog(status, 1);
146}
147#endif /* NO_EXIT_PROG */
148
149/*
150 * Lock support.
151 */
152type_lock allocate_lock _P0()
153{
154 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000155 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000156
157 dprintf(("allocate_lock called\n"));
158 if (!initialized)
159 init_thread();
160
161 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000162 if (lock) {
163 lock->locked = 0;
164
165 status = pthread_mutex_init(&lock->mut,
166 pthread_mutexattr_default);
167 CHECK_STATUS("pthread_mutex_init");
168
169 status = pthread_cond_init(&lock->lock_released,
170 pthread_condattr_default);
171 CHECK_STATUS("pthread_cond_init");
172
173 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000174 free((void *)lock);
175 lock = 0;
176 }
177 }
178
179 dprintf(("allocate_lock() -> %lx\n", (long)lock));
180 return (type_lock) lock;
181}
182
183void free_lock _P1(lock, type_lock lock)
184{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000185 pthread_lock *thelock = (pthread_lock *)lock;
186 int status, error = 0;
187
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000188 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000189
190 status = pthread_mutex_destroy( &thelock->mut );
191 CHECK_STATUS("pthread_mutex_destroy");
192
193 status = pthread_cond_destroy( &thelock->lock_released );
194 CHECK_STATUS("pthread_cond_destroy");
195
196 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000197}
198
199int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
200{
201 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000202 pthread_lock *thelock = (pthread_lock *)lock;
203 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000204
205 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000206
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000207 status = pthread_mutex_lock( &thelock->mut );
208 CHECK_STATUS("pthread_mutex_lock[1]");
209 success = thelock->locked == 0;
210 if (success) thelock->locked = 1;
211 status = pthread_mutex_unlock( &thelock->mut );
212 CHECK_STATUS("pthread_mutex_unlock[1]");
213
214 if ( !success && waitflag ) {
215 /* continue trying until we get the lock */
216
217 /* mut must be locked by me -- part of the condition
218 * protocol */
219 status = pthread_mutex_lock( &thelock->mut );
220 CHECK_STATUS("pthread_mutex_lock[2]");
221 while ( thelock->locked ) {
222 status = pthread_cond_wait(&thelock->lock_released,
223 &thelock->mut);
224 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000225 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000226 thelock->locked = 1;
227 status = pthread_mutex_unlock( &thelock->mut );
228 CHECK_STATUS("pthread_mutex_unlock[2]");
229 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000230 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000231 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000232 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
233 return success;
234}
235
236void release_lock _P1(lock, type_lock lock)
237{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000238 pthread_lock *thelock = (pthread_lock *)lock;
239 int status, error = 0;
240
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000241 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000242
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000243 status = pthread_mutex_lock( &thelock->mut );
244 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000245
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000246 thelock->locked = 0;
247
248 status = pthread_mutex_unlock( &thelock->mut );
249 CHECK_STATUS("pthread_mutex_unlock[3]");
250
251 /* wake up someone (anyone, if any) waiting on the lock */
252 status = pthread_cond_signal( &thelock->lock_released );
253 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000254}
255
256/*
257 * Semaphore support.
258 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000259/* NOTE: 100% non-functional at this time - tim */
260
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000261type_sema allocate_sema _P1(value, int value)
262{
263 char *sema = 0;
264 dprintf(("allocate_sema called\n"));
265 if (!initialized)
266 init_thread();
267
268 dprintf(("allocate_sema() -> %lx\n", (long) sema));
269 return (type_sema) sema;
270}
271
272void free_sema _P1(sema, type_sema sema)
273{
274 dprintf(("free_sema(%lx) called\n", (long) sema));
275}
276
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000277int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000278{
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000279 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000280 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000281 return -1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000282}
283
284void up_sema _P1(sema, type_sema sema)
285{
286 dprintf(("up_sema(%lx)\n", (long) sema));
287}