Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-08-01 20:20:31 +0400
committerChristopher Faylor <me@cgf.cx>2002-08-01 20:20:31 +0400
commitb6bd703781fdbe466e5a4d41e16743a642e7c0d3 (patch)
treeaa275a070284b0dfb7678c94d881b8ea87544b5f /winsup/cygwin/cygthread.cc
parent3874ac637cba083178c9e678e4cefcd204898c8e (diff)
* 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.cc186
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);
+ }
+}