This commit was manufactured by cvs2svn to create tag 'r241c1'.
[python/dscho.git] / Python / thread_os2.h
bloba18ce6fd6c7a2b73319e6068d05a22f5a097d5d3
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
17 #if !defined(THREAD_STACK_SIZE)
18 #define THREAD_STACK_SIZE 0x10000
19 #endif
22 * Initialization of the C package, should not be needed.
24 static void
25 PyThread__init_thread(void)
30 * Thread support.
32 long
33 PyThread_start_new_thread(void (*func)(void *), void *arg)
35 int aThread;
36 int success = 0;
38 aThread = _beginthread(func, NULL, THREAD_STACK_SIZE, arg);
40 if (aThread == -1) {
41 success = -1;
42 fprintf(stderr, "aThread failed == %d", aThread);
43 dprintf(("_beginthread failed. return %ld\n", errno));
46 return success;
49 long
50 PyThread_get_thread_ident(void)
52 #if !defined(PYCC_GCC)
53 PPIB pib;
54 PTIB tib;
55 #endif
57 if (!initialized)
58 PyThread_init_thread();
60 #if defined(PYCC_GCC)
61 return _gettid();
62 #else
63 DosGetInfoBlocks(&tib, &pib);
64 return tib->tib_ptib2->tib2_ultid;
65 #endif
68 static void
69 do_PyThread_exit_thread(int no_cleanup)
71 dprintf(("%ld: PyThread_exit_thread called\n",
72 PyThread_get_thread_ident()));
73 if (!initialized)
74 if (no_cleanup)
75 _exit(0);
76 else
77 exit(0);
78 _endthread();
81 void
82 PyThread_exit_thread(void)
84 do_PyThread_exit_thread(0);
87 void
88 PyThread__exit_thread(void)
90 do_PyThread_exit_thread(1);
93 #ifndef NO_EXIT_PROG
94 static void
95 do_PyThread_exit_prog(int status, int no_cleanup)
97 dprintf(("PyThread_exit_prog(%d) called\n", status));
98 if (!initialized)
99 if (no_cleanup)
100 _exit(status);
101 else
102 exit(status);
105 void
106 PyThread_exit_prog(int status)
108 do_PyThread_exit_prog(status, 0);
111 void
112 PyThread__exit_prog(int status)
114 do_PyThread_exit_prog(status, 1);
116 #endif /* NO_EXIT_PROG */
119 * Lock support. This is implemented with an event semaphore and critical
120 * sections to make it behave more like a posix mutex than its OS/2
121 * counterparts.
124 typedef struct os2_lock_t {
125 int is_set;
126 HEV changed;
127 } *type_os2_lock;
129 PyThread_type_lock
130 PyThread_allocate_lock(void)
132 #if defined(PYCC_GCC)
133 _fmutex *sem = malloc(sizeof(_fmutex));
134 if (!initialized)
135 PyThread_init_thread();
136 dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
137 PyThread_get_thread_ident(),
138 (long)sem));
139 if (_fmutex_create(sem, 0)) {
140 free(sem);
141 sem = NULL;
143 return (PyThread_type_lock)sem;
144 #else
145 APIRET rc;
146 type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
148 dprintf(("PyThread_allocate_lock called\n"));
149 if (!initialized)
150 PyThread_init_thread();
152 lock->is_set = 0;
154 DosCreateEventSem(NULL, &lock->changed, 0, 0);
156 dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
157 PyThread_get_thread_ident(),
158 lock->changed));
160 return (PyThread_type_lock)lock;
161 #endif
164 void
165 PyThread_free_lock(PyThread_type_lock aLock)
167 #if !defined(PYCC_GCC)
168 type_os2_lock lock = (type_os2_lock)aLock;
169 #endif
171 dprintf(("%ld: PyThread_free_lock(%p) called\n",
172 PyThread_get_thread_ident(),aLock));
174 #if defined(PYCC_GCC)
175 if (aLock) {
176 _fmutex_close((_fmutex *)aLock);
177 free((_fmutex *)aLock);
179 #else
180 DosCloseEventSem(lock->changed);
181 free(aLock);
182 #endif
186 * Return 1 on success if the lock was acquired
188 * and 0 if the lock was not acquired.
190 int
191 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
193 #if !defined(PYCC_GCC)
194 int done = 0;
195 ULONG count;
196 PID pid = 0;
197 TID tid = 0;
198 type_os2_lock lock = (type_os2_lock)aLock;
199 #endif
201 dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
202 PyThread_get_thread_ident(),
203 aLock,
204 waitflag));
206 #if defined(PYCC_GCC)
207 /* always successful if the lock doesn't exist */
208 if (aLock &&
209 _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
210 return 0;
211 #else
212 while (!done) {
213 /* if the lock is currently set, we have to wait for
214 * the state to change
216 if (lock->is_set) {
217 if (!waitflag)
218 return 0;
219 DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
222 /* enter a critical section and try to get the semaphore. If
223 * it is still locked, we will try again.
225 if (DosEnterCritSec())
226 return 0;
228 if (!lock->is_set) {
229 lock->is_set = 1;
230 DosResetEventSem(lock->changed, &count);
231 done = 1;
234 DosExitCritSec();
236 #endif
238 return 1;
241 void PyThread_release_lock(PyThread_type_lock aLock)
243 #if !defined(PYCC_GCC)
244 type_os2_lock lock = (type_os2_lock)aLock;
245 #endif
247 dprintf(("%ld: PyThread_release_lock(%p) called\n",
248 PyThread_get_thread_ident(),
249 aLock));
251 #if defined(PYCC_GCC)
252 if (aLock)
253 _fmutex_release((_fmutex *)aLock);
254 #else
255 if (!lock->is_set) {
256 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
257 PyThread_get_thread_ident(),
258 aLock,
259 GetLastError()));
260 return;
263 if (DosEnterCritSec()) {
264 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
265 PyThread_get_thread_ident(),
266 aLock,
267 GetLastError()));
268 return;
271 lock->is_set = 0;
272 DosPostEventSem(lock->changed);
274 DosExitCritSec();
275 #endif