]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | /* This code implemented by cvale@netcom.com */\r |
2 | \r | |
3 | #define INCL_DOSPROCESS\r | |
4 | #define INCL_DOSSEMAPHORES\r | |
5 | #include "os2.h"\r | |
6 | #include "limits.h"\r | |
7 | \r | |
8 | #include "process.h"\r | |
9 | \r | |
10 | #if defined(PYCC_GCC)\r | |
11 | #include <sys/builtin.h>\r | |
12 | #include <sys/fmutex.h>\r | |
13 | #else\r | |
14 | long PyThread_get_thread_ident(void);\r | |
15 | #endif\r | |
16 | \r | |
17 | /* default thread stack size of 64kB */\r | |
18 | #if !defined(THREAD_STACK_SIZE)\r | |
19 | #define THREAD_STACK_SIZE 0x10000\r | |
20 | #endif\r | |
21 | \r | |
22 | #define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)\r | |
23 | \r | |
24 | /*\r | |
25 | * Initialization of the C package, should not be needed.\r | |
26 | */\r | |
27 | static void\r | |
28 | PyThread__init_thread(void)\r | |
29 | {\r | |
30 | }\r | |
31 | \r | |
32 | /*\r | |
33 | * Thread support.\r | |
34 | */\r | |
35 | long\r | |
36 | PyThread_start_new_thread(void (*func)(void *), void *arg)\r | |
37 | {\r | |
38 | int thread_id;\r | |
39 | \r | |
40 | thread_id = _beginthread(func,\r | |
41 | NULL,\r | |
42 | OS2_STACKSIZE(_pythread_stacksize),\r | |
43 | arg);\r | |
44 | \r | |
45 | if (thread_id == -1) {\r | |
46 | dprintf(("_beginthread failed. return %ld\n", errno));\r | |
47 | }\r | |
48 | \r | |
49 | return thread_id;\r | |
50 | }\r | |
51 | \r | |
52 | long\r | |
53 | PyThread_get_thread_ident(void)\r | |
54 | {\r | |
55 | #if !defined(PYCC_GCC)\r | |
56 | PPIB pib;\r | |
57 | PTIB tib;\r | |
58 | #endif\r | |
59 | \r | |
60 | if (!initialized)\r | |
61 | PyThread_init_thread();\r | |
62 | \r | |
63 | #if defined(PYCC_GCC)\r | |
64 | return _gettid();\r | |
65 | #else\r | |
66 | DosGetInfoBlocks(&tib, &pib);\r | |
67 | return tib->tib_ptib2->tib2_ultid;\r | |
68 | #endif\r | |
69 | }\r | |
70 | \r | |
71 | void\r | |
72 | PyThread_exit_thread(void)\r | |
73 | {\r | |
74 | dprintf(("%ld: PyThread_exit_thread called\n",\r | |
75 | PyThread_get_thread_ident()));\r | |
76 | if (!initialized)\r | |
77 | exit(0);\r | |
78 | _endthread();\r | |
79 | }\r | |
80 | \r | |
81 | /*\r | |
82 | * Lock support. This is implemented with an event semaphore and critical\r | |
83 | * sections to make it behave more like a posix mutex than its OS/2\r | |
84 | * counterparts.\r | |
85 | */\r | |
86 | \r | |
87 | typedef struct os2_lock_t {\r | |
88 | int is_set;\r | |
89 | HEV changed;\r | |
90 | } *type_os2_lock;\r | |
91 | \r | |
92 | PyThread_type_lock\r | |
93 | PyThread_allocate_lock(void)\r | |
94 | {\r | |
95 | #if defined(PYCC_GCC)\r | |
96 | _fmutex *sem = malloc(sizeof(_fmutex));\r | |
97 | if (!initialized)\r | |
98 | PyThread_init_thread();\r | |
99 | dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",\r | |
100 | PyThread_get_thread_ident(),\r | |
101 | (long)sem));\r | |
102 | if (_fmutex_create(sem, 0)) {\r | |
103 | free(sem);\r | |
104 | sem = NULL;\r | |
105 | }\r | |
106 | return (PyThread_type_lock)sem;\r | |
107 | #else\r | |
108 | APIRET rc;\r | |
109 | type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));\r | |
110 | \r | |
111 | dprintf(("PyThread_allocate_lock called\n"));\r | |
112 | if (!initialized)\r | |
113 | PyThread_init_thread();\r | |
114 | \r | |
115 | lock->is_set = 0;\r | |
116 | \r | |
117 | DosCreateEventSem(NULL, &lock->changed, 0, 0);\r | |
118 | \r | |
119 | dprintf(("%ld: PyThread_allocate_lock() -> %p\n",\r | |
120 | PyThread_get_thread_ident(),\r | |
121 | lock->changed));\r | |
122 | \r | |
123 | return (PyThread_type_lock)lock;\r | |
124 | #endif\r | |
125 | }\r | |
126 | \r | |
127 | void\r | |
128 | PyThread_free_lock(PyThread_type_lock aLock)\r | |
129 | {\r | |
130 | #if !defined(PYCC_GCC)\r | |
131 | type_os2_lock lock = (type_os2_lock)aLock;\r | |
132 | #endif\r | |
133 | \r | |
134 | dprintf(("%ld: PyThread_free_lock(%p) called\n",\r | |
135 | PyThread_get_thread_ident(),aLock));\r | |
136 | \r | |
137 | #if defined(PYCC_GCC)\r | |
138 | if (aLock) {\r | |
139 | _fmutex_close((_fmutex *)aLock);\r | |
140 | free((_fmutex *)aLock);\r | |
141 | }\r | |
142 | #else\r | |
143 | DosCloseEventSem(lock->changed);\r | |
144 | free(aLock);\r | |
145 | #endif\r | |
146 | }\r | |
147 | \r | |
148 | /*\r | |
149 | * Return 1 on success if the lock was acquired\r | |
150 | *\r | |
151 | * and 0 if the lock was not acquired.\r | |
152 | */\r | |
153 | int\r | |
154 | PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)\r | |
155 | {\r | |
156 | #if !defined(PYCC_GCC)\r | |
157 | int done = 0;\r | |
158 | ULONG count;\r | |
159 | PID pid = 0;\r | |
160 | TID tid = 0;\r | |
161 | type_os2_lock lock = (type_os2_lock)aLock;\r | |
162 | #endif\r | |
163 | \r | |
164 | dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",\r | |
165 | PyThread_get_thread_ident(),\r | |
166 | aLock,\r | |
167 | waitflag));\r | |
168 | \r | |
169 | #if defined(PYCC_GCC)\r | |
170 | /* always successful if the lock doesn't exist */\r | |
171 | if (aLock &&\r | |
172 | _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))\r | |
173 | return 0;\r | |
174 | #else\r | |
175 | while (!done) {\r | |
176 | /* if the lock is currently set, we have to wait for\r | |
177 | * the state to change\r | |
178 | */\r | |
179 | if (lock->is_set) {\r | |
180 | if (!waitflag)\r | |
181 | return 0;\r | |
182 | DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);\r | |
183 | }\r | |
184 | \r | |
185 | /* enter a critical section and try to get the semaphore. If\r | |
186 | * it is still locked, we will try again.\r | |
187 | */\r | |
188 | if (DosEnterCritSec())\r | |
189 | return 0;\r | |
190 | \r | |
191 | if (!lock->is_set) {\r | |
192 | lock->is_set = 1;\r | |
193 | DosResetEventSem(lock->changed, &count);\r | |
194 | done = 1;\r | |
195 | }\r | |
196 | \r | |
197 | DosExitCritSec();\r | |
198 | }\r | |
199 | #endif\r | |
200 | \r | |
201 | return 1;\r | |
202 | }\r | |
203 | \r | |
204 | void\r | |
205 | PyThread_release_lock(PyThread_type_lock aLock)\r | |
206 | {\r | |
207 | #if !defined(PYCC_GCC)\r | |
208 | type_os2_lock lock = (type_os2_lock)aLock;\r | |
209 | #endif\r | |
210 | \r | |
211 | dprintf(("%ld: PyThread_release_lock(%p) called\n",\r | |
212 | PyThread_get_thread_ident(),\r | |
213 | aLock));\r | |
214 | \r | |
215 | #if defined(PYCC_GCC)\r | |
216 | if (aLock)\r | |
217 | _fmutex_release((_fmutex *)aLock);\r | |
218 | #else\r | |
219 | if (!lock->is_set) {\r | |
220 | dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",\r | |
221 | PyThread_get_thread_ident(),\r | |
222 | aLock,\r | |
223 | GetLastError()));\r | |
224 | return;\r | |
225 | }\r | |
226 | \r | |
227 | if (DosEnterCritSec()) {\r | |
228 | dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",\r | |
229 | PyThread_get_thread_ident(),\r | |
230 | aLock,\r | |
231 | GetLastError()));\r | |
232 | return;\r | |
233 | }\r | |
234 | \r | |
235 | lock->is_set = 0;\r | |
236 | DosPostEventSem(lock->changed);\r | |
237 | \r | |
238 | DosExitCritSec();\r | |
239 | #endif\r | |
240 | }\r | |
241 | \r | |
242 | /* minimum/maximum thread stack sizes supported */\r | |
243 | #define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */\r | |
244 | #define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */\r | |
245 | \r | |
246 | /* set the thread stack size.\r | |
247 | * Return 0 if size is valid, -1 otherwise.\r | |
248 | */\r | |
249 | static int\r | |
250 | _pythread_os2_set_stacksize(size_t size)\r | |
251 | {\r | |
252 | /* set to default */\r | |
253 | if (size == 0) {\r | |
254 | _pythread_stacksize = 0;\r | |
255 | return 0;\r | |
256 | }\r | |
257 | \r | |
258 | /* valid range? */\r | |
259 | if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {\r | |
260 | _pythread_stacksize = size;\r | |
261 | return 0;\r | |
262 | }\r | |
263 | \r | |
264 | return -1;\r | |
265 | }\r | |
266 | \r | |
267 | #define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)\r |