blob: a4222cf1e068d1ece3073b84f815482bb911b37d [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
25#ifdef sun
26#define FLORIDA_HACKS
27#endif
28
29#ifdef FLORIDA_HACKS
30/* Hacks for Florida State Posix threads implementation */
31#undef _POSIX_THREADS
Guido van Rossumb98b1b31994-05-11 08:42:04 +000032#include "/ufs/guido/src/python/Contrib/pthreads/src/pthread.h"
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000033#define pthread_attr_default ((pthread_attr_t *)0)
34#define pthread_mutexattr_default ((pthread_mutexattr_t *)0)
35#define pthread_condattr_default ((pthread_condattr_t *)0)
36#define TRYLOCK_OFFSET 1
37#else /* !FLORIDA_HACKS */
38#include <pthread.h>
39#define TRYLOCK_OFFSET 0
40#endif /* FLORIDA_HACKS */
41#include <stdlib.h>
42
Guido van Rossumb98b1b31994-05-11 08:42:04 +000043/* A pthread mutex isn't sufficient to model the Python lock type
44 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
45 * following are undefined:
46 * -> a thread tries to lock a mutex it already has locked
47 * -> a thread tries to unlock a mutex locked by a different thread
48 * pthread mutexes are designed for serializing threads over short pieces
49 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000050 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000051 *
52 * The pthread_lock struct implements a Python lock as a "locked?" bit
53 * and a <condition, mutex> pair. In general, if the bit can be acquired
54 * instantly, it is, else the pair is used to block the thread until the
55 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000056 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000057
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000058typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +000059 char locked; /* 0=unlocked, 1=locked */
60 /* a <cond, mutex> pair to handle an acquire of a locked lock */
61 pthread_cond_t lock_released;
62 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000063} pthread_lock;
64
Guido van Rossumb98b1b31994-05-11 08:42:04 +000065#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
66
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000067/*
68 * Initialization.
69 */
70static void _init_thread _P0()
71{
72}
73
74/*
75 * Thread support.
76 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000077
78
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000079int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
80{
81#if defined(SGI_THREADS) && defined(USE_DL)
82 long addr, size;
83 static int local_initialized = 0;
84#endif /* SGI_THREADS and USE_DL */
85 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +000086 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000087 dprintf(("start_new_thread called\n"));
88 if (!initialized)
89 init_thread();
90 success = pthread_create(&th, pthread_attr_default, func, arg);
91 return success < 0 ? 0 : 1;
92}
93
Guido van Rossume944da81994-05-23 12:43:41 +000094long get_thread_ident _P0()
95{
Guido van Rossum2565bff1995-01-09 17:50:47 +000096 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +000097 if (!initialized)
98 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +000099 /* Jump through some hoops for Alpha OSF/1 */
100 threadid = pthread_self();
101 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000102}
103
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000104static void do_exit_thread _P1(no_cleanup, int no_cleanup)
105{
106 dprintf(("exit_thread called\n"));
107 if (!initialized)
108 if (no_cleanup)
109 _exit(0);
110 else
111 exit(0);
112}
113
114void exit_thread _P0()
115{
116 do_exit_thread(0);
117}
118
119void _exit_thread _P0()
120{
121 do_exit_thread(1);
122}
123
124#ifndef NO_EXIT_PROG
125static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
126{
127 dprintf(("exit_prog(%d) called\n", status));
128 if (!initialized)
129 if (no_cleanup)
130 _exit(status);
131 else
132 exit(status);
133}
134
135void exit_prog _P1(status, int status)
136{
137 do_exit_prog(status, 0);
138}
139
140void _exit_prog _P1(status, int status)
141{
142 do_exit_prog(status, 1);
143}
144#endif /* NO_EXIT_PROG */
145
146/*
147 * Lock support.
148 */
149type_lock allocate_lock _P0()
150{
151 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000152 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000153
154 dprintf(("allocate_lock called\n"));
155 if (!initialized)
156 init_thread();
157
158 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000159 if (lock) {
160 lock->locked = 0;
161
162 status = pthread_mutex_init(&lock->mut,
163 pthread_mutexattr_default);
164 CHECK_STATUS("pthread_mutex_init");
165
166 status = pthread_cond_init(&lock->lock_released,
167 pthread_condattr_default);
168 CHECK_STATUS("pthread_cond_init");
169
170 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000171 free((void *)lock);
172 lock = 0;
173 }
174 }
175
176 dprintf(("allocate_lock() -> %lx\n", (long)lock));
177 return (type_lock) lock;
178}
179
180void free_lock _P1(lock, type_lock lock)
181{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000182 pthread_lock *thelock = (pthread_lock *)lock;
183 int status, error = 0;
184
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000185 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000186
187 status = pthread_mutex_destroy( &thelock->mut );
188 CHECK_STATUS("pthread_mutex_destroy");
189
190 status = pthread_cond_destroy( &thelock->lock_released );
191 CHECK_STATUS("pthread_cond_destroy");
192
193 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000194}
195
196int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
197{
198 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000199 pthread_lock *thelock = (pthread_lock *)lock;
200 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000201
202 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000203
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000204 status = pthread_mutex_lock( &thelock->mut );
205 CHECK_STATUS("pthread_mutex_lock[1]");
206 success = thelock->locked == 0;
207 if (success) thelock->locked = 1;
208 status = pthread_mutex_unlock( &thelock->mut );
209 CHECK_STATUS("pthread_mutex_unlock[1]");
210
211 if ( !success && waitflag ) {
212 /* continue trying until we get the lock */
213
214 /* mut must be locked by me -- part of the condition
215 * protocol */
216 status = pthread_mutex_lock( &thelock->mut );
217 CHECK_STATUS("pthread_mutex_lock[2]");
218 while ( thelock->locked ) {
219 status = pthread_cond_wait(&thelock->lock_released,
220 &thelock->mut);
221 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000222 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000223 thelock->locked = 1;
224 status = pthread_mutex_unlock( &thelock->mut );
225 CHECK_STATUS("pthread_mutex_unlock[2]");
226 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000227 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000228 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000229 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
230 return success;
231}
232
233void release_lock _P1(lock, type_lock lock)
234{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000235 pthread_lock *thelock = (pthread_lock *)lock;
236 int status, error = 0;
237
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000238 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000239
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000240 status = pthread_mutex_lock( &thelock->mut );
241 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000242
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000243 thelock->locked = 0;
244
245 status = pthread_mutex_unlock( &thelock->mut );
246 CHECK_STATUS("pthread_mutex_unlock[3]");
247
248 /* wake up someone (anyone, if any) waiting on the lock */
249 status = pthread_cond_signal( &thelock->lock_released );
250 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000251}
252
253/*
254 * Semaphore support.
255 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000256/* NOTE: 100% non-functional at this time - tim */
257
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000258type_sema allocate_sema _P1(value, int value)
259{
260 char *sema = 0;
261 dprintf(("allocate_sema called\n"));
262 if (!initialized)
263 init_thread();
264
265 dprintf(("allocate_sema() -> %lx\n", (long) sema));
266 return (type_sema) sema;
267}
268
269void free_sema _P1(sema, type_sema sema)
270{
271 dprintf(("free_sema(%lx) called\n", (long) sema));
272}
273
274void down_sema _P1(sema, type_sema sema)
275{
276 dprintf(("down_sema(%lx) called\n", (long) sema));
277 dprintf(("down_sema(%lx) return\n", (long) sema));
278}
279
280void up_sema _P1(sema, type_sema sema)
281{
282 dprintf(("up_sema(%lx)\n", (long) sema));
283}