blob: d1bb0e5673705da25b0f33e93d64076bde00395a [file] [log] [blame]
Guido van Rossumc3f82b61995-01-17 16:29:31 +00001
2/* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */
Guido van Rossum706262b2000-05-04 18:47:15 +00003/* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */
Tim Peterse64ef932002-02-28 21:34:34 +00004/* Eliminated some memory leaks, gsw@agere.com */
Guido van Rossumc3f82b61995-01-17 16:29:31 +00005
Guido van Rossum49b12261997-08-14 20:12:58 +00006#include <windows.h>
7#include <limits.h>
Thomas Wouters0e3f5912006-08-11 14:57:12 +00008#ifdef HAVE_PROCESS_H
Guido van Rossum49b12261997-08-14 20:12:58 +00009#include <process.h>
Thomas Wouters0e3f5912006-08-11 14:57:12 +000010#endif
Guido van Rossumc3f82b61995-01-17 16:29:31 +000011
Antoine Pitrou7899acf2011-03-31 01:00:32 +020012#define PNRMUTEX HANDLE
Guido van Rossum706262b2000-05-04 18:47:15 +000013
Antoine Pitrou7899acf2011-03-31 01:00:32 +020014PNRMUTEX
15AllocNonRecursiveMutex()
Guido van Rossum706262b2000-05-04 18:47:15 +000016{
Antoine Pitrou7899acf2011-03-31 01:00:32 +020017 return CreateSemaphore(NULL, 1, 1, NULL);
Guido van Rossum706262b2000-05-04 18:47:15 +000018}
19
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000020VOID
Antoine Pitrou7899acf2011-03-31 01:00:32 +020021FreeNonRecursiveMutex(PNRMUTEX mutex)
Guido van Rossum706262b2000-05-04 18:47:15 +000022{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 /* No in-use check */
Antoine Pitrou7899acf2011-03-31 01:00:32 +020024 CloseHandle(mutex);
Guido van Rossum706262b2000-05-04 18:47:15 +000025}
26
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000027DWORD
Antoine Pitrou7c3e5772010-04-14 15:44:10 +000028EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
Guido van Rossum706262b2000-05-04 18:47:15 +000029{
Antoine Pitrou7899acf2011-03-31 01:00:32 +020030 return WaitForSingleObject(mutex, milliseconds);
Guido van Rossum706262b2000-05-04 18:47:15 +000031}
32
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000033BOOL
34LeaveNonRecursiveMutex(PNRMUTEX mutex)
Guido van Rossum706262b2000-05-04 18:47:15 +000035{
Antoine Pitrou7899acf2011-03-31 01:00:32 +020036 return ReleaseSemaphore(mutex, 1, NULL);
Guido van Rossum706262b2000-05-04 18:47:15 +000037}
38
Guido van Rossum65d5b571998-12-21 19:32:43 +000039long PyThread_get_thread_ident(void);
Guido van Rossumc3f82b61995-01-17 16:29:31 +000040
41/*
Guido van Rossumc3f82b61995-01-17 16:29:31 +000042 * Initialization of the C package, should not be needed.
43 */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000044static void
45PyThread__init_thread(void)
Guido van Rossumc3f82b61995-01-17 16:29:31 +000046{
47}
48
49/*
50 * Thread support.
51 */
Guido van Rossum3c288632001-10-16 21:13:49 +000052
53typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 void (*func)(void*);
55 void *arg;
Guido van Rossum3c288632001-10-16 21:13:49 +000056} callobj;
57
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +000058/* thunker to call adapt between the function type used by the system's
59thread start function and the internally used one. */
60#if defined(MS_WINCE)
61static DWORD WINAPI
62#else
63static unsigned __stdcall
64#endif
Guido van Rossum3c288632001-10-16 21:13:49 +000065bootstrap(void *call)
66{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 callobj *obj = (callobj*)call;
68 void (*func)(void*) = obj->func;
69 void *arg = obj->arg;
70 HeapFree(GetProcessHeap(), 0, obj);
71 func(arg);
72 return 0;
Guido van Rossum3c288632001-10-16 21:13:49 +000073}
74
Tim Peters2e7e7df2003-07-04 04:40:45 +000075long
76PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossumc3f82b61995-01-17 16:29:31 +000077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 HANDLE hThread;
79 unsigned threadID;
80 callobj *obj;
Guido van Rossumc3f82b61995-01-17 16:29:31 +000081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 dprintf(("%ld: PyThread_start_new_thread called\n",
83 PyThread_get_thread_ident()));
84 if (!initialized)
85 PyThread_init_thread();
86
87 obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
88 if (!obj)
89 return -1;
90 obj->func = func;
91 obj->arg = arg;
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +000092#if defined(MS_WINCE)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 hThread = CreateThread(NULL,
94 Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T),
95 bootstrap, obj, 0, &threadID);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +000096#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 hThread = (HANDLE)_beginthreadex(0,
98 Py_SAFE_DOWNCAST(_pythread_stacksize,
99 Py_ssize_t, unsigned int),
100 bootstrap, obj,
101 0, &threadID);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000102#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 if (hThread == 0) {
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000104#if defined(MS_WINCE)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 /* Save error in variable, to prevent PyThread_get_thread_ident
106 from clobbering it. */
107 unsigned e = GetLastError();
108 dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n",
109 PyThread_get_thread_ident(), e));
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000110#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000111 /* I've seen errno == EAGAIN here, which means "there are
112 * too many threads".
113 */
114 int e = errno;
115 dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n",
116 PyThread_get_thread_ident(), e));
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000117#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 threadID = (unsigned)-1;
119 HeapFree(GetProcessHeap(), 0, obj);
120 }
121 else {
122 dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
123 PyThread_get_thread_ident(), (void*)hThread));
124 CloseHandle(hThread);
125 }
126 return (long) threadID;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000127}
128
129/*
130 * Return the thread Id instead of an handle. The Id is said to uniquely identify the
131 * thread in the system
132 */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000133long
134PyThread_get_thread_ident(void)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 if (!initialized)
137 PyThread_init_thread();
Guido van Rossum706262b2000-05-04 18:47:15 +0000138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 return GetCurrentThreadId();
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000140}
141
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000142void
143PyThread_exit_thread(void)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000144{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
146 if (!initialized)
147 exit(0);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000148#if defined(MS_WINCE)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 ExitThread(0);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000150#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 _endthreadex(0);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000152#endif
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000153}
154
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000155/*
156 * Lock support. It has too be implemented as semaphores.
157 * I [Dag] tried to implement it with mutex but I could find a way to
158 * tell whether a thread already own the lock or not.
159 */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000160PyThread_type_lock
161PyThread_allocate_lock(void)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000162{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 PNRMUTEX aLock;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000165 dprintf(("PyThread_allocate_lock called\n"));
166 if (!initialized)
167 PyThread_init_thread();
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 aLock = AllocNonRecursiveMutex() ;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000171 dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 return (PyThread_type_lock) aLock;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000174}
175
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000176void
177PyThread_free_lock(PyThread_type_lock aLock)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 FreeNonRecursiveMutex(aLock) ;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000182}
183
184/*
185 * Return 1 on success if the lock was acquired
186 *
187 * and 0 if the lock was not acquired. This means a 0 is returned
188 * if the lock has already been acquired by this thread!
189 */
Antoine Pitrou810023d2010-12-15 22:59:16 +0000190PyLockStatus
191PyThread_acquire_lock_timed(PyThread_type_lock aLock,
192 PY_TIMEOUT_T microseconds, int intr_flag)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000193{
Antoine Pitrou810023d2010-12-15 22:59:16 +0000194 /* Fow now, intr_flag does nothing on Windows, and lock acquires are
195 * uninterruptible. */
196 PyLockStatus success;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 PY_TIMEOUT_T milliseconds;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 if (microseconds >= 0) {
200 milliseconds = microseconds / 1000;
201 if (microseconds % 1000 > 0)
202 ++milliseconds;
203 if ((DWORD) milliseconds != milliseconds)
204 Py_FatalError("Timeout too large for a DWORD, "
205 "please check PY_TIMEOUT_MAX");
206 }
207 else
208 milliseconds = INFINITE;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n",
211 PyThread_get_thread_ident(), aLock, microseconds));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000212
Antoine Pitrou810023d2010-12-15 22:59:16 +0000213 if (aLock && EnterNonRecursiveMutex((PNRMUTEX)aLock,
214 (DWORD)milliseconds) == WAIT_OBJECT_0) {
215 success = PY_LOCK_ACQUIRED;
216 }
217 else {
218 success = PY_LOCK_FAILURE;
219 }
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n",
222 PyThread_get_thread_ident(), aLock, microseconds, success));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 return success;
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000225}
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000226int
227PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
228{
Antoine Pitrou810023d2010-12-15 22:59:16 +0000229 return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0, 0);
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000230}
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000231
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000232void
233PyThread_release_lock(PyThread_type_lock aLock)
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
238 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
Guido van Rossumc3f82b61995-01-17 16:29:31 +0000239}
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000240
241/* minimum/maximum thread stack sizes supported */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
243#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000244
245/* set the thread stack size.
246 * Return 0 if size is valid, -1 otherwise.
247 */
248static int
249_pythread_nt_set_stacksize(size_t size)
250{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 /* set to default */
252 if (size == 0) {
253 _pythread_stacksize = 0;
254 return 0;
255 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 /* valid range? */
258 if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
259 _pythread_stacksize = size;
260 return 0;
261 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000264}
265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000267
268
269/* use native Windows TLS functions */
270#define Py_HAVE_NATIVE_TLS
271
272#ifdef Py_HAVE_NATIVE_TLS
273int
274PyThread_create_key(void)
275{
Kristján Valur Jónsson2fea9b92010-09-20 02:11:49 +0000276 DWORD result= TlsAlloc();
277 if (result == TLS_OUT_OF_INDEXES)
278 return -1;
279 return (int)result;
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000280}
281
282void
283PyThread_delete_key(int key)
284{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 TlsFree(key);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000286}
287
288/* We must be careful to emulate the strange semantics implemented in thread.c,
289 * where the value is only set if it hasn't been set before.
290 */
291int
292PyThread_set_key_value(int key, void *value)
293{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 BOOL ok;
295 void *oldvalue;
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 assert(value != NULL);
298 oldvalue = TlsGetValue(key);
299 if (oldvalue != NULL)
300 /* ignore value if already set */
301 return 0;
302 ok = TlsSetValue(key, value);
303 if (!ok)
304 return -1;
305 return 0;
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000306}
307
308void *
309PyThread_get_key_value(int key)
310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 /* because TLS is used in the Py_END_ALLOW_THREAD macro,
312 * it is necessary to preserve the windows error state, because
313 * it is assumed to be preserved across the call to the macro.
314 * Ideally, the macro should be fixed, but it is simpler to
315 * do it here.
316 */
317 DWORD error = GetLastError();
318 void *result = TlsGetValue(key);
319 SetLastError(error);
320 return result;
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000321}
322
323void
324PyThread_delete_key_value(int key)
325{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 /* NULL is used as "key missing", and it is also the default
327 * given by TlsGetValue() if nothing has been set yet.
328 */
329 TlsSetValue(key, NULL);
Martin v. Löwis7c2b66c2009-01-12 08:21:03 +0000330}
331
332/* reinitialization of TLS is not necessary after fork when using
333 * the native TLS functions. And forking isn't supported on Windows either.
334 */
335void
336PyThread_ReInitTLS(void)
337{}
338
339#endif