* 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:
@@ -7,7 +7,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include "exceptions.h"
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
@@ -25,148 +24,6 @@ details. */
|
||||
|
||||
#undef CloseHandle
|
||||
|
||||
static muto NO_COPY *threadname_lock = NULL;
|
||||
#define lock_threadname() \
|
||||
do {if (threadname_lock) threadname_lock->acquire (INFINITE); } while (0)
|
||||
|
||||
#define unlock_threadname() \
|
||||
do {if (threadname_lock) threadname_lock->release (); } while (0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD id;
|
||||
const char *name;
|
||||
} thread_info;
|
||||
|
||||
static NO_COPY thread_info threads[32]; // increase as necessary
|
||||
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
|
||||
|
||||
void
|
||||
threadname_init ()
|
||||
{
|
||||
new_muto (threadname_lock);
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
regthread (const char *name, DWORD tid)
|
||||
{
|
||||
lock_threadname ();
|
||||
for (DWORD i = 0; i < NTHREADS; i++)
|
||||
if (threads[i].name == NULL || strcmp (threads[i].name, name) == 0 ||
|
||||
threads[i].id == tid)
|
||||
{
|
||||
threads[i].name = name;
|
||||
threads[i].id = tid;
|
||||
break;
|
||||
}
|
||||
unlock_threadname ();
|
||||
}
|
||||
|
||||
int __stdcall
|
||||
iscygthread ()
|
||||
{
|
||||
DWORD tid = GetCurrentThreadId ();
|
||||
if (tid != mainthread.id)
|
||||
for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++)
|
||||
if (threads[i].id == tid)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct thread_start
|
||||
{
|
||||
LONG notavail;
|
||||
LPTHREAD_START_ROUTINE func;
|
||||
VOID *arg;
|
||||
};
|
||||
|
||||
/* A place to store arguments to thread_stub since they can't be
|
||||
stored on the stack. An available element is !notavail. */
|
||||
thread_start NO_COPY start_buf[NTHREADS] = {{0, NULL,NULL}};
|
||||
|
||||
/* Initial stub called by makethread. Performs initial per-thread
|
||||
initialization. */
|
||||
static DWORD WINAPI
|
||||
thread_stub (VOID *arg)
|
||||
{
|
||||
DECLARE_TLS_STORAGE;
|
||||
LPTHREAD_START_ROUTINE threadfunc = ((thread_start *) arg)->func;
|
||||
VOID *threadarg = ((thread_start *) arg)->arg;
|
||||
|
||||
exception_list except_entry;
|
||||
|
||||
/* Give up our slot in the start_buf array */
|
||||
(void) InterlockedExchange (&((thread_start *) arg)->notavail, 0);
|
||||
|
||||
/* Initialize this thread's ability to respond to things like
|
||||
SIGSEGV or SIGFPE. */
|
||||
init_exceptions (&except_entry);
|
||||
|
||||
ExitThread (threadfunc (threadarg));
|
||||
}
|
||||
|
||||
/* Wrapper for CreateThread. Registers the thread name/id and ensures that
|
||||
cygwin threads are properly initialized. */
|
||||
HANDLE __stdcall
|
||||
makethread (LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags,
|
||||
const char *name)
|
||||
{
|
||||
DWORD tid;
|
||||
HANDLE h;
|
||||
thread_start *info; /* Various information needed by the newly created thread */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Search the start_buf array for an empty slot to use */
|
||||
for (info = start_buf; info < start_buf + NTHREADS; info++)
|
||||
if (!InterlockedExchange (&info->notavail, 1))
|
||||
goto out;
|
||||
|
||||
/* Should never hit here, but be defensive anyway. */
|
||||
Sleep (0);
|
||||
}
|
||||
|
||||
out:
|
||||
info->func = start; /* Real function to start */
|
||||
info->arg = param; /* The single parameter to the thread */
|
||||
|
||||
if ((h = CreateThread (&sec_none_nih, 0, thread_stub, (VOID *) info, flags,
|
||||
&tid)))
|
||||
regthread (name, tid); /* Register for debugging output. */
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Return the symbolic name of the current thread for debugging.
|
||||
*/
|
||||
const char * __stdcall
|
||||
threadname (DWORD tid, int lockit)
|
||||
{
|
||||
const char *res = NULL;
|
||||
if (!tid)
|
||||
tid = GetCurrentThreadId ();
|
||||
|
||||
if (lockit)
|
||||
lock_threadname ();
|
||||
for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++)
|
||||
if (threads[i].id == tid)
|
||||
{
|
||||
res = threads[i].name;
|
||||
break;
|
||||
}
|
||||
if (lockit)
|
||||
unlock_threadname ();
|
||||
|
||||
if (!res)
|
||||
{
|
||||
static char buf[30] NO_COPY = {0};
|
||||
__small_sprintf (buf, "unknown (%p)", tid);
|
||||
res = buf;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGING
|
||||
/* Here lies extra debugging routines which help track down internal
|
||||
Cygwin problems when compiled with -DDEBUGGING . */
|
||||
|
Reference in New Issue
Block a user