blob: 1d539eea6366fe5d2bef6111d84a55f4c8dd4f78 [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001/***********************************************************
2Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
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;
86 int success = 0; /* init not needed when SOLARIS_THREADS and */
87 /* C_THREADS implemented properly */
88
89 dprintf(("start_new_thread called\n"));
90 if (!initialized)
91 init_thread();
92 success = pthread_create(&th, pthread_attr_default, func, arg);
93 return success < 0 ? 0 : 1;
94}
95
96static void do_exit_thread _P1(no_cleanup, int no_cleanup)
97{
98 dprintf(("exit_thread called\n"));
99 if (!initialized)
100 if (no_cleanup)
101 _exit(0);
102 else
103 exit(0);
104}
105
106void exit_thread _P0()
107{
108 do_exit_thread(0);
109}
110
111void _exit_thread _P0()
112{
113 do_exit_thread(1);
114}
115
116#ifndef NO_EXIT_PROG
117static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
118{
119 dprintf(("exit_prog(%d) called\n", status));
120 if (!initialized)
121 if (no_cleanup)
122 _exit(status);
123 else
124 exit(status);
125}
126
127void exit_prog _P1(status, int status)
128{
129 do_exit_prog(status, 0);
130}
131
132void _exit_prog _P1(status, int status)
133{
134 do_exit_prog(status, 1);
135}
136#endif /* NO_EXIT_PROG */
137
138/*
139 * Lock support.
140 */
141type_lock allocate_lock _P0()
142{
143 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000144 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000145
146 dprintf(("allocate_lock called\n"));
147 if (!initialized)
148 init_thread();
149
150 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000151 if (lock) {
152 lock->locked = 0;
153
154 status = pthread_mutex_init(&lock->mut,
155 pthread_mutexattr_default);
156 CHECK_STATUS("pthread_mutex_init");
157
158 status = pthread_cond_init(&lock->lock_released,
159 pthread_condattr_default);
160 CHECK_STATUS("pthread_cond_init");
161
162 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000163 free((void *)lock);
164 lock = 0;
165 }
166 }
167
168 dprintf(("allocate_lock() -> %lx\n", (long)lock));
169 return (type_lock) lock;
170}
171
172void free_lock _P1(lock, type_lock lock)
173{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000174 pthread_lock *thelock = (pthread_lock *)lock;
175 int status, error = 0;
176
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000177 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000178
179 status = pthread_mutex_destroy( &thelock->mut );
180 CHECK_STATUS("pthread_mutex_destroy");
181
182 status = pthread_cond_destroy( &thelock->lock_released );
183 CHECK_STATUS("pthread_cond_destroy");
184
185 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000186}
187
188int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
189{
190 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000191 pthread_lock *thelock = (pthread_lock *)lock;
192 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000193
194 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000195
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000196 status = pthread_mutex_lock( &thelock->mut );
197 CHECK_STATUS("pthread_mutex_lock[1]");
198 success = thelock->locked == 0;
199 if (success) thelock->locked = 1;
200 status = pthread_mutex_unlock( &thelock->mut );
201 CHECK_STATUS("pthread_mutex_unlock[1]");
202
203 if ( !success && waitflag ) {
204 /* continue trying until we get the lock */
205
206 /* mut must be locked by me -- part of the condition
207 * protocol */
208 status = pthread_mutex_lock( &thelock->mut );
209 CHECK_STATUS("pthread_mutex_lock[2]");
210 while ( thelock->locked ) {
211 status = pthread_cond_wait(&thelock->lock_released,
212 &thelock->mut);
213 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000214 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000215 thelock->locked = 1;
216 status = pthread_mutex_unlock( &thelock->mut );
217 CHECK_STATUS("pthread_mutex_unlock[2]");
218 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000219 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000220 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000221 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
222 return success;
223}
224
225void release_lock _P1(lock, type_lock lock)
226{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000227 pthread_lock *thelock = (pthread_lock *)lock;
228 int status, error = 0;
229
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000230 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000231
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000232 status = pthread_mutex_lock( &thelock->mut );
233 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000234
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000235 thelock->locked = 0;
236
237 status = pthread_mutex_unlock( &thelock->mut );
238 CHECK_STATUS("pthread_mutex_unlock[3]");
239
240 /* wake up someone (anyone, if any) waiting on the lock */
241 status = pthread_cond_signal( &thelock->lock_released );
242 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000243}
244
245/*
246 * Semaphore support.
247 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000248/* NOTE: 100% non-functional at this time - tim */
249
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000250type_sema allocate_sema _P1(value, int value)
251{
252 char *sema = 0;
253 dprintf(("allocate_sema called\n"));
254 if (!initialized)
255 init_thread();
256
257 dprintf(("allocate_sema() -> %lx\n", (long) sema));
258 return (type_sema) sema;
259}
260
261void free_sema _P1(sema, type_sema sema)
262{
263 dprintf(("free_sema(%lx) called\n", (long) sema));
264}
265
266void down_sema _P1(sema, type_sema sema)
267{
268 dprintf(("down_sema(%lx) called\n", (long) sema));
269 dprintf(("down_sema(%lx) return\n", (long) sema));
270}
271
272void up_sema _P1(sema, type_sema sema)
273{
274 dprintf(("up_sema(%lx)\n", (long) sema));
275}