_make_boundary(): Fix for SF bug #745478, broken boundary calculation
[python/dscho.git] / Python / thread_os2.h
blobeeefe03760029a12a591ae9947d7bd02eef6835f
1 /* This code implemented by cvale@netcom.com */
3 #define INCL_DOSPROCESS
4 #define INCL_DOSSEMAPHORES
5 #include "os2.h"
6 #include "limits.h"
8 #include "process.h"
10 #if defined(PYCC_GCC)
11 #include <sys/builtin.h>
12 #include <sys/fmutex.h>
13 #else
14 long PyThread_get_thread_ident(void);
15 #endif
18 * Initialization of the C package, should not be needed.
20 static void
21 PyThread__init_thread(void)
26 * Thread support.
28 long
29 PyThread_start_new_thread(void (*func)(void *), void *arg)
31 int aThread;
32 int success = 0;
34 aThread = _beginthread(func,NULL,65536,arg);
36 if (aThread == -1) {
37 success = -1;
38 fprintf(stderr, "aThread failed == %d", aThread);
39 dprintf(("_beginthread failed. return %ld\n", errno));
42 return success;
45 long
46 PyThread_get_thread_ident(void)
48 #if !defined(PYCC_GCC)
49 PPIB pib;
50 PTIB tib;
51 #endif
53 if (!initialized)
54 PyThread_init_thread();
56 #if defined(PYCC_GCC)
57 return _gettid();
58 #else
59 DosGetInfoBlocks(&tib, &pib);
60 return tib->tib_ptib2->tib2_ultid;
61 #endif
64 static void
65 do_PyThread_exit_thread(int no_cleanup)
67 dprintf(("%ld: PyThread_exit_thread called\n",
68 PyThread_get_thread_ident()));
69 if (!initialized)
70 if (no_cleanup)
71 _exit(0);
72 else
73 exit(0);
74 _endthread();
77 void
78 PyThread_exit_thread(void)
80 do_PyThread_exit_thread(0);
83 void
84 PyThread__exit_thread(void)
86 do_PyThread_exit_thread(1);
89 #ifndef NO_EXIT_PROG
90 static void
91 do_PyThread_exit_prog(int status, int no_cleanup)
93 dprintf(("PyThread_exit_prog(%d) called\n", status));
94 if (!initialized)
95 if (no_cleanup)
96 _exit(status);
97 else
98 exit(status);
101 void
102 PyThread_exit_prog(int status)
104 do_PyThread_exit_prog(status, 0);
107 void
108 PyThread__exit_prog(int status)
110 do_PyThread_exit_prog(status, 1);
112 #endif /* NO_EXIT_PROG */
115 * Lock support. This is implemented with an event semaphore and critical
116 * sections to make it behave more like a posix mutex than its OS/2
117 * counterparts.
120 typedef struct os2_lock_t {
121 int is_set;
122 HEV changed;
123 } *type_os2_lock;
125 PyThread_type_lock
126 PyThread_allocate_lock(void)
128 #if defined(PYCC_GCC)
129 _fmutex *sem = malloc(sizeof(_fmutex));
130 if (!initialized)
131 PyThread_init_thread();
132 dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
133 PyThread_get_thread_ident(),
134 (long)sem));
135 if (_fmutex_create(sem, 0)) {
136 free(sem);
137 sem = NULL;
139 return (PyThread_type_lock)sem;
140 #else
141 APIRET rc;
142 type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
144 dprintf(("PyThread_allocate_lock called\n"));
145 if (!initialized)
146 PyThread_init_thread();
148 lock->is_set = 0;
150 DosCreateEventSem(NULL, &lock->changed, 0, 0);
152 dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
153 PyThread_get_thread_ident(),
154 lock->changed));
156 return (PyThread_type_lock)lock;
157 #endif
160 void
161 PyThread_free_lock(PyThread_type_lock aLock)
163 #if !defined(PYCC_GCC)
164 type_os2_lock lock = (type_os2_lock)aLock;
165 #endif
167 dprintf(("%ld: PyThread_free_lock(%p) called\n",
168 PyThread_get_thread_ident(),aLock));
170 #if defined(PYCC_GCC)
171 if (aLock) {
172 _fmutex_close((_fmutex *)aLock);
173 free((_fmutex *)aLock);
175 #else
176 DosCloseEventSem(lock->changed);
177 free(aLock);
178 #endif
182 * Return 1 on success if the lock was acquired
184 * and 0 if the lock was not acquired.
186 int
187 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
189 #if !defined(PYCC_GCC)
190 int done = 0;
191 ULONG count;
192 PID pid = 0;
193 TID tid = 0;
194 type_os2_lock lock = (type_os2_lock)aLock;
195 #endif
197 dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
198 PyThread_get_thread_ident(),
199 aLock,
200 waitflag));
202 #if defined(PYCC_GCC)
203 /* always successful if the lock doesn't exist */
204 if (aLock &&
205 _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
206 return 0;
207 #else
208 while (!done) {
209 /* if the lock is currently set, we have to wait for
210 * the state to change
212 if (lock->is_set) {
213 if (!waitflag)
214 return 0;
215 DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
218 /* enter a critical section and try to get the semaphore. If
219 * it is still locked, we will try again.
221 if (DosEnterCritSec())
222 return 0;
224 if (!lock->is_set) {
225 lock->is_set = 1;
226 DosResetEventSem(lock->changed, &count);
227 done = 1;
230 DosExitCritSec();
232 #endif
234 return 1;
237 void PyThread_release_lock(PyThread_type_lock aLock)
239 #if !defined(PYCC_GCC)
240 type_os2_lock lock = (type_os2_lock)aLock;
241 #endif
243 dprintf(("%ld: PyThread_release_lock(%p) called\n",
244 PyThread_get_thread_ident(),
245 aLock));
247 #if defined(PYCC_GCC)
248 if (aLock)
249 _fmutex_release((_fmutex *)aLock);
250 #else
251 if (!lock->is_set) {
252 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
253 PyThread_get_thread_ident(),
254 aLock,
255 GetLastError()));
256 return;
259 if (DosEnterCritSec()) {
260 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
261 PyThread_get_thread_ident(),
262 aLock,
263 GetLastError()));
264 return;
267 lock->is_set = 0;
268 DosPostEventSem(lock->changed);
270 DosExitCritSec();
271 #endif