+2002-08-05 Christopher Faylor <cgf@redhat.com>
+
+ * cygthread.cc (cygthread::stub): Change event creation to manual
+ reset. Set __name after calling SetEvent to prevent races.
+ (cygthread::detach): Always reset event here to prevent races.
+
2002-08-03 Conrad Scott <conrad.scott@dsl.pipex.com>
* debug.h (WaitForMultipleObjects): Correct typo.
details. */
#include "winsup.h"
+#include <windows.h>
#include "exceptions.h"
#include "security.h"
#include "cygthread.h"
-#include <windows.h>
#undef CloseHandle
DWORD NO_COPY cygthread::main_thread_id;
-/* Initial stub called by makethread. Performs initial per-thread
- initialization. */
+/* Initial stub called by cygthread constructor. Performs initial
+ per-thread initialization and loops waiting for new thread functions
+ to execute. */
DWORD WINAPI
cygthread::stub (VOID *arg)
{
init_exceptions (&except_entry);
cygthread *info = (cygthread *) arg;
- info->ev = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
+ info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
while (1)
{
if (!info->func)
/* Cygwin threads should not call ExitThread */
info->func (info->arg);
- info->__name = NULL;
+ debug_printf ("returned from function %p", info->func);
SetEvent (info->ev);
+ info->__name = NULL;
SuspendThread (info->h);
}
}
+/* This function runs in a secondary thread and starts up a bunch of
+ other suspended threads for use in the cygthread pool. */
DWORD WINAPI
cygthread::runner (VOID *arg)
{
return 0;
}
+/* Start things going. Called from dll_crt0_1. */
void
cygthread::init ()
{
new (size_t)
{
DWORD id;
- cygthread *info; /* Various information needed by the newly created thread */
+ cygthread *info;
for (;;)
{
return ev;
}
+/* Should only be called when the process is exiting since it
+ leaves an open thread slot. */
void
cygthread::exit_thread ()
{
ExitThread (0);
}
+/* Detach the cygthread from the current thread. Note that the
+ theory is that cygthread's are only associated with one thread.
+ So, there should be no problems with multiple threads doing waits
+ on the one cygthread. */
void
cygthread::detach ()
{
if (!avail)
{
DWORD avail = id;
- if (__name)
+ /* Checking for __name here is just a minor optimization to avoid
+ an OS call. */
+ if (!__name)
+ debug_printf ("thread routine returned. No need to wait.");
+ else
{
DWORD res = WaitForSingleObject (*this, INFINITE);
debug_printf ("WFSO returns %d", res);
}
+ ResetEvent (*this);
id = 0;
+ /* Mark the thread as available by setting avail to non-zero */
(void) InterlockedExchange ((LPLONG) &this->avail, avail);
}
}