From c350feda2096e2446bf7cc0b97019eed7386400d Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 14 Dec 2003 07:09:22 +0000 Subject: [PATCH] * cygthread.cc (cygthread::stub): Revert previous change and again subsume cygthread::stub2. Just return from function now since ExitThread is guaranteed by automatic _threadinfo wrapper. Define as per ThreadProc convention. (cygthread::stub2): Remove. (cygthread::simplestub): Perform similar operations to cygthread::stub. (cygthread::simplestub2): Remove. * cygthread.h (cygthread::stub): Declare as per ThreadProc convention. (cygthread::stub2): Remove declaration. (cygthread::simplestub): Declare as per ThreadProc convention. (cygthread::simplestub2): Remove declaration. * cygtls.h (_threadinfo::call): Define first argument as per ThreadProc convention. (_threadinfo::call2): Ditto. (_tlsbase): Define as char * pointer. (_tlstop): New definition. (_main_tls): Define here. * dcrt0.cc (alloc_stack): Revert previous change which called init_thread since information would be overwritten by fork later anyway. (dll_crt0_1): Use _tlsbase and _tlstop for setting stack bottom, top. * exceptions.cc: Move _main_tls declaration to cygtls.h. (_threadinfo::call): Define first argument as per ThreadProc convention. (_threadinfo::call2): Call ExitThread with thread function return value. (_threadinfo::init_thread): Don't initialize cygtls to zero if input arg is NULL. * fork.cc (fork_child): Reset _main_tls here. Reinitialize parts of _my_tls after copying data from parent. * init.cc (threadfunc_fe): New function. Front-end for all threads created in cygwin processes. (munge_threadfunc): New function. (dll_entry): Call munge_threadfunc to force the call of a thread wrapper. * thread.cc (pthread::thread_init_wrapper): Perform similar operations to cygthread::stub. (pthread::thread_init_wrapper2): Remove. * thread.h (pthread::thread_init_wrapper): Declare as per ThreadProc convention. (pthread::thread_init_wrapper2): Remove declaration. * window.cc (Winmain): Just return from function now since ExitThread is guaranteed by automatic _threadinfo wrapper. --- winsup/cygwin/ChangeLog | 46 +++++++++++++++++++++++++++++++++++++ winsup/cygwin/cygthread.cc | 18 ++------------- winsup/cygwin/cygthread.h | 2 +- winsup/cygwin/cygtls.h | 10 ++++---- winsup/cygwin/dcrt0.cc | 10 +++----- winsup/cygwin/exceptions.cc | 16 +++++++------ winsup/cygwin/fork.cc | 4 ++-- winsup/cygwin/init.cc | 35 +++++++++++++++++++++++++--- winsup/cygwin/thread.cc | 16 ++++--------- winsup/cygwin/thread.h | 3 +-- winsup/cygwin/window.cc | 2 +- 11 files changed, 108 insertions(+), 54 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8b178f531..d2ada0674 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,49 @@ +2003-12-14 Christopher Faylor + + * cygthread.cc (cygthread::stub): Revert previous change and again + subsume cygthread::stub2. Just return from function now since + ExitThread is guaranteed by automatic _threadinfo wrapper. Define as + per ThreadProc convention. + (cygthread::stub2): Remove. + (cygthread::simplestub): Perform similar operations to cygthread::stub. + (cygthread::simplestub2): Remove. + * cygthread.h (cygthread::stub): Declare as per ThreadProc convention. + (cygthread::stub2): Remove declaration. + (cygthread::simplestub): Declare as per ThreadProc convention. + (cygthread::simplestub2): Remove declaration. + * cygtls.h (_threadinfo::call): Define first argument as per ThreadProc + convention. + (_threadinfo::call2): Ditto. + (_tlsbase): Define as char * pointer. + (_tlstop): New definition. + (_main_tls): Define here. + * dcrt0.cc (alloc_stack): Revert previous change which called + init_thread since information would be overwritten by fork later + anyway. + (dll_crt0_1): Use _tlsbase and _tlstop for setting stack bottom, top. + * exceptions.cc: Move _main_tls declaration to cygtls.h. + (_threadinfo::call): Define first argument as per ThreadProc + convention. + (_threadinfo::call2): Call ExitThread with thread function return + value. + (_threadinfo::init_thread): Don't initialize cygtls to zero if input + arg is NULL. + * fork.cc (fork_child): Reset _main_tls here. Reinitialize parts of + _my_tls after copying data from parent. + * init.cc (threadfunc_fe): New function. Front-end for all threads + created in cygwin processes. + (munge_threadfunc): New function. + (dll_entry): Call munge_threadfunc to force the call of a thread + wrapper. + * thread.cc (pthread::thread_init_wrapper): Perform similar operations + to cygthread::stub. + (pthread::thread_init_wrapper2): Remove. + * thread.h (pthread::thread_init_wrapper): Declare as per ThreadProc + convention. + (pthread::thread_init_wrapper2): Remove declaration. + * window.cc (Winmain): Just return from function now since ExitThread + is guaranteed by automatic _threadinfo wrapper. + 2003-12-12 Christopher Faylor * dtable.cc (dtable::delete_archetype): Add debugging. diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 2a120fb61..16f629634 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -31,13 +31,6 @@ bool NO_COPY cygthread::exiting; to execute. */ DWORD WINAPI cygthread::stub (VOID *arg) -{ - _threadinfo::call (stub2, arg); - return 0; -} - -void -cygthread::stub2 (void *arg, void *) { exception_list except_entry; /* Initialize this thread's ability to respond to things like @@ -71,7 +64,7 @@ cygthread::stub2 (void *arg, void *) else { if (!info->func || exiting) - ExitThread (0); + return 0; /* Cygwin threads should not call ExitThread directly */ info->func (info->arg == cygself ? info : info->arg); @@ -98,13 +91,6 @@ cygthread::stub2 (void *arg, void *) and then exits the thread. */ DWORD WINAPI cygthread::simplestub (VOID *arg) -{ - _threadinfo::call (simplestub2, arg); - return 0; -} - -void -cygthread::simplestub2 (void *arg, void *) { exception_list except_entry; /* Initialize this thread's ability to respond to things like @@ -116,7 +102,7 @@ cygthread::simplestub2 (void *arg, void *) info->stack_ptr = &arg; info->ev = info->h; info->func (info->arg == cygself ? info : info->arg); - ExitThread (0); + return 0; } /* Start things going. Called from dll_crt0_1. */ diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index a01719b7e..eb2eb9a8f 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -19,12 +19,12 @@ class cygthread VOID *arg; bool is_freerange; static bool exiting; - static DWORD WINAPI stub (VOID *); static void stub2 (void *, void *); static DWORD WINAPI simplestub (VOID *); static void simplestub2 (void *, void *); void terminate_thread (); public: + static DWORD WINAPI stub (VOID *); static DWORD main_thread_id; static const char * name (DWORD = 0); cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *); diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index f62efed12..29f2103b1 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -44,8 +44,8 @@ struct _threadinfo static CRITICAL_SECTION protect_linked_list; static void init (); void init_thread (void *); - static void call (void (*) (void *, void *), void *); - void call2 (void (*) (void *, void *), void *, void *); + static void call (DWORD (*) (void *, void *), void *); + void call2 (DWORD (*) (void *, void *), void *, void *); static struct _threadinfo *find_tls (int sig); void remove (); void push (__stack_t, bool = false); @@ -62,8 +62,10 @@ struct _threadinfo }; #pragma pack(pop) -extern _threadinfo *_tlsbase __asm__ ("%fs:4"); -#define _my_tls (_tlsbase[-1]) +extern char *_tlsbase __asm__ ("%fs:4"); +extern char *_tlstop __asm__ ("%fs:8"); +#define _my_tls (((_threadinfo *) _tlsbase)[-1]) +extern _threadinfo *_main_tls; #define CYGTLS_PADSIZE (sizeof (_threadinfo) + 64) #endif /*_CYGTLS_H*/ diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 0b878a8b3..72161f91e 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -520,11 +520,7 @@ alloc_stack (child_info_fork *ci) if (sm.AllocationBase == ci->stacktop) ci->stacksize = 0; else - { - alloc_stack_hard_way (ci, b + sizeof (b) - 1); - _main_tls = &_my_tls; - _main_tls->init_thread (NULL); - } + alloc_stack_hard_way (ci, b + sizeof (b) - 1); return; } @@ -665,8 +661,8 @@ dll_crt0_1 () this step. */ if (fork_info->stacksize) { - asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom)); - asm ("movl %0,%%fs:8" : : "r" (fork_info->stacktop)); + _tlsbase = (char *) fork_info->stackbottom; + _tlstop = (char *) fork_info->stacktop; } longjmp (fork_info->jmp, fork_info->cygpid); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index feb36327c..a47951936 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -38,7 +38,6 @@ extern void sigdelayed (); _threadinfo NO_COPY dummy_thread; _threadinfo NO_COPY *_last_thread = &dummy_thread; -extern _threadinfo *_main_tls; CRITICAL_SECTION NO_COPY _threadinfo::protect_linked_list; @@ -150,17 +149,17 @@ _threadinfo::reset_exception () } void -_threadinfo::call (void (*func) (void *, void *), void *arg) +_threadinfo::call (DWORD (*func) (void *, void *), void *arg) { char buf[CYGTLS_PADSIZE]; _my_tls.call2 (func, arg, buf); } void -_threadinfo::call2 (void (*func) (void *, void *), void *arg, void *buf) +_threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf) { init_thread (buf); - func (arg, buf); + ExitThread (func (arg, buf)); } void @@ -170,10 +169,13 @@ _threadinfo::init () } void -_threadinfo::init_thread (void *) +_threadinfo::init_thread (void *x) { - memset (this, 0, sizeof (*this)); - stackptr = stack; + if (x) + { + memset (this, 0, sizeof (*this)); + stackptr = stack; + } EnterCriticalSection (&protect_linked_list); prev = _last_thread; diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index e6ab93902..66f83a033 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -262,8 +262,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls) Exit with a status code of 0. */ if (fork_info->stacksize) { - ((DWORD *)fork_info->stackbottom)[-17] = (DWORD)do_exit; - ((DWORD *)fork_info->stackbottom)[-15] = (DWORD)0; + _main_tls = &_my_tls; + _my_tls.init_thread (NULL); } set_file_api_mode (current_codepage); diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index dc2b1a717..94453f602 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -12,12 +12,41 @@ details. */ #include #include "thread.h" #include "perprocess.h" +#include "cygthread.h" #include "cygtls.h" int NO_COPY dynamically_loaded; -extern "C" int -WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) +static void WINAPI +threadfunc_fe (VOID *arg) +{ + _threadinfo::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[-1]), arg); +} + +static void +munge_threadfunc (HANDLE cygwin_hmodule) +{ + char **ebp = (char **) __builtin_frame_address (0); + static unsigned threadfunc_ix; + if (!threadfunc_ix) + { + for (char **peb = ebp; peb < (char **) _tlsbase; peb++) + if (*peb == (char *) cygthread::stub) + { + threadfunc_ix = peb - ebp; + goto foundit; + } + return; + } + +foundit: + char *threadfunc = ebp[threadfunc_ix]; + ebp[threadfunc_ix] = (char *) threadfunc_fe; + ((char **) _tlsbase)[-1] = threadfunc; +} + +extern "C" int WINAPI +dll_entry (HANDLE h, DWORD reason, void *static_load) { switch (reason) { @@ -28,9 +57,9 @@ WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: - _my_tls.stackptr = _my_tls.stack; if (MT_INTERFACE->reent_key.set (&MT_INTERFACE->reents)) api_fatal ("thread initialization failed"); + munge_threadfunc (h); break; } return 1; diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index b2ba543fe..93bf701ac 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -338,8 +338,8 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, arg = threadarg; win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize, - (LPTHREAD_START_ROUTINE) thread_init_wrapper, - this, CREATE_SUSPENDED, &thread_id); + thread_init_wrapper, this, CREATE_SUSPENDED, + &thread_id); if (!win32_obj_id) { @@ -1887,8 +1887,8 @@ __reent_t::init_clib (struct _reent& var) _clib = &var; }; -void -pthread::thread_init_wrapper2 (void *arg, void *) +DWORD WINAPI +pthread::thread_init_wrapper (void *arg) { pthread *thread = (pthread *) arg; _my_tls.tid = thread; @@ -1928,14 +1928,8 @@ pthread::thread_init_wrapper2 (void *arg, void *) void *ret = thread->function (thread->arg); thread->exit (ret); -} -/* Pthreads */ -void -pthread::thread_init_wrapper (void *arg) -{ - // calls thread_init_wrapper2. Never returns. - _threadinfo::call (thread_init_wrapper2, arg); + return 0; // just for show. Never returns. } bool diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index e530a649d..4e94cbbb4 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -502,8 +502,7 @@ public: virtual void pop_cleanup_handler (int const execute); static pthread* self (); - static void thread_init_wrapper (void *); - static void thread_init_wrapper2 (void *, void *); + static DWORD WINAPI thread_init_wrapper (void *); virtual unsigned long getsequence_np(); diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc index 3f9462509..f9f5da23a 100644 --- a/winsup/cygwin/window.cc +++ b/winsup/cygwin/window.cc @@ -120,7 +120,7 @@ Winmain (VOID *) while (GetMessage (&msg, ourhwnd, 0, 0) == TRUE) DispatchMessage (&msg); - ExitThread (0); + return 0; } HWND __stdcall