blob: 608778df0a71615238942013fe49c1c224a8ab44 [file] [log] [blame]
Guido van Rossum07bd90e2000-05-08 13:41:38 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum07bd90e2000-05-08 13:41:38 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum07bd90e2000-05-08 13:41:38 +00009******************************************************************/
10
11/* GNU pth threads interface
12 http://www.gnu.org/software/pth
13 2000-05-03 Andy Dustman <andy@dustman.net>
14
15 Adapted from Posix threads interface
16 12 May 1997 -- david arnold <davida@pobox.com>
17 */
18
19#include <stdlib.h>
20#include <string.h>
21#include <pth.h>
22
23/* A pth mutex isn't sufficient to model the Python lock type
24 * because pth mutexes can be acquired multiple times by the
25 * same thread.
26 *
27 * The pth_lock struct implements a Python lock as a "locked?" bit
28 * and a <condition, mutex> pair. In general, if the bit can be acquired
29 * instantly, it is, else the pair is used to block the thread until the
30 * bit is cleared.
31 */
32
33typedef struct {
34 char locked; /* 0=unlocked, 1=locked */
35 /* a <cond, mutex> pair to handle an acquire of a locked lock */
36 pth_cond_t lock_released;
37 pth_mutex_t mut;
38} pth_lock;
39
40#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
41
42/*
43 * Initialization.
44 */
45
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000046static void PyThread__init_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000047{
48 pth_init();
49}
50
51/*
52 * Thread support.
53 */
54
55
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000056int PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000057{
58 pth_t th;
59 int success;
60 dprintf(("PyThread_start_new_thread called\n"));
61 if (!initialized)
62 PyThread_init_thread();
63
64 th = pth_spawn(PTH_ATTR_DEFAULT,
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000065 (void* (*)(void *))func,
Guido van Rossum07bd90e2000-05-08 13:41:38 +000066 (void *)arg
67 );
68
69 return th == NULL ? 0 : 1;
70}
71
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000072long PyThread_get_thread_ident(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000073{
74 volatile pth_t threadid;
75 if (!initialized)
76 PyThread_init_thread();
77 /* Jump through some hoops for Alpha OSF/1 */
78 threadid = pth_self();
79 return (long) *(long *) &threadid;
80}
81
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000082static void do_PyThread_exit_thread(int no_cleanup)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000083{
84 dprintf(("PyThread_exit_thread called\n"));
85 if (!initialized) {
86 if (no_cleanup)
87 _exit(0);
88 else
89 exit(0);
90 }
91}
92
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000093void PyThread_exit_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000094{
95 do_PyThread_exit_thread(0);
96}
97
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000098void PyThread__exit_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000099{
100 do_PyThread_exit_thread(1);
101}
102
103#ifndef NO_EXIT_PROG
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000104static void do_PyThread_exit_prog(int status, int no_cleanup)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000105{
106 dprintf(("PyThread_exit_prog(%d) called\n", status));
107 if (!initialized)
108 if (no_cleanup)
109 _exit(status);
110 else
111 exit(status);
112}
113
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000114void PyThread_exit_prog(int status)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000115{
116 do_PyThread_exit_prog(status, 0);
117}
118
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000119void PyThread__exit_prog(int status)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000120{
121 do_PyThread_exit_prog(status, 1);
122}
123#endif /* NO_EXIT_PROG */
124
125/*
126 * Lock support.
127 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000128PyThread_type_lock PyThread_allocate_lock(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000129{
130 pth_lock *lock;
131 int status, error = 0;
132
133 dprintf(("PyThread_allocate_lock called\n"));
134 if (!initialized)
135 PyThread_init_thread();
136
137 lock = (pth_lock *) malloc(sizeof(pth_lock));
138 memset((void *)lock, '\0', sizeof(pth_lock));
139 if (lock) {
140 lock->locked = 0;
141 status = pth_mutex_init(&lock->mut);
142 CHECK_STATUS("pth_mutex_init");
143 status = pth_cond_init(&lock->lock_released);
144 CHECK_STATUS("pth_cond_init");
145 if (error) {
146 free((void *)lock);
147 lock = NULL;
148 }
149 }
Fred Drakea44d3532000-06-30 15:01:00 +0000150 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000151 return (PyThread_type_lock) lock;
152}
153
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000154void PyThread_free_lock(PyThread_type_lock lock)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000155{
156 pth_lock *thelock = (pth_lock *)lock;
157 int status, error = 0;
158
Fred Drakea44d3532000-06-30 15:01:00 +0000159 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000160
161 free((void *)thelock);
162}
163
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000164int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000165{
166 int success;
167 pth_lock *thelock = (pth_lock *)lock;
168 int status, error = 0;
169
Fred Drakea44d3532000-06-30 15:01:00 +0000170 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000171
172 status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
173 CHECK_STATUS("pth_mutex_acquire[1]");
174 success = thelock->locked == 0;
175 if (success) thelock->locked = 1;
176 status = pth_mutex_release( &thelock->mut );
177 CHECK_STATUS("pth_mutex_release[1]");
178
179 if ( !success && waitflag ) {
180 /* continue trying until we get the lock */
181
182 /* mut must be locked by me -- part of the condition
183 * protocol */
184 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
185 CHECK_STATUS("pth_mutex_acquire[2]");
186 while ( thelock->locked ) {
187 status = pth_cond_await(&thelock->lock_released,
188 &thelock->mut, NULL);
189 CHECK_STATUS("pth_cond_await");
190 }
191 thelock->locked = 1;
192 status = pth_mutex_release( &thelock->mut );
193 CHECK_STATUS("pth_mutex_release[2]");
194 success = 1;
195 }
196 if (error) success = 0;
Fred Drakea44d3532000-06-30 15:01:00 +0000197 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000198 return success;
199}
200
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000201void PyThread_release_lock(PyThread_type_lock lock)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000202{
203 pth_lock *thelock = (pth_lock *)lock;
204 int status, error = 0;
205
Fred Drakea44d3532000-06-30 15:01:00 +0000206 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000207
208 status = pth_mutex_acquire( &thelock->mut, 0, NULL );
209 CHECK_STATUS("pth_mutex_acquire[3]");
210
211 thelock->locked = 0;
212
213 status = pth_mutex_release( &thelock->mut );
214 CHECK_STATUS("pth_mutex_release[3]");
215
216 /* wake up someone (anyone, if any) waiting on the lock */
217 status = pth_cond_notify( &thelock->lock_released, 0 );
218 CHECK_STATUS("pth_cond_notify");
219}
220
221/*
222 * Semaphore support.
223 */
224
225struct semaphore {
226 pth_mutex_t mutex;
227 pth_cond_t cond;
228 int value;
229};
230
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000231PyThread_type_sema PyThread_allocate_sema(int value)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000232{
233 struct semaphore *sema;
234 int status, error = 0;
235
236 dprintf(("PyThread_allocate_sema called\n"));
237 if (!initialized)
238 PyThread_init_thread();
239
240 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
241 if (sema != NULL) {
242 sema->value = value;
243 status = pth_mutex_init(&sema->mutex);
244 CHECK_STATUS("pth_mutex_init");
245 status = pth_cond_init(&sema->cond);
246 CHECK_STATUS("pth_mutex_init");
247 if (error) {
248 free((void *) sema);
249 sema = NULL;
250 }
251 }
Fred Drakea44d3532000-06-30 15:01:00 +0000252 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000253 return (PyThread_type_sema) sema;
254}
255
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000256void PyThread_free_sema(PyThread_type_sema sema)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000257{
258 int status, error = 0;
259 struct semaphore *thesema = (struct semaphore *) sema;
260
Fred Drakea44d3532000-06-30 15:01:00 +0000261 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000262 free((void *) thesema);
263}
264
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000265int PyThread_down_sema(PyThread_type_sema sema, int waitflag)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000266{
267 int status, error = 0, success;
268 struct semaphore *thesema = (struct semaphore *) sema;
269
Fred Drakea44d3532000-06-30 15:01:00 +0000270 dprintf(("PyThread_down_sema(%p, %d) called\n", sema, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000271 status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
272 CHECK_STATUS("pth_mutex_acquire");
273 if (waitflag) {
274 while (!error && thesema->value <= 0) {
275 status = pth_cond_await(&thesema->cond,
276 &thesema->mutex, NULL);
277 CHECK_STATUS("pth_cond_await");
278 }
279 }
280 if (error)
281 success = 0;
282 else if (thesema->value > 0) {
283 thesema->value--;
284 success = 1;
285 }
286 else
287 success = 0;
288 status = pth_mutex_release(&thesema->mutex);
289 CHECK_STATUS("pth_mutex_release");
Fred Drakea44d3532000-06-30 15:01:00 +0000290 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000291 return success;
292}
293
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000294void PyThread_up_sema(PyThread_type_sema sema)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000295{
296 int status, error = 0;
297 struct semaphore *thesema = (struct semaphore *) sema;
298
Fred Drakea44d3532000-06-30 15:01:00 +0000299 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000300 status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
301 CHECK_STATUS("pth_mutex_acquire");
302 thesema->value++;
303 status = pth_cond_notify(&thesema->cond, 1);
304 CHECK_STATUS("pth_cond_notify");
305 status = pth_mutex_release(&thesema->mutex);
306 CHECK_STATUS("pth_mutex_release");
307}