blob: 93af4ee2445d1633bee7e47605779a8f5b1d1b31 [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
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
Guido van Rossum07bd90e2000-05-08 13:41:38 +000011
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000012See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum07bd90e2000-05-08 13:41:38 +000014
15******************************************************************/
16
17/* GNU pth threads interface
18 http://www.gnu.org/software/pth
19 2000-05-03 Andy Dustman <andy@dustman.net>
20
21 Adapted from Posix threads interface
22 12 May 1997 -- david arnold <davida@pobox.com>
23 */
24
25#include <stdlib.h>
26#include <string.h>
27#include <pth.h>
28
29/* A pth mutex isn't sufficient to model the Python lock type
30 * because pth mutexes can be acquired multiple times by the
31 * same thread.
32 *
33 * The pth_lock struct implements a Python lock as a "locked?" bit
34 * and a <condition, mutex> pair. In general, if the bit can be acquired
35 * instantly, it is, else the pair is used to block the thread until the
36 * bit is cleared.
37 */
38
39typedef struct {
40 char locked; /* 0=unlocked, 1=locked */
41 /* a <cond, mutex> pair to handle an acquire of a locked lock */
42 pth_cond_t lock_released;
43 pth_mutex_t mut;
44} pth_lock;
45
46#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
47
48/*
49 * Initialization.
50 */
51
52static void PyThread__init_thread _P0()
53{
54 pth_init();
55}
56
57/*
58 * Thread support.
59 */
60
61
62int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
63{
64 pth_t th;
65 int success;
66 dprintf(("PyThread_start_new_thread called\n"));
67 if (!initialized)
68 PyThread_init_thread();
69
70 th = pth_spawn(PTH_ATTR_DEFAULT,
71 (void* (*)_P((void *)))func,
72 (void *)arg
73 );
74
75 return th == NULL ? 0 : 1;
76}
77
78long PyThread_get_thread_ident _P0()
79{
80 volatile pth_t threadid;
81 if (!initialized)
82 PyThread_init_thread();
83 /* Jump through some hoops for Alpha OSF/1 */
84 threadid = pth_self();
85 return (long) *(long *) &threadid;
86}
87
88static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
89{
90 dprintf(("PyThread_exit_thread called\n"));
91 if (!initialized) {
92 if (no_cleanup)
93 _exit(0);
94 else
95 exit(0);
96 }
97}
98
99void PyThread_exit_thread _P0()
100{
101 do_PyThread_exit_thread(0);
102}
103
104void PyThread__exit_thread _P0()
105{
106 do_PyThread_exit_thread(1);
107}
108
109#ifndef NO_EXIT_PROG
110static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
111{
112 dprintf(("PyThread_exit_prog(%d) called\n", status));
113 if (!initialized)
114 if (no_cleanup)
115 _exit(status);
116 else
117 exit(status);
118}
119
120void PyThread_exit_prog _P1(status, int status)
121{
122 do_PyThread_exit_prog(status, 0);
123}
124
125void PyThread__exit_prog _P1(status, int status)
126{
127 do_PyThread_exit_prog(status, 1);
128}
129#endif /* NO_EXIT_PROG */
130
131/*
132 * Lock support.
133 */
134PyThread_type_lock PyThread_allocate_lock _P0()
135{
136 pth_lock *lock;
137 int status, error = 0;
138
139 dprintf(("PyThread_allocate_lock called\n"));
140 if (!initialized)
141 PyThread_init_thread();
142
143 lock = (pth_lock *) malloc(sizeof(pth_lock));
144 memset((void *)lock, '\0', sizeof(pth_lock));
145 if (lock) {
146 lock->locked = 0;
147 status = pth_mutex_init(&lock->mut);
148 CHECK_STATUS("pth_mutex_init");
149 status = pth_cond_init(&lock->lock_released);
150 CHECK_STATUS("pth_cond_init");
151 if (error) {
152 free((void *)lock);
153 lock = NULL;
154 }
155 }
Fred Drakea44d3532000-06-30 15:01:00 +0000156 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000157 return (PyThread_type_lock) lock;
158}
159
160void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
161{
162 pth_lock *thelock = (pth_lock *)lock;
163 int status, error = 0;
164
Fred Drakea44d3532000-06-30 15:01:00 +0000165 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000166
167 free((void *)thelock);
168}
169
170int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
171{
172 int success;
173 pth_lock *thelock = (pth_lock *)lock;
174 int status, error = 0;
175
Fred Drakea44d3532000-06-30 15:01:00 +0000176 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000177
178 status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
179 CHECK_STATUS("pth_mutex_acquire[1]");
180 success = thelock->locked == 0;
181 if (success) thelock->locked = 1;
182 status = pth_mutex_release( &thelock->mut );
183 CHECK_STATUS("pth_mutex_release[1]");
184
185 if ( !success && waitflag ) {
186 /* continue trying until we get the lock */
187
188 /* mut must be locked by me -- part of the condition
189 * protocol */
190 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
191 CHECK_STATUS("pth_mutex_acquire[2]");
192 while ( thelock->locked ) {
193 status = pth_cond_await(&thelock->lock_released,
194 &thelock->mut, NULL);
195 CHECK_STATUS("pth_cond_await");
196 }
197 thelock->locked = 1;
198 status = pth_mutex_release( &thelock->mut );
199 CHECK_STATUS("pth_mutex_release[2]");
200 success = 1;
201 }
202 if (error) success = 0;
Fred Drakea44d3532000-06-30 15:01:00 +0000203 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000204 return success;
205}
206
207void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
208{
209 pth_lock *thelock = (pth_lock *)lock;
210 int status, error = 0;
211
Fred Drakea44d3532000-06-30 15:01:00 +0000212 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000213
214 status = pth_mutex_acquire( &thelock->mut, 0, NULL );
215 CHECK_STATUS("pth_mutex_acquire[3]");
216
217 thelock->locked = 0;
218
219 status = pth_mutex_release( &thelock->mut );
220 CHECK_STATUS("pth_mutex_release[3]");
221
222 /* wake up someone (anyone, if any) waiting on the lock */
223 status = pth_cond_notify( &thelock->lock_released, 0 );
224 CHECK_STATUS("pth_cond_notify");
225}
226
227/*
228 * Semaphore support.
229 */
230
231struct semaphore {
232 pth_mutex_t mutex;
233 pth_cond_t cond;
234 int value;
235};
236
237PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
238{
239 struct semaphore *sema;
240 int status, error = 0;
241
242 dprintf(("PyThread_allocate_sema called\n"));
243 if (!initialized)
244 PyThread_init_thread();
245
246 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
247 if (sema != NULL) {
248 sema->value = value;
249 status = pth_mutex_init(&sema->mutex);
250 CHECK_STATUS("pth_mutex_init");
251 status = pth_cond_init(&sema->cond);
252 CHECK_STATUS("pth_mutex_init");
253 if (error) {
254 free((void *) sema);
255 sema = NULL;
256 }
257 }
Fred Drakea44d3532000-06-30 15:01:00 +0000258 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000259 return (PyThread_type_sema) sema;
260}
261
262void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
263{
264 int status, error = 0;
265 struct semaphore *thesema = (struct semaphore *) sema;
266
Fred Drakea44d3532000-06-30 15:01:00 +0000267 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000268 free((void *) thesema);
269}
270
271int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
272{
273 int status, error = 0, success;
274 struct semaphore *thesema = (struct semaphore *) sema;
275
Fred Drakea44d3532000-06-30 15:01:00 +0000276 dprintf(("PyThread_down_sema(%p, %d) called\n", sema, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000277 status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
278 CHECK_STATUS("pth_mutex_acquire");
279 if (waitflag) {
280 while (!error && thesema->value <= 0) {
281 status = pth_cond_await(&thesema->cond,
282 &thesema->mutex, NULL);
283 CHECK_STATUS("pth_cond_await");
284 }
285 }
286 if (error)
287 success = 0;
288 else if (thesema->value > 0) {
289 thesema->value--;
290 success = 1;
291 }
292 else
293 success = 0;
294 status = pth_mutex_release(&thesema->mutex);
295 CHECK_STATUS("pth_mutex_release");
Fred Drakea44d3532000-06-30 15:01:00 +0000296 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000297 return success;
298}
299
300void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
301{
302 int status, error = 0;
303 struct semaphore *thesema = (struct semaphore *) sema;
304
Fred Drakea44d3532000-06-30 15:01:00 +0000305 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000306 status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
307 CHECK_STATUS("pth_mutex_acquire");
308 thesema->value++;
309 status = pth_cond_notify(&thesema->cond, 1);
310 CHECK_STATUS("pth_cond_notify");
311 status = pth_mutex_release(&thesema->mutex);
312 CHECK_STATUS("pth_mutex_release");
313}