|
5 | 5 | #include <windows.h> |
6 | 6 | #include <limits.h> |
7 | 7 | #include <process.h> |
| 8 | +#include <Python.h> |
8 | 9 |
|
9 | 10 | typedef struct NRMUTEX { |
10 | 11 | LONG owned ; |
11 | 12 | DWORD thread_id ; |
12 | 13 | HANDLE hevent ; |
13 | 14 | } NRMUTEX, *PNRMUTEX ; |
14 | 15 |
|
| 16 | +/* dictionary to correlate thread ids with the handle needed to terminate them*/ |
| 17 | +static PyObject *threads = NULL; |
15 | 18 |
|
16 | 19 | typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ; |
17 | 20 |
|
@@ -145,28 +148,67 @@ long PyThread_get_thread_ident(void); |
145 | 148 | */ |
146 | 149 | static void PyThread__init_thread(void) |
147 | 150 | { |
| 151 | + threads = PyDict_New(); |
148 | 152 | } |
149 | 153 |
|
150 | 154 | /* |
151 | 155 | * Thread support. |
152 | 156 | */ |
153 | | -int PyThread_start_new_thread(void (*func)(void *), void *arg) |
| 157 | + |
| 158 | +typedef struct { |
| 159 | + void (*func)(void*); |
| 160 | + void *arg; |
| 161 | + long id; |
| 162 | + HANDLE done; |
| 163 | +} callobj; |
| 164 | + |
| 165 | +static int |
| 166 | +bootstrap(void *call) |
| 167 | +{ |
| 168 | + callobj *obj = (callobj*)call; |
| 169 | + /* copy callobj since other thread might free it before we're done */ |
| 170 | + void (*func)(void*) = obj->func; |
| 171 | + void *arg = obj->arg; |
| 172 | + |
| 173 | + obj->id = PyThread_get_thread_ident(); |
| 174 | + ReleaseSemaphore(obj->done, 1, NULL); |
| 175 | + func(arg); |
| 176 | + return 0; |
| 177 | +} |
| 178 | + |
| 179 | +long PyThread_start_new_thread(void (*func)(void *), void *arg) |
154 | 180 | { |
155 | 181 | unsigned long rv; |
156 | 182 | int success = 0; |
| 183 | + callobj *obj; |
| 184 | + int id; |
| 185 | + PyObject *key, *val; |
157 | 186 |
|
158 | 187 | dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); |
159 | 188 | if (!initialized) |
160 | 189 | PyThread_init_thread(); |
161 | 190 |
|
162 | | - rv = _beginthread(func, 0, arg); /* use default stack size */ |
| 191 | + obj = malloc(sizeof(callobj)); |
| 192 | + obj->func = func; |
| 193 | + obj->arg = arg; |
| 194 | + obj->done = CreateSemaphore(NULL, 0, 1, NULL); |
| 195 | + |
| 196 | + rv = _beginthread(func, 0, obj); /* use default stack size */ |
163 | 197 |
|
164 | 198 | if (rv != (unsigned long)-1) { |
165 | 199 | success = 1; |
166 | 200 | dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", PyThread_get_thread_ident(), rv)); |
167 | 201 | } |
168 | 202 |
|
169 | | - return success; |
| 203 | + /* wait for thread to initialize and retrieve id */ |
| 204 | + WaitForSingleObject(obj->done, 5000); /* maybe INFINITE instead of 5000? */ |
| 205 | + CloseHandle((HANDLE)obj->done); |
| 206 | + key = PyLong_FromLong(obj->id); |
| 207 | + val = PyLong_FromLong((long)rv); |
| 208 | + PyDict_SetItem(threads, key, val); |
| 209 | + id = obj->id; |
| 210 | + free(obj); |
| 211 | + return id; |
170 | 212 | } |
171 | 213 |
|
172 | 214 | /* |
|
0 commit comments