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 TerminateThread (h
, 0);
306 WaitForSingleObject (h
, INFINITE
);
309 if (!inuse
|| exiting
)
310 goto force_notterminated
;
312 if (ev
&& !(terminated
= !IsEventSignalled (ev
)))
333 /* Detach the cygthread from the current thread. Note that the
334 theory is that cygthreads are only associated with one thread.
335 So, there should be never be multiple threads doing waits
336 on the same cygthread. */
338 cygthread::detach (HANDLE sigwait
)
340 bool signalled
= false;
341 bool thread_was_reset
= false;
343 system_printf ("called detach but inuse %d, thread %y?", inuse
, id
);
349 /* If the caller specified a special handle for notification, wait for that.
350 This assumes that the thread in question is auto releasing. */
351 res
= WaitForSingleObject (*this, INFINITE
);
354 /* Lower our priority and give priority to the read thread */
355 HANDLE hth
= GetCurrentThread ();
356 LONG prio
= GetThreadPriority (hth
);
357 ::SetThreadPriority (hth
, THREAD_PRIORITY_BELOW_NORMAL
);
361 DWORD howlong
= INFINITE
;
363 wait_signal_arrived
here (w4
[1]);
364 /* For a description of the below loop see the end of this file */
365 for (int i
= 0; i
< 2; i
++)
366 switch (res
= WaitForMultipleObjects (n
, w4
, FALSE
, howlong
))
372 case WAIT_OBJECT_0
+ 1:
382 system_printf ("WFMO failed waiting for cygthread '%s', %E", __name
);
383 for (unsigned j
= 0; j
< n
; j
++)
384 switch (WaitForSingleObject (w4
[j
], 0))
390 system_printf ("%s handle %p is bad", (j
? "signal_arrived" : "semaphore"), w4
[j
]);
393 api_fatal ("exiting on fatal error");
397 /* WAIT_OBJECT_0 means that the thread successfully read something,
398 so wait for the cygthread to "terminate". */
399 if (res
== WAIT_OBJECT_0
)
400 WaitForSingleObject (*this, INFINITE
);
403 /* Thread didn't terminate on its own, so maybe we have to
405 signalled
= terminate_thread ();
406 /* Possibly the thread completed *just* before it was
407 terminated. Detect this. If this happened then the
408 read was not terminated on a signal. */
409 if (WaitForSingleObject (sigwait
, 0) == WAIT_OBJECT_0
)
412 set_sig_errno (EINTR
);
413 thread_was_reset
= true;
415 ::SetThreadPriority (hth
, prio
);
418 thread_printf ("%s returns %d, id %y", sigwait
? "WFMO" : "WFSO",
421 if (thread_was_reset
)
422 /* already handled */;
423 else if (is_freerange
)
431 /* Mark the thread as available by setting inuse to zero */
432 InterlockedExchange (&inuse
, 0);
439 cygthread::terminate ()
444 /* The below is an explanation of synchronization loop in cygthread::detach.
445 The intent is that the loop will always try hard to wait for both
446 synchronization events from the reader thread but will exit with
447 res == WAIT_TIMEOUT if a signal occurred and the reader thread is
452 i == 0 (howlong == INFINITE)
454 howlong not set because n != 1
457 i == 1 (howlong == INFINITE)
459 howlong not set because n != 1
460 just loop (to exit loop) - no signal
462 i == 2 (howlong == INFINITE)
465 case 1 - signal before thread initialized
467 i == 0 (howlong == INFINITE)
470 howlong untouched because i-- == 0
473 i == 0 (howlong == INFINITE)
475 howlong set to 50 because n == 1
477 i == 1 (howlong == 50)
479 loop (to exit loop) - no signal
481 WAIT_TIMEOUT activated
482 signal potentially detected
485 i == 2 (howlong == 50)
488 case 2 - signal after thread initialized
490 i == 0 (howlong == INFINITE)
492 howlong not set because n != 1
495 i == 1 (howlong == INFINITE)
498 howlong set to 50 because i-- != 0
501 i == 1 (howlong == 50)
503 loop (to exit loop) - no signal
505 WAIT_TIMEOUT activated
506 loop (to exit loop) - signal
508 i == 2 (howlong == 50)