* Makefile.in (DLL_OFILES): Add cygthread.o.

* dcrt0.cc (dll_crt0_1): Eliminate various thread initialization functions in
favor of new cygthread class.
* debug.cc: Remove thread manipulation functions.
* debug.h: Ditto.
* external.cc (cygwin_internal): Use cygthread method for determining thread
name.  Remove capability for setting thread name.
* fhandler_console.cc (fhandler_console::read): Use cygthread method rather
than iscygthread function.
* fhandler_tty.cc (fhandler_tty_master::fhandler_tty_master): Use cygthread
methods to create threads.
(fhandler_tty_common::__acquire_output_mutex): Use cygthread method to retrieve
thread name.
* select.cc (pipeinf): Use cygthread pointer rather than handle.
(start_thread_pipe): Ditto.
(pipe_cleanup): Ditto.
(serialinf): Ditto.
(start_thread_serial): Ditto.
(serial_cleanup): Ditto.
(socketinf): Ditto.
(start_thread_socket): Ditto.
(socket_cleanup): Ditto.
* sigproc.cc (hwait_sig): Ditto.
(hwait_subproc): Ditto.
(proc_terminate): Ditto.
(sigproc_terminate): Ditto.
(sigproc_init): Initialize cygthread hwait_sig pointer.
(subproc_init): Initialize cygthread hwait_subproc pointer.
(wait_sig): Rely on cygthread HANDLE operator.
* strace.cc (strace::vsprntf): Use cygthread::name rather than threadname.
* window.cc (gethwnd): Use cygthread method to initialize thread.
This commit is contained in:
Christopher Faylor
2002-08-01 16:20:31 +00:00
parent 3874ac637c
commit b6bd703781
15 changed files with 321 additions and 287 deletions

186
winsup/cygwin/cygthread.cc Normal file
View File

@@ -0,0 +1,186 @@
/* cygthread.cc
Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
class cygthread
{
DWORD avail;
DWORD id;
HANDLE h;
HANDLE ev;
const char *__name;
LPTHREAD_START_ROUTINE func;
VOID *arg;
static DWORD main_thread_id;
static DWORD WINAPI runner (VOID *);
static DWORD WINAPI stub (VOID *);
public:
static const char * name (DWORD = 0);
cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *);
cygthread () {};
static void init ();
void detach ();
operator HANDLE ();
static bool is ();
void * operator new (size_t);
};
#include "winsup.h"
#include "exceptions.h"
#include "security.h"
#include "cygthread.h"
#include <windows.h>
#undef CloseHandle
static cygthread NO_COPY threads[8];
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
static HANDLE NO_COPY hthreads[NTHREADS];
DWORD NO_COPY cygthread::main_thread_id;
/* Initial stub called by makethread. Performs initial per-thread
initialization. */
DWORD WINAPI
cygthread::stub (VOID *arg)
{
DECLARE_TLS_STORAGE;
exception_list except_entry;
/* Initialize this thread's ability to respond to things like
SIGSEGV or SIGFPE. */
init_exceptions (&except_entry);
cygthread *info = (cygthread *) arg;
info->ev = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
while (1)
{
if (!info->func)
ExitThread (0);
/* Cygwin threads should not call ExitThread */
info->func (info->arg);
info->__name = NULL;
SetEvent (info->ev);
SuspendThread (info->h);
}
}
DWORD WINAPI
cygthread::runner (VOID *arg)
{
for (unsigned i = 0; i < NTHREADS; i++)
hthreads[i] = threads[i].h =
CreateThread (&sec_none_nih, 0, cygthread::stub, &threads[i],
CREATE_SUSPENDED, &threads[i].avail);
return 0;
}
void
cygthread::init ()
{
DWORD tid;
HANDLE h = CreateThread (&sec_none_nih, 0, cygthread::runner, NULL, 0, &tid);
if (!h)
api_fatal ("can't start thread_runner, %E");
CloseHandle (h);
main_thread_id = GetCurrentThreadId ();
}
bool
cygthread::is ()
{
DWORD tid = GetCurrentThreadId ();
for (DWORD i = 0; i < NTHREADS; i++)
if (threads[i].id == tid)
return 1;
return 0;
}
void * cygthread::operator
new (size_t)
{
DWORD id;
cygthread *info; /* Various information needed by the newly created thread */
for (;;)
{
/* Search the threads array for an empty slot to use */
for (info = threads; info < threads + NTHREADS; info++)
if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0)))
{
info->id = id;
return info;
}
/* thread_runner may not be finished yet. */
Sleep (0);
}
}
cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param,
const char *name): __name (name), func (start), arg (param)
{
while (ResumeThread (h) == 0)
Sleep (0);
}
/* Return the symbolic name of the current thread for debugging.
*/
const char *
cygthread::name (DWORD tid)
{
const char *res = NULL;
if (!tid)
tid = GetCurrentThreadId ();
if (tid == main_thread_id)
return "main";
for (DWORD i = 0; i < NTHREADS; i++)
if (threads[i].id == tid)
{
res = threads[i].__name ?: "exiting thread";
break;
}
if (!res)
{
static char buf[30] NO_COPY = {0};
__small_sprintf (buf, "unknown (%p)", tid);
res = buf;
}
return res;
}
cygthread::operator
HANDLE ()
{
while (!ev)
Sleep (0);
return ev;
}
void
cygthread::detach ()
{
if (!avail)
{
DWORD avail = id;
if (__name)
{
DWORD res = WaitForSingleObject (*this, INFINITE);
debug_printf ("WFSO returns %d", res);
}
id = 0;
(void) InterlockedExchange ((LPLONG) &this->avail, avail);
}
}