blob: 9058bf7b791478beda8712ed850778c0aa8fea6b [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 Rossum2c8cb9f1994-05-09 15:12:46 +000030#define pthread_attr_default ((pthread_attr_t *)0)
31#define pthread_mutexattr_default ((pthread_mutexattr_t *)0)
32#define pthread_condattr_default ((pthread_condattr_t *)0)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000033
Guido van Rossumb98b1b31994-05-11 08:42:04 +000034/* A pthread mutex isn't sufficient to model the Python lock type
35 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
36 * following are undefined:
37 * -> a thread tries to lock a mutex it already has locked
38 * -> a thread tries to unlock a mutex locked by a different thread
39 * pthread mutexes are designed for serializing threads over short pieces
40 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000041 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000042 *
43 * The pthread_lock struct implements a Python lock as a "locked?" bit
44 * and a <condition, mutex> pair. In general, if the bit can be acquired
45 * instantly, it is, else the pair is used to block the thread until the
46 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000047 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000048
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000049typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +000050 char locked; /* 0=unlocked, 1=locked */
51 /* a <cond, mutex> pair to handle an acquire of a locked lock */
52 pthread_cond_t lock_released;
53 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000054} pthread_lock;
55
Guido van Rossumb98b1b31994-05-11 08:42:04 +000056#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
57
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000058/*
59 * Initialization.
60 */
61static void _init_thread _P0()
62{
63}
64
65/*
66 * Thread support.
67 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000068
69
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000070int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
71{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000072 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +000073 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000074 dprintf(("start_new_thread called\n"));
75 if (!initialized)
76 init_thread();
Guido van Rossum66020991996-06-11 18:32:18 +000077 success = pthread_create(&th, pthread_attr_default,
78 (void* (*) _P((void *)))func, arg);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000079 return success < 0 ? 0 : 1;
80}
81
Guido van Rossume944da81994-05-23 12:43:41 +000082long get_thread_ident _P0()
83{
Guido van Rossum2565bff1995-01-09 17:50:47 +000084 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +000085 if (!initialized)
86 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +000087 /* Jump through some hoops for Alpha OSF/1 */
88 threadid = pthread_self();
89 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +000090}
91
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000092static void do_exit_thread _P1(no_cleanup, int no_cleanup)
93{
94 dprintf(("exit_thread called\n"));
95 if (!initialized)
96 if (no_cleanup)
97 _exit(0);
98 else
99 exit(0);
100}
101
102void exit_thread _P0()
103{
104 do_exit_thread(0);
105}
106
107void _exit_thread _P0()
108{
109 do_exit_thread(1);
110}
111
112#ifndef NO_EXIT_PROG
113static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
114{
115 dprintf(("exit_prog(%d) called\n", status));
116 if (!initialized)
117 if (no_cleanup)
118 _exit(status);
119 else
120 exit(status);
121}
122
123void exit_prog _P1(status, int status)
124{
125 do_exit_prog(status, 0);
126}
127
128void _exit_prog _P1(status, int status)
129{
130 do_exit_prog(status, 1);
131}
132#endif /* NO_EXIT_PROG */
133
134/*
135 * Lock support.
136 */
137type_lock allocate_lock _P0()
138{
139 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000140 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000141
142 dprintf(("allocate_lock called\n"));
143 if (!initialized)
144 init_thread();
145
146 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000147 if (lock) {
148 lock->locked = 0;
149
150 status = pthread_mutex_init(&lock->mut,
151 pthread_mutexattr_default);
152 CHECK_STATUS("pthread_mutex_init");
153
154 status = pthread_cond_init(&lock->lock_released,
155 pthread_condattr_default);
156 CHECK_STATUS("pthread_cond_init");
157
158 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000159 free((void *)lock);
160 lock = 0;
161 }
162 }
163
164 dprintf(("allocate_lock() -> %lx\n", (long)lock));
165 return (type_lock) lock;
166}
167
168void free_lock _P1(lock, type_lock lock)
169{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000170 pthread_lock *thelock = (pthread_lock *)lock;
171 int status, error = 0;
172
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000173 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000174
175 status = pthread_mutex_destroy( &thelock->mut );
176 CHECK_STATUS("pthread_mutex_destroy");
177
178 status = pthread_cond_destroy( &thelock->lock_released );
179 CHECK_STATUS("pthread_cond_destroy");
180
181 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000182}
183
184int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
185{
186 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000187 pthread_lock *thelock = (pthread_lock *)lock;
188 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000189
190 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000191
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000192 status = pthread_mutex_lock( &thelock->mut );
193 CHECK_STATUS("pthread_mutex_lock[1]");
194 success = thelock->locked == 0;
195 if (success) thelock->locked = 1;
196 status = pthread_mutex_unlock( &thelock->mut );
197 CHECK_STATUS("pthread_mutex_unlock[1]");
198
199 if ( !success && waitflag ) {
200 /* continue trying until we get the lock */
201
202 /* mut must be locked by me -- part of the condition
203 * protocol */
204 status = pthread_mutex_lock( &thelock->mut );
205 CHECK_STATUS("pthread_mutex_lock[2]");
206 while ( thelock->locked ) {
207 status = pthread_cond_wait(&thelock->lock_released,
208 &thelock->mut);
209 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000210 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000211 thelock->locked = 1;
212 status = pthread_mutex_unlock( &thelock->mut );
213 CHECK_STATUS("pthread_mutex_unlock[2]");
214 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000215 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000216 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000217 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
218 return success;
219}
220
221void release_lock _P1(lock, type_lock lock)
222{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000223 pthread_lock *thelock = (pthread_lock *)lock;
224 int status, error = 0;
225
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000226 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000227
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000228 status = pthread_mutex_lock( &thelock->mut );
229 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000230
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000231 thelock->locked = 0;
232
233 status = pthread_mutex_unlock( &thelock->mut );
234 CHECK_STATUS("pthread_mutex_unlock[3]");
235
236 /* wake up someone (anyone, if any) waiting on the lock */
237 status = pthread_cond_signal( &thelock->lock_released );
238 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000239}
240
241/*
242 * Semaphore support.
243 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000244/* NOTE: 100% non-functional at this time - tim */
245
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000246type_sema allocate_sema _P1(value, int value)
247{
248 char *sema = 0;
249 dprintf(("allocate_sema called\n"));
250 if (!initialized)
251 init_thread();
252
253 dprintf(("allocate_sema() -> %lx\n", (long) sema));
254 return (type_sema) sema;
255}
256
257void free_sema _P1(sema, type_sema sema)
258{
259 dprintf(("free_sema(%lx) called\n", (long) sema));
260}
261
262void down_sema _P1(sema, type_sema sema)
263{
264 dprintf(("down_sema(%lx) called\n", (long) sema));
265 dprintf(("down_sema(%lx) return\n", (long) sema));
266}
267
268void up_sema _P1(sema, type_sema sema)
269{
270 dprintf(("up_sema(%lx)\n", (long) sema));
271}