From c2b91d800e64ac8106a86b28959dcbaca814df0b Mon Sep 17 00:00:00 2001 From: scottc Date: Mon, 16 Sep 2002 17:24:16 +0000 Subject: Merged changes from HEAD --- winsup/cygwin/ChangeLog | 87 +++++++++++++++++- winsup/cygwin/init.cc | 22 ++--- winsup/cygwin/pthread.cc | 7 +- winsup/cygwin/syscalls.cc | 20 +++-- winsup/cygwin/thread.cc | 224 ++++++++++++++++++++++++++++++++++++---------- winsup/cygwin/thread.h | 70 +++++++++------ 6 files changed, 333 insertions(+), 97 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f5b42ef9ca4..32ac26d817b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,86 @@ +2002-09-16 Christopher Faylor + + * init.cc: Cleanup slightly and remove obsolete code. + +2002-09-11 Robert Collins + + * init.cc (dll_entry): On thread detach, if the thread hasn't + exit()ed, do so. + * pthread.cc (pthread_getsequence_np): Remove the + __pthread_getsequence_np wrapper. This requires errno.h. + * thread.cc (pthread::self): Instantiate a new pthread object + when called and none exists. return a NULL object if instantiation + fails. + (pthread::precreate): Factor out common code. + (pthread::postcreate): Ditto. + (pthread::create): Ditto. + (pthread::exit): Remove the TLS value when we exit to prevent + double exits. + (MTinterface::Init): Bugfix - don't mark the TLS index as created + if one was not allocated. + Apply Extract Method to move pthread specific initialisation into + pthread. + (pthread::initMainThread): Extracted method from MTinterface::Init. + (pthread::setTlsSelfPointer): Extracted method from various pthread + calls, to make reading those functions easier. + (pthread::setThreadIdtoCurrent): Ditto. + (pthread::cancel_self): Bring into the .cc file, it's only used + within the class. + (pthread::getThreadId): Ditto. + (pthread::thread_init_wrapper): Apply Extract Method to the TLS + setting logic. + (pthread::isGoodObject): Extracted method from various pthread + wrapper calls, for clarity of reading. + (pthread::getsequence_np): Converted from __pthread_getsquence_np. + (__pthread_create): Apply Extract Method to the object validation. + (__pthread_cancel): Ditto. + (__pthread_join): Ditto. + (__pthread_detach): Ditto. + (__pthread_suspend): Ditto. + (__pthread_continue): Ditto. + (__pthread_getschedparam): Ditto. + (__pthread_getsequence_np): Remove. + (__pthread_setschedparam): Apply Extract Method to the object + validation. + (pthreadNull::getNullpthread): New method, return the pthreadNull + object. + (pthreadNull::pthreadNull): Private constructor to prevent accidental + use. + (pthreadNull::~pthreadNull): Prevent compile warnings. + (pthreadNull::create): Override pthread behaviour. + (pthreadNull::exit): Ditto. + (pthreadNull::cancel): Ditto. + (pthreadNull::testcancel): Ditto. + (pthreadNull::setcancelstate): Ditto. + (pthreadNull::setcanceltype): Ditto. + (pthreadNull::push_cleanup_handler): Ditto. + (pthreadNull::pop_cleanup_handler): Ditto. + (pthreadNull::getsequence_np): Ditto. + (pthreadNull::_instance): Ditto. + * thread.h (pthread): Declare pre- and post-create. + Move GetThreadId to private scope and rename to getThreadId. + Move setThreadIdtoCurrent to private scope. + Make create virtual. + Make ~pthread virtual. + Declare initMainThread. + Declare isGoodObject. + Make exit virtual. + Make cancel virtual. + Make testcancel virtual. + Make setcancelstate virtual. + Make setcanceltype virtual. + Make push_cleanup_handler virtual. + Make pop_cleanup_handler virtual. + Declare getsequence_np. + Declare setTlsSelfPointer. + (pthreadNull): New null object class for pthread. + (__pthread_getsequence_np): Remove. + +2002-09-13 Corinna Vinschen + + * syscalls.cc (seteuid32): Treat ILLEGAL_UID invalid. + (setegid32): Treat ILLEGAL_GID invalid. + 2002-09-10 Pierre Humblet * grp.cc (initgroups): Call groups::clear_supp to free the @@ -251,7 +334,7 @@ 2002-08-26 Christopher Faylor - * Makefile.in (cygcheck.exe): Make a -mno-cygwin program. + * Makefile.in (cygrunk.exe): Make a -mno-cygwin program. * cygrun.c (main): Export CYGWIN=ntsec unless otherwise set. * shared.cc (shared_name): Only add build date to shared name when @@ -459,7 +542,7 @@ * cygthread.cc (cygthread::stub): Accept flag to pass info structure to thread function. - (cygthread::operator new): Add defense debugging output. + (cygthread::operator new): Add defensive debugging output. (cygthread::cygthread): Add debugging output. Set name after thread has been awakened to avoid a race. (cygthread::exit_thread): Use handle operator rather than using ev diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index 525ec29b1c6..ca5e7176d54 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -1,6 +1,6 @@ /* init.cc - Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. This file is part of Cygwin. @@ -35,19 +35,13 @@ WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) case DLL_PROCESS_DETACH: break; case DLL_THREAD_DETACH: -#if 0 // FIXME: REINSTATE SOON - waitq *w; - if ((w = waitq_storage.get ()) != NULL) - { - if (w->thread_ev != NULL) - { - system_printf ("closing %p", w->thread_ev); - (void) CloseHandle (w->thread_ev); - } - memset (w, 0, sizeof(*w)); // FIXME: memory leak - } - // FIXME: Need to add other per_thread stuff here -#endif + pthread *thisthread = (pthread *) TlsGetValue ( + user_data->threadinterface->thread_self_dwTlsIndex); + if (thisthread) { + /* Some non-pthread call created this thread, + * but we need to clean it up */ + thisthread->exit(0); + } break; } return 1; diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc index 0484f0412c2..90eb20f2573 100644 --- a/winsup/cygwin/pthread.cc +++ b/winsup/cygwin/pthread.cc @@ -1,6 +1,6 @@ /* pthread.cc: posix pthread interface for Cygwin - Copyright 1998, 1999, 2000, 2001 Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. Originally written by Marco Fuykschot @@ -12,6 +12,7 @@ #include "winsup.h" #include "thread.h" +#include "errno.h" extern "C" { @@ -173,7 +174,9 @@ pthread_continue (pthread_t thread) unsigned long pthread_getsequence_np (pthread_t * thread) { - return __pthread_getsequence_np (thread); + if (!pthread::isGoodObject (thread)) + return EINVAL; + return (*thread)->getsequence_np(); } /* Thread SpecificData */ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 657a40cfc3e..8c2b96b7b3e 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1943,14 +1943,18 @@ seteuid32 (__uid32_t uid) debug_printf ("uid: %d myself->gid: %d", uid, myself->gid); if (!wincap.has_security () - || (uid == myself->uid - && !cygheap->user.groups.ischanged) - || uid == ILLEGAL_UID) + || (uid == myself->uid && !cygheap->user.groups.ischanged)) { debug_printf ("Nothing happens"); return 0; } + if (uid == ILLEGAL_UID) + { + set_errno (EINVAL); + return -1; + } + sigframe thisframe (mainthread); cygsid usersid; user_groups &groups = cygheap->user.groups; @@ -2122,11 +2126,15 @@ setuid (__uid16_t uid) extern "C" int setegid32 (__gid32_t gid) { - if ((!wincap.has_security ()) || - (gid == myself->gid) || - (gid == ILLEGAL_GID)) + if (!wincap.has_security () || gid == myself->gid) return 0; + if (gid == ILLEGAL_GID) + { + set_errno (EINVAL); + return -1; + } + sigframe thisframe (mainthread); user_groups * groups = &cygheap->user.groups; cygsid gsid; diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 618fa7a9d8f..2e2f353a875 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -283,20 +283,18 @@ MTinterface::Init (int forked) if (!indexallocated) { - indexallocated = (-1); thread_self_dwTlsIndex = TlsAlloc (); if (thread_self_dwTlsIndex == TLS_OUT_OF_INDEXES) system_printf ("local storage for thread couldn't be set\nThis means that we are not thread safe!"); + else + indexallocated = (-1); } concurrency = 0; threadcount = 1; /*1 current thread when Init occurs.*/ - mainthread.win32_obj_id = myself->hProcess; - mainthread.setThreadIdtoCurrent (); - /*store the main thread's self pointer */ - TlsSetValue (thread_self_dwTlsIndex, &mainthread); + pthread::initMainThread(&mainthread, myself->hProcess); if (forked) return; @@ -346,17 +344,41 @@ MTinterface::fixup_after_fork (void) /* pthread calls */ /* static methods */ +void +pthread::initMainThread(pthread *mainThread, HANDLE win32_obj_id) +{ + mainThread->win32_obj_id = win32_obj_id; + mainThread->setThreadIdtoCurrent (); + setTlsSelfPointer(mainThread); +} pthread * pthread::self () { - return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); + pthread *temp = (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); + if (temp) + return temp; + temp = new pthread (); + temp->precreate (NULL); + if (!temp->magic) { + delete temp; + return pthreadNull::getNullpthread(); + } + temp->postcreate (); + return temp; +} + +void +pthread::setTlsSelfPointer(pthread *thisThread) +{ + /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */ + TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread); } /* member methods */ pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0), - cancelstate (0), canceltype (0), cancel_event(0), - joiner (NULL), cleanup_stack(NULL) + cancelstate (0), canceltype (0), cancel_event(0), + joiner (NULL), cleanup_stack(NULL) { } @@ -368,10 +390,14 @@ pthread::~pthread () CloseHandle (cancel_event); } +void +pthread::setThreadIdtoCurrent () +{ + thread_id = GetCurrentThreadId (); +} void -pthread::create (void *(*func) (void *), pthread_attr *newattr, - void *threadarg) +pthread::precreate (pthread_attr *newattr) { pthread_mutex *verifyable_mutex_obj = &mutex; @@ -386,8 +412,6 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, attr.inheritsched = newattr->inheritsched; attr.stacksize = newattr->stacksize; } - function = func; - arg = threadarg; if (verifyable_object_isvalid (&verifyable_mutex_obj, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT) { @@ -405,6 +429,17 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, magic = 0; return; } +} + +void +pthread::create (void *(*func) (void *), pthread_attr *newattr, + void *threadarg) +{ + precreate (newattr); + if (!magic) + return; + function = func; + arg = threadarg; win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize, (LPTHREAD_START_ROUTINE) thread_init_wrapper, @@ -415,17 +450,22 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, thread_printf ("CreateThread failed: this %p LastError %E", this); magic = 0; } - else - { - InterlockedIncrement (&MT_INTERFACE->threadcount); - /*FIXME: set the priority appropriately for system contention scope */ - if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED) - { - /*FIXME: set the scheduling settings for the new thread */ - /*sched_thread_setparam (win32_obj_id, attr.schedparam); */ - } + else { + postcreate (); ResumeThread (win32_obj_id); - } + } +} + +void +pthread::postcreate () +{ + InterlockedIncrement (&MT_INTERFACE->threadcount); + /*FIXME: set the priority appropriately for system contention scope */ + if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED) + { + /*FIXME: set the scheduling settings for the new thread */ + /*sched_thread_setparam (win32_obj_id, attr.schedparam); */ + } } void @@ -443,11 +483,14 @@ pthread::exit (void *value_ptr) if( __pthread_equal(&joiner, &thread ) ) delete this; else - { + { return_ptr = value_ptr; mutex.UnLock (); } + /* Prevent DLL_THREAD_DETACH Attempting to clean us up */ + setTlsSelfPointer(0); + if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0) ::exit (0); else @@ -696,7 +739,7 @@ pthread::setcancelstate (int state, int *oldstate) else { if (oldstate) - *oldstate = cancelstate; + *oldstate = cancelstate; cancelstate = state; } @@ -717,7 +760,7 @@ pthread::setcanceltype (int type, int *oldtype) else { if (oldtype) - *oldtype = canceltype; + *oldtype = canceltype; canceltype = type; } @@ -731,7 +774,7 @@ pthread::push_cleanup_handler (__pthread_cleanup_handler *handler) { if (this != self ()) // TODO: do it? - api_fatal ("Attempt to push a cleanup handler across threads"); + api_fatal ("Attempt to push a cleanup handler across threads"); handler->next = cleanup_stack; InterlockedExchangePointer( &cleanup_stack, handler ); } @@ -742,7 +785,7 @@ pthread::pop_cleanup_handler (int const execute) if (this != self ()) // TODO: send a signal or something to the thread ? api_fatal ("Attempt to execute a cleanup handler across threads"); - + mutex.Lock (); if (cleanup_stack != NULL) @@ -750,7 +793,7 @@ pthread::pop_cleanup_handler (int const execute) __pthread_cleanup_handler *handler = cleanup_stack; if (execute) - (*handler->function) (handler->arg); + (*handler->function) (handler->arg); cleanup_stack = handler->next; } @@ -764,6 +807,18 @@ pthread::pop_all_cleanup_handlers () pop_cleanup_handler (1); } +void +pthread::cancel_self() +{ + exit (PTHREAD_CANCELED); +} + +DWORD +pthread::getThreadId() +{ + return thread_id; +} + pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS), inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0) @@ -1278,8 +1333,7 @@ pthread::thread_init_wrapper (void *_arg) if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent)) system_printf ("local storage for thread couldn't be set"); - /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */ - TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); + setTlsSelfPointer(thread); thread->mutex.Lock (); // if thread is detached force cleanup on exit @@ -1308,6 +1362,20 @@ pthread::thread_init_wrapper (void *_arg) return 0; } +bool +pthread::isGoodObject (pthread_t *thread) +{ + if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + return false; + return true; +} + +unsigned long +pthread::getsequence_np () +{ + return getThreadId (); +} + int __pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) @@ -1318,7 +1386,7 @@ __pthread_create (pthread_t *thread, const pthread_attr_t *attr, *thread = new pthread (); (*thread)->create (start_routine, attr ? *attr : NULL, arg); - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (thread)) { delete (*thread); *thread = NULL; @@ -1355,7 +1423,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) int __pthread_cancel (pthread_t thread) { - if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (&thread)) return ESRCH; return thread->cancel (); @@ -1642,7 +1710,7 @@ __pthread_join (pthread_t *thread, void **return_val) *return_val = NULL; /*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/ - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (thread)) return ESRCH; if (__pthread_equal(thread,&joiner)) @@ -1675,7 +1743,7 @@ __pthread_join (pthread_t *thread, void **return_val) int __pthread_detach (pthread_t *thread) { - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (thread)) return ESRCH; (*thread)->mutex.Lock (); @@ -1706,7 +1774,7 @@ __pthread_detach (pthread_t *thread) int __pthread_suspend (pthread_t *thread) { - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (thread)) return ESRCH; if ((*thread)->suspended == false) @@ -1722,7 +1790,7 @@ __pthread_suspend (pthread_t *thread) int __pthread_continue (pthread_t *thread) { - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (thread)) return ESRCH; if ((*thread)->suspended == true) @@ -1746,7 +1814,7 @@ int __pthread_getschedparam (pthread_t thread, int *policy, struct sched_param *param) { - if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (&thread)) return ESRCH; *policy = SCHED_FIFO; /*we don't return the current effective priority, we return the current requested @@ -1755,15 +1823,6 @@ __pthread_getschedparam (pthread_t thread, int *policy, return 0; } - -unsigned long -__pthread_getsequence_np (pthread_t *thread) -{ - if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) - return EINVAL; - return (*thread)->GetThreadId (); -} - /*Thread SpecificData */ int __pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) @@ -1812,7 +1871,7 @@ int __pthread_setschedparam (pthread_t thread, int policy, const struct sched_param *param) { - if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (&thread)) return ESRCH; if (policy != SCHED_FIFO) return ENOTSUP; @@ -2045,7 +2104,7 @@ __pthread_kill (pthread_t thread, int sig) // lock myself, for the use of thread2signal // two different kills might clash: FIXME - if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT) + if (!pthread::isGoodObject (&thread)) return EINVAL; if (thread->sigs) @@ -2401,4 +2460,73 @@ __sem_post (sem_t *sem) return 0; } +/* pthreadNull */ +pthread * +pthreadNull::getNullpthread() +{ + /* because of weird entry points */ + _instance.magic = 0; + return &_instance; +} + +pthreadNull::pthreadNull() +{ + /* Mark ourselves as invalid */ + magic = 0; +} + +pthreadNull::~pthreadNull() +{ +} + +void +pthreadNull::create (void *(*)(void *), pthread_attr *, void *) +{ +} + +void +pthreadNull::exit (void *value_ptr) +{ +} + +int +pthreadNull::cancel () +{ + return 0; +} + +void +pthreadNull::testcancel () +{ +} + +int +pthreadNull::setcancelstate (int state, int *oldstate) +{ + return EINVAL; +} + +int +pthreadNull::setcanceltype (int type, int *oldtype) +{ + return EINVAL; +} + +void +pthreadNull::push_cleanup_handler (__pthread_cleanup_handler *handler) +{ +} + +void +pthreadNull::pop_cleanup_handler (int const execute) +{ +} +unsigned long +pthreadNull::getsequence_np() +{ + return 0; +} + +pthreadNull pthreadNull::_instance = pthreadNull (); + #endif // MT_SAFE diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index a00ad903d05..8c69886a0f9 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -270,43 +270,35 @@ public: pthread_t joiner; // int joinable; - DWORD GetThreadId () - { - return thread_id; - } - void setThreadIdtoCurrent () - { - thread_id = GetCurrentThreadId (); - } - /* signal handling */ struct sigaction *sigs; sigset_t *sigmask; LONG *sigtodo; - void create (void *(*)(void *), pthread_attr *, void *); + virtual void create (void *(*)(void *), pthread_attr *, void *); + + pthread (); + virtual ~pthread (); - pthread (); - ~pthread (); + static void initMainThread(pthread *, HANDLE); + static bool isGoodObject(pthread_t *); - void exit (void *value_ptr); + virtual void exit (void *value_ptr); - int cancel (); - void testcancel (); - void cancel_self () - { - exit (PTHREAD_CANCELED); - } + virtual int cancel (); + virtual void testcancel (); static void static_cancel_self (); - int setcancelstate (int state, int *oldstate); - int setcanceltype (int type, int *oldtype); + virtual int setcancelstate (int state, int *oldstate); + virtual int setcanceltype (int type, int *oldtype); - void push_cleanup_handler (__pthread_cleanup_handler *handler); - void pop_cleanup_handler (int const execute); + virtual void push_cleanup_handler (__pthread_cleanup_handler *handler); + virtual void pop_cleanup_handler (int const execute); static pthread* self (); static void *thread_init_wrapper (void *); + virtual unsigned long getsequence_np(); + private: DWORD thread_id; __pthread_cleanup_handler *cleanup_stack; @@ -316,6 +308,36 @@ private: friend int __pthread_detach (pthread_t * thread); void pop_all_cleanup_handlers (void); + void precreate (pthread_attr *); + void postcreate (); + void setThreadIdtoCurrent(); + static void setTlsSelfPointer(pthread *); + void cancel_self (); + DWORD getThreadId (); +}; + +class pthreadNull : public pthread +{ + public: + static pthread *getNullpthread(); + ~pthreadNull(); + + /* From pthread These should never get called + * as the ojbect is not verifyable + */ + void create (void *(*)(void *), pthread_attr *, void *); + void exit (void *value_ptr); + int cancel (); + void testcancel (); + int setcancelstate (int state, int *oldstate); + int setcanceltype (int type, int *oldtype); + void push_cleanup_handler (__pthread_cleanup_handler *handler); + void pop_cleanup_handler (int const execute); + unsigned long getsequence_np(); + + private: + pthreadNull (); + static pthreadNull _instance; }; class pthread_condattr:public verifyable_object @@ -458,8 +480,6 @@ int __pthread_attr_setstackaddr (pthread_attr_t *, void *); int __pthread_suspend (pthread_t * thread); int __pthread_continue (pthread_t * thread); -unsigned long __pthread_getsequence_np (pthread_t * thread); - /* Thread SpecificData */ int __pthread_key_create (pthread_key_t * key, void (*destructor) (void *)); int __pthread_key_delete (pthread_key_t key); -- cgit v1.2.1