blob: 12eeed51c46b06aa1dd9e3748c1a1421721e0866 [file] [log] [blame]
Guido van Rossum62332931995-04-10 11:36:14 +00001/* This code implemented by cvale@netcom.com */
2
3#define INCL_DOSPROCESS
4#define INCL_DOSSEMAPHORES
5#include "os2.h"
6#include "limits.h"
7
8#include "process.h"
9
Andrew MacIntyred9400542002-02-26 11:41:34 +000010#if defined(PYCC_GCC)
11#include <sys/builtin.h>
12#include <sys/fmutex.h>
13#else
Guido van Rossum65d5b571998-12-21 19:32:43 +000014long PyThread_get_thread_ident(void);
Andrew MacIntyred9400542002-02-26 11:41:34 +000015#endif
Guido van Rossum62332931995-04-10 11:36:14 +000016
Thomas Wouters0e3f5912006-08-11 14:57:12 +000017/* default thread stack size of 64kB */
Andrew MacIntyre2bea4742005-01-17 12:16:36 +000018#if !defined(THREAD_STACK_SIZE)
19#define THREAD_STACK_SIZE 0x10000
20#endif
21
Thomas Wouters0e3f5912006-08-11 14:57:12 +000022#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
23
Guido van Rossum62332931995-04-10 11:36:14 +000024/*
25 * Initialization of the C package, should not be needed.
26 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000027static void
28PyThread__init_thread(void)
Guido van Rossum62332931995-04-10 11:36:14 +000029{
30}
31
32/*
33 * Thread support.
34 */
Guido van Rossum3c288632001-10-16 21:13:49 +000035long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000036PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum62332931995-04-10 11:36:14 +000037{
Thomas Wouters0e3f5912006-08-11 14:57:12 +000038 int thread_id;
Guido van Rossum62332931995-04-10 11:36:14 +000039
Thomas Wouters0e3f5912006-08-11 14:57:12 +000040 thread_id = _beginthread(func,
41 NULL,
42 OS2_STACKSIZE(_pythread_stacksize),
43 arg);
Guido van Rossum62332931995-04-10 11:36:14 +000044
Thomas Wouters0e3f5912006-08-11 14:57:12 +000045 if (thread_id == -1) {
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000046 dprintf(("_beginthread failed. return %ld\n", errno));
47 }
Guido van Rossum62332931995-04-10 11:36:14 +000048
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049 return thread_id;
Guido van Rossum62332931995-04-10 11:36:14 +000050}
51
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000052long
53PyThread_get_thread_ident(void)
Guido van Rossum62332931995-04-10 11:36:14 +000054{
Andrew MacIntyred9400542002-02-26 11:41:34 +000055#if !defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000056 PPIB pib;
57 PTIB tib;
Andrew MacIntyred9400542002-02-26 11:41:34 +000058#endif
Guido van Rossum62332931995-04-10 11:36:14 +000059
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000060 if (!initialized)
61 PyThread_init_thread();
62
Andrew MacIntyred9400542002-02-26 11:41:34 +000063#if defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000064 return _gettid();
Andrew MacIntyred9400542002-02-26 11:41:34 +000065#else
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000066 DosGetInfoBlocks(&tib, &pib);
67 return tib->tib_ptib2->tib2_ultid;
Andrew MacIntyred9400542002-02-26 11:41:34 +000068#endif
Guido van Rossum62332931995-04-10 11:36:14 +000069}
70
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000071static void
72do_PyThread_exit_thread(int no_cleanup)
Guido van Rossum62332931995-04-10 11:36:14 +000073{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000074 dprintf(("%ld: PyThread_exit_thread called\n",
75 PyThread_get_thread_ident()));
76 if (!initialized)
77 if (no_cleanup)
78 _exit(0);
79 else
80 exit(0);
81 _endthread();
Guido van Rossum62332931995-04-10 11:36:14 +000082}
83
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000084void
85PyThread_exit_thread(void)
Guido van Rossum62332931995-04-10 11:36:14 +000086{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000087 do_PyThread_exit_thread(0);
Guido van Rossum62332931995-04-10 11:36:14 +000088}
89
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000090void
91PyThread__exit_thread(void)
Guido van Rossum62332931995-04-10 11:36:14 +000092{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +000093 do_PyThread_exit_thread(1);
Guido van Rossum62332931995-04-10 11:36:14 +000094}
95
96#ifndef NO_EXIT_PROG
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000097static void
98do_PyThread_exit_prog(int status, int no_cleanup)
Guido van Rossum62332931995-04-10 11:36:14 +000099{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000100 dprintf(("PyThread_exit_prog(%d) called\n", status));
101 if (!initialized)
102 if (no_cleanup)
103 _exit(status);
104 else
105 exit(status);
Guido van Rossum62332931995-04-10 11:36:14 +0000106}
107
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000108void
109PyThread_exit_prog(int status)
Guido van Rossum62332931995-04-10 11:36:14 +0000110{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000111 do_PyThread_exit_prog(status, 0);
Guido van Rossum62332931995-04-10 11:36:14 +0000112}
113
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000114void
115PyThread__exit_prog(int status)
Guido van Rossum62332931995-04-10 11:36:14 +0000116{
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000117 do_PyThread_exit_prog(status, 1);
Guido van Rossum62332931995-04-10 11:36:14 +0000118}
119#endif /* NO_EXIT_PROG */
120
121/*
Tim Petersa6ca4f42001-10-31 03:50:45 +0000122 * Lock support. This is implemented with an event semaphore and critical
123 * sections to make it behave more like a posix mutex than its OS/2
Andrew MacIntyred9400542002-02-26 11:41:34 +0000124 * counterparts.
Guido van Rossum62332931995-04-10 11:36:14 +0000125 */
Tim Petersa6ca4f42001-10-31 03:50:45 +0000126
127typedef struct os2_lock_t {
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000128 int is_set;
129 HEV changed;
Tim Petersa6ca4f42001-10-31 03:50:45 +0000130} *type_os2_lock;
131
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000132PyThread_type_lock
133PyThread_allocate_lock(void)
Guido van Rossum62332931995-04-10 11:36:14 +0000134{
Andrew MacIntyred9400542002-02-26 11:41:34 +0000135#if defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000136 _fmutex *sem = malloc(sizeof(_fmutex));
137 if (!initialized)
138 PyThread_init_thread();
139 dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
140 PyThread_get_thread_ident(),
141 (long)sem));
142 if (_fmutex_create(sem, 0)) {
143 free(sem);
144 sem = NULL;
145 }
146 return (PyThread_type_lock)sem;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000147#else
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000148 APIRET rc;
149 type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
Guido van Rossum62332931995-04-10 11:36:14 +0000150
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000151 dprintf(("PyThread_allocate_lock called\n"));
152 if (!initialized)
153 PyThread_init_thread();
Guido van Rossum62332931995-04-10 11:36:14 +0000154
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000155 lock->is_set = 0;
Guido van Rossum62332931995-04-10 11:36:14 +0000156
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000157 DosCreateEventSem(NULL, &lock->changed, 0, 0);
Guido van Rossum62332931995-04-10 11:36:14 +0000158
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000159 dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
160 PyThread_get_thread_ident(),
161 lock->changed));
Tim Petersa6ca4f42001-10-31 03:50:45 +0000162
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000163 return (PyThread_type_lock)lock;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000164#endif
Guido van Rossum62332931995-04-10 11:36:14 +0000165}
166
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000167void
168PyThread_free_lock(PyThread_type_lock aLock)
Guido van Rossum62332931995-04-10 11:36:14 +0000169{
Andrew MacIntyred9400542002-02-26 11:41:34 +0000170#if !defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000171 type_os2_lock lock = (type_os2_lock)aLock;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000172#endif
173
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000174 dprintf(("%ld: PyThread_free_lock(%p) called\n",
175 PyThread_get_thread_ident(),aLock));
Guido van Rossum62332931995-04-10 11:36:14 +0000176
Andrew MacIntyred9400542002-02-26 11:41:34 +0000177#if defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000178 if (aLock) {
179 _fmutex_close((_fmutex *)aLock);
180 free((_fmutex *)aLock);
181 }
Andrew MacIntyred9400542002-02-26 11:41:34 +0000182#else
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000183 DosCloseEventSem(lock->changed);
184 free(aLock);
Andrew MacIntyred9400542002-02-26 11:41:34 +0000185#endif
Guido van Rossum62332931995-04-10 11:36:14 +0000186}
187
188/*
189 * Return 1 on success if the lock was acquired
190 *
Tim Petersa6ca4f42001-10-31 03:50:45 +0000191 * and 0 if the lock was not acquired.
Guido van Rossum62332931995-04-10 11:36:14 +0000192 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000193int
194PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
Guido van Rossum62332931995-04-10 11:36:14 +0000195{
Andrew MacIntyred9400542002-02-26 11:41:34 +0000196#if !defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000197 int done = 0;
198 ULONG count;
199 PID pid = 0;
200 TID tid = 0;
201 type_os2_lock lock = (type_os2_lock)aLock;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000202#endif
Guido van Rossum62332931995-04-10 11:36:14 +0000203
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000204 dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
205 PyThread_get_thread_ident(),
206 aLock,
207 waitflag));
Guido van Rossum62332931995-04-10 11:36:14 +0000208
Andrew MacIntyred9400542002-02-26 11:41:34 +0000209#if defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000210 /* always successful if the lock doesn't exist */
211 if (aLock &&
212 _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
213 return 0;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000214#else
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000215 while (!done) {
216 /* if the lock is currently set, we have to wait for
217 * the state to change
218 */
219 if (lock->is_set) {
220 if (!waitflag)
221 return 0;
222 DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
223 }
Tim Petersa6ca4f42001-10-31 03:50:45 +0000224
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000225 /* enter a critical section and try to get the semaphore. If
226 * it is still locked, we will try again.
227 */
228 if (DosEnterCritSec())
229 return 0;
Tim Petersa6ca4f42001-10-31 03:50:45 +0000230
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000231 if (!lock->is_set) {
232 lock->is_set = 1;
233 DosResetEventSem(lock->changed, &count);
234 done = 1;
235 }
236
237 DosExitCritSec();
238 }
Andrew MacIntyred9400542002-02-26 11:41:34 +0000239#endif
Guido van Rossum62332931995-04-10 11:36:14 +0000240
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000241 return 1;
Guido van Rossum62332931995-04-10 11:36:14 +0000242}
243
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244void
245PyThread_release_lock(PyThread_type_lock aLock)
Guido van Rossum62332931995-04-10 11:36:14 +0000246{
Andrew MacIntyre69049592002-12-04 12:27:06 +0000247#if !defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000248 type_os2_lock lock = (type_os2_lock)aLock;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000249#endif
250
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000251 dprintf(("%ld: PyThread_release_lock(%p) called\n",
252 PyThread_get_thread_ident(),
253 aLock));
Guido van Rossum62332931995-04-10 11:36:14 +0000254
Andrew MacIntyred9400542002-02-26 11:41:34 +0000255#if defined(PYCC_GCC)
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000256 if (aLock)
257 _fmutex_release((_fmutex *)aLock);
Andrew MacIntyred9400542002-02-26 11:41:34 +0000258#else
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000259 if (!lock->is_set) {
260 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
261 PyThread_get_thread_ident(),
262 aLock,
263 GetLastError()));
264 return;
265 }
Tim Petersa6ca4f42001-10-31 03:50:45 +0000266
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000267 if (DosEnterCritSec()) {
268 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
269 PyThread_get_thread_ident(),
270 aLock,
271 GetLastError()));
272 return;
273 }
Tim Petersa6ca4f42001-10-31 03:50:45 +0000274
Andrew MacIntyrec4c127b2002-12-04 12:29:37 +0000275 lock->is_set = 0;
276 DosPostEventSem(lock->changed);
277
278 DosExitCritSec();
Andrew MacIntyred9400542002-02-26 11:41:34 +0000279#endif
Guido van Rossum62332931995-04-10 11:36:14 +0000280}
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000281
282/* minimum/maximum thread stack sizes supported */
283#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
284#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
285
286/* set the thread stack size.
287 * Return 0 if size is valid, -1 otherwise.
288 */
289static int
290_pythread_os2_set_stacksize(size_t size)
291{
292 /* set to default */
293 if (size == 0) {
294 _pythread_stacksize = 0;
295 return 0;
296 }
297
298 /* valid range? */
299 if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
300 _pythread_stacksize = size;
301 return 0;
302 }
303
304 return -1;
305}
306
307#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)