3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008,
4 2009, 2010, 2011 Red Hat, Inc.
6 This software is a copyrighted work licensed under the terms of the
7 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #include "miscfuncs.h"
19 static cygthread NO_COPY threads[64];
20 #define NTHREADS (sizeof (threads) / sizeof (threads[0]))
22 DWORD NO_COPY cygthread::main_thread_id;
23 bool NO_COPY cygthread::exiting;
26 cygthread::callfunc (bool issimplestub)
36 ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
37 pass_arg = alloca (arglen);
38 memcpy (pass_arg, arg, arglen);
43 /* Wait for main thread to assign 'h' */
50 /* Cygwin threads should not call ExitThread directly */
52 /* ...so the above should always return */
55 /* Initial stub called by cygthread constructor. Performs initial
56 per-thread initialization and loops waiting for another thread function
59 cygthread::stub (VOID *arg)
61 cygthread *info = (cygthread *) arg;
62 _my_tls._ctinfo = info;
63 if (info->arg == cygself)
67 CloseHandle (info->ev);
68 CloseHandle (info->thread_sync);
70 info->ev = info->thread_sync = info->stack_ptr = NULL;
74 info->stack_ptr = &arg;
75 debug_printf ("thread '%s', id %p, stack_ptr %p", info->name (), info->id, info->stack_ptr);
78 info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
79 info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
87 system_printf ("erroneous thread activation, name is NULL prev thread name = '%s'", info->__oldname);
89 system_printf ("erroneous thread activation, name is NULL");
95 info->inuse = false; // FIXME: Do we need this?
99 info->callfunc (false);
101 HANDLE notify = info->notify_detached;
102 /* If func is NULL, the above function has set that to indicate
103 that it doesn't want to alert anyone with a SetEvent and should
104 just be marked as no longer inuse. Hopefully the function knows
107 info->release (false);
111 info->func = NULL; // catch erroneous activation
112 info->__oldname = info->__name;
120 switch (WaitForSingleObject (info->thread_sync, INFINITE))
125 api_fatal ("WFSO failed, %E");
131 /* Overflow stub called by cygthread constructor. Calls specified function
132 and then exits the thread. */
134 cygthread::simplestub (VOID *arg)
136 cygthread *info = (cygthread *) arg;
137 _my_tls._ctinfo = info;
138 info->stack_ptr = &arg;
139 HANDLE notify = info->notify_detached;
140 info->callfunc (true);
146 /* Start things going. Called from dll_crt0_1. */
150 main_thread_id = GetCurrentThreadId ();
154 cygthread::freerange ()
156 cygthread *self = (cygthread *) calloc (1, sizeof (*self));
157 self->is_freerange = true;
162 void * cygthread::operator
167 /* Search the threads array for an empty slot to use */
168 for (info = threads; info < threads + NTHREADS; info++)
169 if (!InterlockedExchange (&info->inuse, 1))
174 api_fatal ("name not NULL? %s, id %p, i %d", info->__name, info->id, info - threads);
180 if (!getenv ("CYGWIN_FREERANGE_NOCHECK"))
181 api_fatal ("overflowed cygwin thread pool");
183 thread_printf ("overflowed cygwin thread pool");
186 info = freerange (); /* exhausted thread pool */
192 /* This function is called via QueueUserAPC. Apparently creating threads
193 asynchronously is a huge performance win on Win64. */
195 cygthread::async_create (ULONG_PTR arg)
197 cygthread *that = (cygthread *) arg;
199 ::SetThreadPriority (that->h, THREAD_PRIORITY_HIGHEST);
206 thread_printf ("name %s, id %p, this %p", __name, id, this);
214 SetEvent (thread_sync);
215 thread_printf ("activated name '%s', thread_sync %p for id %p", __name, thread_sync, id);
221 htobe = CreateThread (&sec_none_nih, 0, is_freerange ? simplestub : stub,
224 api_fatal ("CreateThread failed for %s - %p<%p>, %E", __name, h, id);
225 thread_printf ("created name '%s', thread %p, id %p", __name, h, id);
235 WaitForSingleObject (ev, INFINITE);
241 /* Return the symbolic name of the current thread for debugging.
244 cygthread::name (DWORD tid)
246 const char *res = NULL;
248 tid = GetCurrentThreadId ();
250 if (tid == main_thread_id)
253 for (DWORD i = 0; i < NTHREADS; i++)
254 if (threads[i].id == tid)
256 res = threads[i].__name ?: "exiting thread";
266 __small_sprintf (_my_tls.locals.unknown_thread_name, "unknown (%p)", tid);
267 res = _my_tls.locals.unknown_thread_name;
281 cygthread::release (bool nuke_h)
287 debug_printf ("released thread '%s'", __oldname);
292 if (!InterlockedExchange (&inuse, 0))
294 api_fatal ("released a thread that was not inuse");
296 system_printf ("released a thread that was not inuse");
300 /* Forcibly terminate a thread. */
302 cygthread::terminate_thread ()
304 bool terminated = true;
305 debug_printf ("thread '%s', id %p, inuse %d, stack_ptr %p", __name, id, inuse, stack_ptr);
306 while (inuse && !stack_ptr)
310 goto force_notterminated;
312 TerminateThread (h, 0);
313 WaitForSingleObject (h, INFINITE);
316 if (!inuse || exiting)
317 goto force_notterminated;
319 if (ev && !(terminated = !IsEventSignalled (ev)))
322 MEMORY_BASIC_INFORMATION m;
323 memset (&m, 0, sizeof (m));
324 VirtualQuery (stack_ptr, &m, sizeof m);
327 system_printf ("m.RegionSize 0? stack_ptr %p", stack_ptr);
328 else if (!VirtualFree (m.AllocationBase, 0, MEM_RELEASE))
329 debug_printf ("VirtualFree of allocation base %p<%p> failed, %E",
330 stack_ptr, m.AllocationBase);
350 /* Detach the cygthread from the current thread. Note that the
351 theory is that cygthreads are only associated with one thread.
352 So, there should be never be multiple threads doing waits
353 on the same cygthread. */
355 cygthread::detach (HANDLE sigwait)
357 bool signalled = false;
358 bool thread_was_reset = false;
360 system_printf ("called detach but inuse %d, thread %p?", inuse, id);
366 /* If the caller specified a special handle for notification, wait for that.
367 This assumes that the thread in question is auto releasing. */
368 res = WaitForSingleObject (*this, INFINITE);
371 /* Lower our priority and give priority to the read thread */
372 HANDLE hth = GetCurrentThread ();
373 LONG prio = GetThreadPriority (hth);
374 ::SetThreadPriority (hth, THREAD_PRIORITY_BELOW_NORMAL);
378 DWORD howlong = INFINITE;
380 w4[1] = signal_arrived;
381 /* For a description of the below loop see the end of this file */
382 for (int i = 0; i < 2; i++)
383 switch (res = WaitForMultipleObjects (n, w4, FALSE, howlong))
389 case WAIT_OBJECT_0 + 1:
399 system_printf ("WFMO failed waiting for cygthread '%s', %E", __name);
400 for (unsigned j = 0; j < n; j++)
401 switch (WaitForSingleObject (w4[j], 0))
407 system_printf ("%s handle %p is bad", (j ? "signal_arrived" : "semaphore"), w4[j]);
410 api_fatal ("exiting on fatal error");
414 /* WAIT_OBJECT_0 means that the thread successfully read something,
415 so wait for the cygthread to "terminate". */
416 if (res == WAIT_OBJECT_0)
417 WaitForSingleObject (*this, INFINITE);
420 /* Thread didn't terminate on its own, so maybe we have to
422 signalled = terminate_thread ();
423 /* Possibly the thread completed *just* before it was
424 terminated. Detect this. If this happened then the
425 read was not terminated on a signal. */
426 if (WaitForSingleObject (sigwait, 0) == WAIT_OBJECT_0)
429 set_sig_errno (EINTR);
430 thread_was_reset = true;
432 ::SetThreadPriority (hth, prio);
435 thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO",
438 if (thread_was_reset)
439 /* already handled */;
440 else if (is_freerange)
448 /* Mark the thread as available by setting inuse to zero */
449 InterlockedExchange (&inuse, 0);
456 cygthread::terminate ()
461 /* The below is an explanation of synchronization loop in cygthread::detach.
462 The intent is that the loop will always try hard to wait for both
463 synchronization events from the reader thread but will exit with
464 res == WAIT_TIMEOUT if a signal occurred and the reader thread is
469 i == 0 (howlong == INFINITE)
471 howlong not set because n != 1
474 i == 1 (howlong == INFINITE)
476 howlong not set because n != 1
477 just loop (to exit loop) - no signal
479 i == 2 (howlong == INFINITE)
482 case 1 - signal before thread initialized
484 i == 0 (howlong == INFINITE)
487 howlong untouched because i-- == 0
490 i == 0 (howlong == INFINITE)
492 howlong set to 50 because n == 1
494 i == 1 (howlong == 50)
496 loop (to exit loop) - no signal
498 WAIT_TIMEOUT activated
499 signal potentially detected
502 i == 2 (howlong == 50)
505 case 2 - signal after thread initialized
507 i == 0 (howlong == INFINITE)
509 howlong not set because n != 1
512 i == 1 (howlong == INFINITE)
515 howlong set to 50 because i-- != 0
518 i == 1 (howlong == 50)
520 loop (to exit loop) - no signal
522 WAIT_TIMEOUT activated
523 loop (to exit loop) - signal
525 i == 2 (howlong == 50)