diff options
author | Robert Collins <rbtcollins@hotmail.com> | 2002-09-16 10:53:29 +0000 |
---|---|---|
committer | Robert Collins <rbtcollins@hotmail.com> | 2002-09-16 10:53:29 +0000 |
commit | 4e786173219dedb425672f495a36adbff68273f7 (patch) | |
tree | 4991e6c5a09d8a887826ba96fc2c9cf5055f780d /winsup/cygwin/thread.cc | |
parent | 0812076923f58711b8eab2eae0835810eb305d79 (diff) | |
download | cygnal-4e786173219dedb425672f495a36adbff68273f7.tar.gz cygnal-4e786173219dedb425672f495a36adbff68273f7.tar.bz2 cygnal-4e786173219dedb425672f495a36adbff68273f7.zip |
2002-09-11 Robert Collins <rbtcollins@hotmail.com>
* 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.
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r-- | winsup/cygwin/thread.cc | 208 |
1 files changed, 168 insertions, 40 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 618fa7a9d..3d9c40b48 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,11 +344,35 @@ 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 */ @@ -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 @@ -448,6 +488,9 @@ pthread::exit (void *value_ptr) mutex.UnLock (); } + /* Prevent DLL_THREAD_DETACH Attempting to clean us up */ + setTlsSelfPointer(0); + if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0) ::exit (0); else @@ -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 |