3 This software is a copyrighted work licensed under the terms of the
4 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 static cygthread NO_COPY threads
[64];
17 #define NTHREADS (sizeof (threads) / sizeof (threads[0]))
19 DWORD NO_COPY
cygthread::main_thread_id
;
20 bool NO_COPY
cygthread::exiting
;
23 cygthread::callfunc (bool issimplestub
)
33 ev
= CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
34 pass_arg
= alloca (arglen
);
35 memcpy (pass_arg
, arg
, arglen
);
40 /* Wait for main thread to assign 'h' */
47 /* Cygwin threads should not call ExitThread directly */
49 /* ...so the above should always return */
52 /* Initial stub called by cygthread constructor. Performs initial
53 per-thread initialization and loops waiting for another thread function
56 cygthread::stub (VOID
*arg
)
58 cygthread
*info
= (cygthread
*) arg
;
59 _my_tls
._ctinfo
= info
;
60 if (info
->arg
== cygself
)
64 CloseHandle (info
->ev
);
65 CloseHandle (info
->thread_sync
);
67 info
->ev
= info
->thread_sync
= info
->stack_ptr
= NULL
;
71 info
->stack_ptr
= &arg
;
72 debug_printf ("thread '%s', id %y, stack_ptr %p", info
->name (), info
->id
, info
->stack_ptr
);
75 info
->ev
= CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
76 info
->thread_sync
= CreateEvent (&sec_none_nih
, FALSE
, FALSE
, NULL
);
84 system_printf ("erroneous thread activation, name is NULL prev thread name = '%s'", info
->__oldname
);
86 system_printf ("erroneous thread activation, name is NULL");
90 SetThreadName (info
->id
, info
->__name
);
91 info
->callfunc (false);
93 HANDLE notify
= info
->notify_detached
;
94 /* If func is NULL, the above function has set that to indicate
95 that it doesn't want to alert anyone with a SetEvent and should
96 just be marked as no longer inuse. Hopefully the function knows
99 info
->release (false);
103 info
->func
= NULL
; // catch erroneous activation
104 info
->__oldname
= info
->__name
;
112 switch (WaitForSingleObject (info
->thread_sync
, INFINITE
))
117 api_fatal ("WFSO failed, %E");
123 /* Overflow stub called by cygthread constructor. Calls specified function
124 and then exits the thread. */
126 cygthread::simplestub (VOID
*arg
)
128 cygthread
*info
= (cygthread
*) arg
;
129 _my_tls
._ctinfo
= info
;
130 info
->stack_ptr
= &arg
;
131 HANDLE notify
= info
->notify_detached
;
132 SetThreadName (info
->id
, info
->__name
);
133 info
->callfunc (true);
139 /* Start things going. Called from dll_crt0_1. */
143 main_thread_id
= GetCurrentThreadId ();
147 cygthread::freerange ()
149 cygthread
*self
= (cygthread
*) calloc (1, sizeof (*self
));
150 self
->is_freerange
= true;
155 void * cygthread::operator
160 /* Search the threads array for an empty slot to use */
161 for (info
= threads
; info
< threads
+ NTHREADS
; info
++)
162 if (!InterlockedExchange (&info
->inuse
, 1))
167 api_fatal ("name not NULL? %s, id %y, i %ld", info
->__name
, info
->id
, info
- threads
);
173 if (!getenv ("CYGWIN_FREERANGE_NOCHECK"))
174 api_fatal ("overflowed cygwin thread pool");
176 thread_printf ("overflowed cygwin thread pool");
179 info
= freerange (); /* exhausted thread pool */
185 /* This function is called via QueueUserAPC. Apparently creating threads
186 asynchronously is a huge performance win on Win64. */
188 cygthread::async_create (ULONG_PTR arg
)
190 cygthread
*that
= (cygthread
*) arg
;
192 ::SetThreadPriority (that
->h
, THREAD_PRIORITY_HIGHEST
);
199 thread_printf ("name %s, id %y, this %p", __name
, id
, this);
207 SetEvent (thread_sync
);
208 thread_printf ("activated name '%s', thread_sync %p for id %y", __name
, thread_sync
, id
);
214 htobe
= CreateThread (&sec_none_nih
, 0, is_freerange
? simplestub
: stub
,
217 api_fatal ("CreateThread failed for %s - %p<%y>, %E", __name
, h
, id
);
218 thread_printf ("created name '%s', thread %p, id %y", __name
, h
, id
);
228 WaitForSingleObject (ev
, INFINITE
);
234 /* Return the symbolic name of the current thread for debugging.
237 cygthread::name (DWORD tid
)
239 const char *res
= NULL
;
241 tid
= GetCurrentThreadId ();
243 if (tid
== main_thread_id
)
246 for (DWORD i
= 0; i
< NTHREADS
; i
++)
247 if (threads
[i
].id
== tid
)
249 res
= threads
[i
].__name
?: "exiting thread";
259 __small_sprintf (_my_tls
.locals
.unknown_thread_name
, "unknown (%y)", tid
);
260 res
= _my_tls
.locals
.unknown_thread_name
;
274 cygthread::release (bool nuke_h
)
280 debug_printf ("released thread '%s'", __oldname
);
285 if (!InterlockedExchange (&inuse
, 0))
287 api_fatal ("released a thread that was not inuse");
289 system_printf ("released a thread that was not inuse");
293 /* Forcibly terminate a thread. */
295 cygthread::terminate_thread ()
297 bool terminated
= true;
298 debug_printf ("thread '%s', id %y, inuse %d, stack_ptr %p", __name
, id
, inuse
, stack_ptr
);
299 while (inuse
&& !stack_ptr
)
303 goto force_notterminated
;
305 if (_my_tls
._ctinfo
!= this)
308 context
.ContextFlags
= CONTEXT_CONTROL
;
309 /* SuspendThread makes sure a thread is "booted" from emulation before
310 it is suspended. As such, the emulator hopefully won't be in a bad
311 state (aka, holding any locks) when the thread is terminated. */
313 /* We need to call GetThreadContext, even though we don't care about the
314 context, because SuspendThread is asynchronous and GetThreadContext
315 will make sure the thread is *really* suspended before returning */
316 GetThreadContext (h
, &context
);
319 TerminateThread (h
, 0);
320 WaitForSingleObject (h
, INFINITE
);
323 if (!inuse
|| exiting
)
324 goto force_notterminated
;
326 if (ev
&& !(terminated
= !IsEventSignalled (ev
)))
347 /* Detach the cygthread from the current thread. Note that the
348 theory is that cygthreads are only associated with one thread.
349 So, there should be never be multiple threads doing waits
350 on the same cygthread. */
352 cygthread::detach (HANDLE sigwait
)
354 bool signalled
= false;
355 bool thread_was_reset
= false;
357 system_printf ("called detach but inuse %d, thread %y?", inuse
, id
);
363 /* If the caller specified a special handle for notification, wait for that.
364 This assumes that the thread in question is auto releasing. */
365 res
= WaitForSingleObject (*this, INFINITE
);
368 /* Lower our priority and give priority to the read thread */
369 HANDLE hth
= GetCurrentThread ();
370 LONG prio
= GetThreadPriority (hth
);
371 ::SetThreadPriority (hth
, THREAD_PRIORITY_BELOW_NORMAL
);
375 DWORD howlong
= INFINITE
;
377 wait_signal_arrived
here (w4
[1]);
378 /* For a description of the below loop see the end of this file */
379 for (int i
= 0; i
< 2; i
++)
380 switch (res
= WaitForMultipleObjects (n
, w4
, FALSE
, howlong
))
386 case WAIT_OBJECT_0
+ 1:
396 system_printf ("WFMO failed waiting for cygthread '%s', %E", __name
);
397 for (unsigned j
= 0; j
< n
; j
++)
398 switch (WaitForSingleObject (w4
[j
], 0))
404 system_printf ("%s handle %p is bad", (j
? "signal_arrived" : "semaphore"), w4
[j
]);
407 api_fatal ("exiting on fatal error");
411 /* WAIT_OBJECT_0 means that the thread successfully read something,
412 so wait for the cygthread to "terminate". */
413 if (res
== WAIT_OBJECT_0
)
414 WaitForSingleObject (*this, INFINITE
);
417 /* Thread didn't terminate on its own, so maybe we have to
419 signalled
= terminate_thread ();
420 /* Possibly the thread completed *just* before it was
421 terminated. Detect this. If this happened then the
422 read was not terminated on a signal. */
423 if (WaitForSingleObject (sigwait
, 0) == WAIT_OBJECT_0
)
426 set_sig_errno (EINTR
);
427 thread_was_reset
= true;
429 ::SetThreadPriority (hth
, prio
);
432 thread_printf ("%s returns %d, id %y", sigwait
? "WFMO" : "WFSO",
435 if (thread_was_reset
)
436 /* already handled */;
437 else if (is_freerange
)
445 /* Mark the thread as available by setting inuse to zero */
446 InterlockedExchange (&inuse
, 0);
453 cygthread::terminate ()
458 /* The below is an explanation of synchronization loop in cygthread::detach.
459 The intent is that the loop will always try hard to wait for both
460 synchronization events from the reader thread but will exit with
461 res == WAIT_TIMEOUT if a signal occurred and the reader thread is
466 i == 0 (howlong == INFINITE)
468 howlong not set because n != 1
471 i == 1 (howlong == INFINITE)
473 howlong not set because n != 1
474 just loop (to exit loop) - no signal
476 i == 2 (howlong == INFINITE)
479 case 1 - signal before thread initialized
481 i == 0 (howlong == INFINITE)
484 howlong untouched because i-- == 0
487 i == 0 (howlong == INFINITE)
489 howlong set to 50 because n == 1
491 i == 1 (howlong == 50)
493 loop (to exit loop) - no signal
495 WAIT_TIMEOUT activated
496 signal potentially detected
499 i == 2 (howlong == 50)
502 case 2 - signal after thread initialized
504 i == 0 (howlong == INFINITE)
506 howlong not set because n != 1
509 i == 1 (howlong == INFINITE)
512 howlong set to 50 because i-- != 0
515 i == 1 (howlong == 50)
517 loop (to exit loop) - no signal
519 WAIT_TIMEOUT activated
520 loop (to exit loop) - signal
522 i == 2 (howlong == 50)