blob: a5ae91b6aaec1bae1f5252b412d4e8609ab272ba [file] [log] [blame]
Guido van Rossum07bd90e2000-05-08 13:41:38 +00001
2/* GNU pth threads interface
3 http://www.gnu.org/software/pth
4 2000-05-03 Andy Dustman <andy@dustman.net>
5
6 Adapted from Posix threads interface
7 12 May 1997 -- david arnold <davida@pobox.com>
8 */
9
10#include <stdlib.h>
11#include <string.h>
12#include <pth.h>
13
14/* A pth mutex isn't sufficient to model the Python lock type
15 * because pth mutexes can be acquired multiple times by the
16 * same thread.
17 *
18 * The pth_lock struct implements a Python lock as a "locked?" bit
19 * and a <condition, mutex> pair. In general, if the bit can be acquired
20 * instantly, it is, else the pair is used to block the thread until the
21 * bit is cleared.
22 */
23
24typedef struct {
25 char locked; /* 0=unlocked, 1=locked */
26 /* a <cond, mutex> pair to handle an acquire of a locked lock */
27 pth_cond_t lock_released;
28 pth_mutex_t mut;
29} pth_lock;
30
31#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
32
33/*
34 * Initialization.
35 */
36
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000037static void PyThread__init_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000038{
39 pth_init();
40}
41
42/*
43 * Thread support.
44 */
45
46
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000047int PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000048{
49 pth_t th;
50 int success;
51 dprintf(("PyThread_start_new_thread called\n"));
52 if (!initialized)
53 PyThread_init_thread();
54
55 th = pth_spawn(PTH_ATTR_DEFAULT,
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000056 (void* (*)(void *))func,
Guido van Rossum07bd90e2000-05-08 13:41:38 +000057 (void *)arg
58 );
59
60 return th == NULL ? 0 : 1;
61}
62
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000063long PyThread_get_thread_ident(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000064{
65 volatile pth_t threadid;
66 if (!initialized)
67 PyThread_init_thread();
68 /* Jump through some hoops for Alpha OSF/1 */
69 threadid = pth_self();
70 return (long) *(long *) &threadid;
71}
72
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000073static void do_PyThread_exit_thread(int no_cleanup)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000074{
75 dprintf(("PyThread_exit_thread called\n"));
76 if (!initialized) {
77 if (no_cleanup)
78 _exit(0);
79 else
80 exit(0);
81 }
82}
83
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000084void PyThread_exit_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000085{
86 do_PyThread_exit_thread(0);
87}
88
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000089void PyThread__exit_thread(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000090{
91 do_PyThread_exit_thread(1);
92}
93
94#ifndef NO_EXIT_PROG
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000095static void do_PyThread_exit_prog(int status, int no_cleanup)
Guido van Rossum07bd90e2000-05-08 13:41:38 +000096{
97 dprintf(("PyThread_exit_prog(%d) called\n", status));
98 if (!initialized)
99 if (no_cleanup)
100 _exit(status);
101 else
102 exit(status);
103}
104
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000105void PyThread_exit_prog(int status)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000106{
107 do_PyThread_exit_prog(status, 0);
108}
109
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000110void PyThread__exit_prog(int status)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000111{
112 do_PyThread_exit_prog(status, 1);
113}
114#endif /* NO_EXIT_PROG */
115
116/*
117 * Lock support.
118 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000119PyThread_type_lock PyThread_allocate_lock(void)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000120{
121 pth_lock *lock;
122 int status, error = 0;
123
124 dprintf(("PyThread_allocate_lock called\n"));
125 if (!initialized)
126 PyThread_init_thread();
127
128 lock = (pth_lock *) malloc(sizeof(pth_lock));
129 memset((void *)lock, '\0', sizeof(pth_lock));
130 if (lock) {
131 lock->locked = 0;
132 status = pth_mutex_init(&lock->mut);
133 CHECK_STATUS("pth_mutex_init");
134 status = pth_cond_init(&lock->lock_released);
135 CHECK_STATUS("pth_cond_init");
136 if (error) {
137 free((void *)lock);
138 lock = NULL;
139 }
140 }
Fred Drakea44d3532000-06-30 15:01:00 +0000141 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000142 return (PyThread_type_lock) lock;
143}
144
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000145void PyThread_free_lock(PyThread_type_lock lock)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000146{
147 pth_lock *thelock = (pth_lock *)lock;
148 int status, error = 0;
149
Fred Drakea44d3532000-06-30 15:01:00 +0000150 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000151
152 free((void *)thelock);
153}
154
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000155int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000156{
157 int success;
158 pth_lock *thelock = (pth_lock *)lock;
159 int status, error = 0;
160
Fred Drakea44d3532000-06-30 15:01:00 +0000161 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000162
163 status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
164 CHECK_STATUS("pth_mutex_acquire[1]");
165 success = thelock->locked == 0;
166 if (success) thelock->locked = 1;
167 status = pth_mutex_release( &thelock->mut );
168 CHECK_STATUS("pth_mutex_release[1]");
169
170 if ( !success && waitflag ) {
171 /* continue trying until we get the lock */
172
173 /* mut must be locked by me -- part of the condition
174 * protocol */
175 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
176 CHECK_STATUS("pth_mutex_acquire[2]");
177 while ( thelock->locked ) {
178 status = pth_cond_await(&thelock->lock_released,
179 &thelock->mut, NULL);
180 CHECK_STATUS("pth_cond_await");
181 }
182 thelock->locked = 1;
183 status = pth_mutex_release( &thelock->mut );
184 CHECK_STATUS("pth_mutex_release[2]");
185 success = 1;
186 }
187 if (error) success = 0;
Fred Drakea44d3532000-06-30 15:01:00 +0000188 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000189 return success;
190}
191
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000192void PyThread_release_lock(PyThread_type_lock lock)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000193{
194 pth_lock *thelock = (pth_lock *)lock;
195 int status, error = 0;
196
Fred Drakea44d3532000-06-30 15:01:00 +0000197 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000198
199 status = pth_mutex_acquire( &thelock->mut, 0, NULL );
200 CHECK_STATUS("pth_mutex_acquire[3]");
201
202 thelock->locked = 0;
203
204 status = pth_mutex_release( &thelock->mut );
205 CHECK_STATUS("pth_mutex_release[3]");
206
207 /* wake up someone (anyone, if any) waiting on the lock */
208 status = pth_cond_notify( &thelock->lock_released, 0 );
209 CHECK_STATUS("pth_cond_notify");
210}
211
212/*
213 * Semaphore support.
214 */
215
216struct semaphore {
217 pth_mutex_t mutex;
218 pth_cond_t cond;
219 int value;
220};
221
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000222PyThread_type_sema PyThread_allocate_sema(int value)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000223{
224 struct semaphore *sema;
225 int status, error = 0;
226
227 dprintf(("PyThread_allocate_sema called\n"));
228 if (!initialized)
229 PyThread_init_thread();
230
231 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
232 if (sema != NULL) {
233 sema->value = value;
234 status = pth_mutex_init(&sema->mutex);
235 CHECK_STATUS("pth_mutex_init");
236 status = pth_cond_init(&sema->cond);
237 CHECK_STATUS("pth_mutex_init");
238 if (error) {
239 free((void *) sema);
240 sema = NULL;
241 }
242 }
Fred Drakea44d3532000-06-30 15:01:00 +0000243 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000244 return (PyThread_type_sema) sema;
245}
246
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000247void PyThread_free_sema(PyThread_type_sema sema)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000248{
249 int status, error = 0;
250 struct semaphore *thesema = (struct semaphore *) sema;
251
Fred Drakea44d3532000-06-30 15:01:00 +0000252 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000253 free((void *) thesema);
254}
255
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000256int PyThread_down_sema(PyThread_type_sema sema, int waitflag)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000257{
258 int status, error = 0, success;
259 struct semaphore *thesema = (struct semaphore *) sema;
260
Fred Drakea44d3532000-06-30 15:01:00 +0000261 dprintf(("PyThread_down_sema(%p, %d) called\n", sema, waitflag));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000262 status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
263 CHECK_STATUS("pth_mutex_acquire");
264 if (waitflag) {
265 while (!error && thesema->value <= 0) {
266 status = pth_cond_await(&thesema->cond,
267 &thesema->mutex, NULL);
268 CHECK_STATUS("pth_cond_await");
269 }
270 }
271 if (error)
272 success = 0;
273 else if (thesema->value > 0) {
274 thesema->value--;
275 success = 1;
276 }
277 else
278 success = 0;
279 status = pth_mutex_release(&thesema->mutex);
280 CHECK_STATUS("pth_mutex_release");
Fred Drakea44d3532000-06-30 15:01:00 +0000281 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000282 return success;
283}
284
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000285void PyThread_up_sema(PyThread_type_sema sema)
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000286{
287 int status, error = 0;
288 struct semaphore *thesema = (struct semaphore *) sema;
289
Fred Drakea44d3532000-06-30 15:01:00 +0000290 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum07bd90e2000-05-08 13:41:38 +0000291 status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
292 CHECK_STATUS("pth_mutex_acquire");
293 thesema->value++;
294 status = pth_cond_notify(&thesema->cond, 1);
295 CHECK_STATUS("pth_cond_notify");
296 status = pth_mutex_release(&thesema->mutex);
297 CHECK_STATUS("pth_mutex_release");
298}