blob: 3004650e16bc45a7dcf7a0b01f5af3959733703d [file] [log] [blame]
Guido van Rossum07bd90e2000-05-08 13:41:38 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The 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 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.
16
17While 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.
29
30******************************************************************/
31
32/* GNU pth threads interface
33 http://www.gnu.org/software/pth
34 2000-05-03 Andy Dustman <andy@dustman.net>
35
36 Adapted from Posix threads interface
37 12 May 1997 -- david arnold <davida@pobox.com>
38 */
39
40#include <stdlib.h>
41#include <string.h>
42#include <pth.h>
43
44/* A pth mutex isn't sufficient to model the Python lock type
45 * because pth mutexes can be acquired multiple times by the
46 * same thread.
47 *
48 * The pth_lock struct implements a Python lock as a "locked?" bit
49 * and a <condition, mutex> pair. In general, if the bit can be acquired
50 * instantly, it is, else the pair is used to block the thread until the
51 * bit is cleared.
52 */
53
54typedef struct {
55 char locked; /* 0=unlocked, 1=locked */
56 /* a <cond, mutex> pair to handle an acquire of a locked lock */
57 pth_cond_t lock_released;
58 pth_mutex_t mut;
59} pth_lock;
60
61#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
62
63/*
64 * Initialization.
65 */
66
67static void PyThread__init_thread _P0()
68{
69 pth_init();
70}
71
72/*
73 * Thread support.
74 */
75
76
77int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
78{
79 pth_t th;
80 int success;
81 dprintf(("PyThread_start_new_thread called\n"));
82 if (!initialized)
83 PyThread_init_thread();
84
85 th = pth_spawn(PTH_ATTR_DEFAULT,
86 (void* (*)_P((void *)))func,
87 (void *)arg
88 );
89
90 return th == NULL ? 0 : 1;
91}
92
93long PyThread_get_thread_ident _P0()
94{
95 volatile pth_t threadid;
96 if (!initialized)
97 PyThread_init_thread();
98 /* Jump through some hoops for Alpha OSF/1 */
99 threadid = pth_self();
100 return (long) *(long *) &threadid;
101}
102
103static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
104{
105 dprintf(("PyThread_exit_thread called\n"));
106 if (!initialized) {
107 if (no_cleanup)
108 _exit(0);
109 else
110 exit(0);
111 }
112}
113
114void PyThread_exit_thread _P0()
115{
116 do_PyThread_exit_thread(0);
117}
118
119void PyThread__exit_thread _P0()
120{
121 do_PyThread_exit_thread(1);
122}
123
124#ifndef NO_EXIT_PROG
125static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
126{
127 dprintf(("PyThread_exit_prog(%d) called\n", status));
128 if (!initialized)
129 if (no_cleanup)
130 _exit(status);
131 else
132 exit(status);
133}
134
135void PyThread_exit_prog _P1(status, int status)
136{
137 do_PyThread_exit_prog(status, 0);
138}
139
140void PyThread__exit_prog _P1(status, int status)
141{
142 do_PyThread_exit_prog(status, 1);
143}
144#endif /* NO_EXIT_PROG */
145
146/*
147 * Lock support.
148 */
149PyThread_type_lock PyThread_allocate_lock _P0()
150{
151 pth_lock *lock;
152 int status, error = 0;
153
154 dprintf(("PyThread_allocate_lock called\n"));
155 if (!initialized)
156 PyThread_init_thread();
157
158 lock = (pth_lock *) malloc(sizeof(pth_lock));
159 memset((void *)lock, '\0', sizeof(pth_lock));
160 if (lock) {
161 lock->locked = 0;
162 status = pth_mutex_init(&lock->mut);
163 CHECK_STATUS("pth_mutex_init");
164 status = pth_cond_init(&lock->lock_released);
165 CHECK_STATUS("pth_cond_init");
166 if (error) {
167 free((void *)lock);
168 lock = NULL;
169 }
170 }
Fred Drakea44d3532000-06-30 15:01:00 +0000171 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000172 return (PyThread_type_lock) lock;
173}
174
175void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
176{
177 pth_lock *thelock = (pth_lock *)lock;
178 int status, error = 0;
179
Fred Drakea44d3532000-06-30 15:01:00 +0000180 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000181
182 free((void *)thelock);
183}
184
185int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
186{
187 int success;
188 pth_lock *thelock = (pth_lock *)lock;
189 int status, error = 0;
190
Fred Drakea44d3532000-06-30 15:01:00 +0000191 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000192
193 status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
194 CHECK_STATUS("pth_mutex_acquire[1]");
195 success = thelock->locked == 0;
196 if (success) thelock->locked = 1;
197 status = pth_mutex_release( &thelock->mut );
198 CHECK_STATUS("pth_mutex_release[1]");
199
200 if ( !success && waitflag ) {
201 /* continue trying until we get the lock */
202
203 /* mut must be locked by me -- part of the condition
204 * protocol */
205 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
206 CHECK_STATUS("pth_mutex_acquire[2]");
207 while ( thelock->locked ) {
208 status = pth_cond_await(&thelock->lock_released,
209 &thelock->mut, NULL);
210 CHECK_STATUS("pth_cond_await");
211 }
212 thelock->locked = 1;
213 status = pth_mutex_release( &thelock->mut );
214 CHECK_STATUS("pth_mutex_release[2]");
215 success = 1;
216 }
217 if (error) success = 0;
Fred Drakea44d3532000-06-30 15:01:00 +0000218 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000219 return success;
220}
221
222void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
223{
224 pth_lock *thelock = (pth_lock *)lock;
225 int status, error = 0;
226
Fred Drakea44d3532000-06-30 15:01:00 +0000227 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000228
229 status = pth_mutex_acquire( &thelock->mut, 0, NULL );
230 CHECK_STATUS("pth_mutex_acquire[3]");
231
232 thelock->locked = 0;
233
234 status = pth_mutex_release( &thelock->mut );
235 CHECK_STATUS("pth_mutex_release[3]");
236
237 /* wake up someone (anyone, if any) waiting on the lock */
238 status = pth_cond_notify( &thelock->lock_released, 0 );
239 CHECK_STATUS("pth_cond_notify");
240}
241
242/*
243 * Semaphore support.
244 */
245
246struct semaphore {
247 pth_mutex_t mutex;
248 pth_cond_t cond;
249 int value;
250};
251
252PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
253{
254 struct semaphore *sema;
255 int status, error = 0;
256
257 dprintf(("PyThread_allocate_sema called\n"));
258 if (!initialized)
259 PyThread_init_thread();
260
261 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
262 if (sema != NULL) {
263 sema->value = value;
264 status = pth_mutex_init(&sema->mutex);
265 CHECK_STATUS("pth_mutex_init");
266 status = pth_cond_init(&sema->cond);
267 CHECK_STATUS("pth_mutex_init");
268 if (error) {
269 free((void *) sema);
270 sema = NULL;
271 }
272 }
Fred Drakea44d3532000-06-30 15:01:00 +0000273 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000274 return (PyThread_type_sema) sema;
275}
276
277void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
278{
279 int status, error = 0;
280 struct semaphore *thesema = (struct semaphore *) sema;
281
Fred Drakea44d3532000-06-30 15:01:00 +0000282 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000283 free((void *) thesema);
284}
285
286int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
287{
288 int status, error = 0, success;
289 struct semaphore *thesema = (struct semaphore *) sema;
290
Fred Drakea44d3532000-06-30 15:01:00 +0000291 dprintf(("PyThread_down_sema(%p, %d) called\n", sema, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000292 status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
293 CHECK_STATUS("pth_mutex_acquire");
294 if (waitflag) {
295 while (!error && thesema->value <= 0) {
296 status = pth_cond_await(&thesema->cond,
297 &thesema->mutex, NULL);
298 CHECK_STATUS("pth_cond_await");
299 }
300 }
301 if (error)
302 success = 0;
303 else if (thesema->value > 0) {
304 thesema->value--;
305 success = 1;
306 }
307 else
308 success = 0;
309 status = pth_mutex_release(&thesema->mutex);
310 CHECK_STATUS("pth_mutex_release");
Fred Drakea44d3532000-06-30 15:01:00 +0000311 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000312 return success;
313}
314
315void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
316{
317 int status, error = 0;
318 struct semaphore *thesema = (struct semaphore *) sema;
319
Fred Drakea44d3532000-06-30 15:01:00 +0000320 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000321 status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
322 CHECK_STATUS("pth_mutex_acquire");
323 thesema->value++;
324 status = pth_cond_notify(&thesema->cond, 1);
325 CHECK_STATUS("pth_cond_notify");
326 status = pth_mutex_release(&thesema->mutex);
327 CHECK_STATUS("pth_mutex_release");
328}