diff options
author | Christopher Faylor <me@cgf.cx> | 2002-08-01 16:20:31 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2002-08-01 16:20:31 +0000 |
commit | b6bd703781fdbe466e5a4d41e16743a642e7c0d3 (patch) | |
tree | aa275a070284b0dfb7678c94d881b8ea87544b5f /winsup/cygwin/cygthread.cc | |
parent | 3874ac637cba083178c9e678e4cefcd204898c8e (diff) | |
download | cygnal-b6bd703781fdbe466e5a4d41e16743a642e7c0d3.tar.gz cygnal-b6bd703781fdbe466e5a4d41e16743a642e7c0d3.tar.bz2 cygnal-b6bd703781fdbe466e5a4d41e16743a642e7c0d3.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/cygthread.cc')
-rw-r--r-- | winsup/cygwin/cygthread.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc new file mode 100644 index 000000000..bbfcd8218 --- /dev/null +++ b/winsup/cygwin/cygthread.cc @@ -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); + } +} |