source: python/trunk/Python/thread_os2.h@ 390

Last change on this file since 390 was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 5.6 KB
Line 
1/* 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
10#if defined(PYCC_GCC)
11#include <sys/builtin.h>
12#include <sys/fmutex.h>
13#else
14long PyThread_get_thread_ident(void);
15#endif
16
17/* default thread stack size of 64kB */
18#if !defined(THREAD_STACK_SIZE)
19#define THREAD_STACK_SIZE 0x10000
20#endif
21
22#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
23
24/*
25 * Initialization of the C package, should not be needed.
26 */
27static void
28PyThread__init_thread(void)
29{
30}
31
32/*
33 * Thread support.
34 */
35long
36PyThread_start_new_thread(void (*func)(void *), void *arg)
37{
38 int thread_id;
39
40 thread_id = _beginthread(func,
41 NULL,
42 OS2_STACKSIZE(_pythread_stacksize),
43 arg);
44
45 if (thread_id == -1) {
46 dprintf(("_beginthread failed. return %ld\n", errno));
47 }
48
49 return thread_id;
50}
51
52long
53PyThread_get_thread_ident(void)
54{
55#if !defined(PYCC_GCC)
56 PPIB pib;
57 PTIB tib;
58#endif
59
60 if (!initialized)
61 PyThread_init_thread();
62
63#if defined(PYCC_GCC)
64 return _gettid();
65#else
66 DosGetInfoBlocks(&tib, &pib);
67 return tib->tib_ptib2->tib2_ultid;
68#endif
69}
70
71static void
72do_PyThread_exit_thread(int no_cleanup)
73{
74 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();
82}
83
84void
85PyThread_exit_thread(void)
86{
87 do_PyThread_exit_thread(0);
88}
89
90void
91PyThread__exit_thread(void)
92{
93 do_PyThread_exit_thread(1);
94}
95
96#ifndef NO_EXIT_PROG
97static void
98do_PyThread_exit_prog(int status, int no_cleanup)
99{
100 dprintf(("PyThread_exit_prog(%d) called\n", status));
101 if (!initialized)
102 if (no_cleanup)
103 _exit(status);
104 else
105 exit(status);
106}
107
108void
109PyThread_exit_prog(int status)
110{
111 do_PyThread_exit_prog(status, 0);
112}
113
114void
115PyThread__exit_prog(int status)
116{
117 do_PyThread_exit_prog(status, 1);
118}
119#endif /* NO_EXIT_PROG */
120
121/*
122 * 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
124 * counterparts.
125 */
126
127typedef struct os2_lock_t {
128 int is_set;
129 HEV changed;
130} *type_os2_lock;
131
132PyThread_type_lock
133PyThread_allocate_lock(void)
134{
135#if defined(PYCC_GCC)
136 _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;
147#else
148 APIRET rc;
149 type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
150
151 dprintf(("PyThread_allocate_lock called\n"));
152 if (!initialized)
153 PyThread_init_thread();
154
155 lock->is_set = 0;
156
157 DosCreateEventSem(NULL, &lock->changed, 0, 0);
158
159 dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
160 PyThread_get_thread_ident(),
161 lock->changed));
162
163 return (PyThread_type_lock)lock;
164#endif
165}
166
167void
168PyThread_free_lock(PyThread_type_lock aLock)
169{
170#if !defined(PYCC_GCC)
171 type_os2_lock lock = (type_os2_lock)aLock;
172#endif
173
174 dprintf(("%ld: PyThread_free_lock(%p) called\n",
175 PyThread_get_thread_ident(),aLock));
176
177#if defined(PYCC_GCC)
178 if (aLock) {
179 _fmutex_close((_fmutex *)aLock);
180 free((_fmutex *)aLock);
181 }
182#else
183 DosCloseEventSem(lock->changed);
184 free(aLock);
185#endif
186}
187
188/*
189 * Return 1 on success if the lock was acquired
190 *
191 * and 0 if the lock was not acquired.
192 */
193int
194PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
195{
196#if !defined(PYCC_GCC)
197 int done = 0;
198 ULONG count;
199 PID pid = 0;
200 TID tid = 0;
201 type_os2_lock lock = (type_os2_lock)aLock;
202#endif
203
204 dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
205 PyThread_get_thread_ident(),
206 aLock,
207 waitflag));
208
209#if defined(PYCC_GCC)
210 /* always successful if the lock doesn't exist */
211 if (aLock &&
212 _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
213 return 0;
214#else
215 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 }
224
225 /* 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;
230
231 if (!lock->is_set) {
232 lock->is_set = 1;
233 DosResetEventSem(lock->changed, &count);
234 done = 1;
235 }
236
237 DosExitCritSec();
238 }
239#endif
240
241 return 1;
242}
243
244void
245PyThread_release_lock(PyThread_type_lock aLock)
246{
247#if !defined(PYCC_GCC)
248 type_os2_lock lock = (type_os2_lock)aLock;
249#endif
250
251 dprintf(("%ld: PyThread_release_lock(%p) called\n",
252 PyThread_get_thread_ident(),
253 aLock));
254
255#if defined(PYCC_GCC)
256 if (aLock)
257 _fmutex_release((_fmutex *)aLock);
258#else
259 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 }
266
267 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 }
274
275 lock->is_set = 0;
276 DosPostEventSem(lock->changed);
277
278 DosExitCritSec();
279#endif
280}
281
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)
Note: See TracBrowser for help on using the repository browser.