From aea1f301fcc9037a222ccf7c2f0f247cdeb2d06e Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 29 Sep 2002 02:19:35 +0000 Subject: [PATCH] * cygthread.h (cygthread::terminate): Declare new function. (cygthread::initialized): Change to 'int'. * cygthread.cc (cygthread::stub): Exit thread if initialized < 0. (cygthread::new): Ditto. (cygthread::runner): Ditto. Set initialized using xor to preserve sign. (cygthread::terminate): New function. * dcrt0.cc (do_exit): Call cygthread::terminate. --- winsup/cygwin/ChangeLog | 11 +++ winsup/cygwin/cygthread.cc | 35 ++++++-- winsup/cygwin/cygthread.h | 3 +- winsup/cygwin/dcrt0.cc | 1 + winsup/cygwin/thread.h | 160 ++++++++++++++++++------------------- 5 files changed, 123 insertions(+), 87 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 591dcfc30..005dea333 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2002-09-28 Christopher Faylor + + * cygthread.h (cygthread::terminate): Declare new function. + (cygthread::initialized): Change to 'int'. + * cygthread.cc (cygthread::stub): Exit thread if initialized < 0. + (cygthread::new): Ditto. + (cygthread::runner): Ditto. Set initialized using xor to preserve + sign. + (cygthread::terminate): New function. + * dcrt0.cc (do_exit): Call cygthread::terminate. + 2002-09-27 Robert Collins * thread.cc (pthread_key::run_destructor): Run_destructor is not diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index b81c4c16f..b2a62247b 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -19,7 +19,7 @@ static cygthread NO_COPY threads[6]; #define NTHREADS (sizeof (threads) / sizeof (threads[0])) DWORD NO_COPY cygthread::main_thread_id; -bool NO_COPY cygthread::initialized; +int NO_COPY cygthread::initialized; /* Initial stub called by cygthread constructor. Performs initial per-thread initialization and loops waiting for new thread functions @@ -68,7 +68,10 @@ cygthread::stub (VOID *arg) #endif SetEvent (info->ev); info->__name = NULL; - SuspendThread (info->h); + if (initialized < 0) + ExitThread (0); + else + SuspendThread (info->h); } } @@ -78,9 +81,14 @@ DWORD WINAPI cygthread::runner (VOID *arg) { for (unsigned i = 0; i < NTHREADS; i++) - threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, &threads[i], - CREATE_SUSPENDED, &threads[i].avail); - cygthread::initialized = true; + if (!initialized) + threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, + &threads[i], CREATE_SUSPENDED, + &threads[i].avail); + else + return 0; + + initialized ^= 1; return 0; } @@ -127,7 +135,10 @@ new (size_t) for (;;) { - bool was_initialized = initialized; + int was_initialized = initialized; + if (was_initialized < 0) + ExitThread (0); + /* Search the threads array for an empty slot to use */ for (info = threads + NTHREADS - 1; info >= threads; info--) if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) @@ -140,6 +151,9 @@ new (size_t) return info; } + if (was_initialized < 0) + ExitThread (0); + if (!was_initialized) Sleep (0); /* thread_runner is not finished yet. */ else @@ -259,3 +273,12 @@ cygthread::detach () } } } + +void +cygthread::terminate () +{ + initialized = -1; + for (cygthread *info = threads + NTHREADS - 1; info >= threads; info--) + if (!(DWORD) InterlockedExchange ((LPLONG) &info->avail, 0) && info->id) + SetEvent (info->ev); +} diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index 37f7c6537..b55aec90c 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -17,7 +17,7 @@ class cygthread VOID *arg; bool is_freerange; static DWORD main_thread_id; - static bool initialized; + static int initialized; static DWORD WINAPI runner (VOID *); static DWORD WINAPI free_runner (VOID *); static DWORD WINAPI stub (VOID *); @@ -33,6 +33,7 @@ class cygthread void * operator new (size_t); static void * freerange (); void exit_thread (); + static void terminate (); }; #define cygself NULL diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 701fb140c..58fb823a0 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1024,6 +1024,7 @@ do_exit (int status) window_terminate (); events_terminate (); shared_terminate (); + cygthread::terminate (); minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n); myself->exit (n); diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 4be0bf14d..0ac429e14 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -159,8 +159,8 @@ class verifyable_object public: long magic; - verifyable_object (long); - ~verifyable_object (); + verifyable_object (long); + virtual ~verifyable_object (); }; typedef enum @@ -197,7 +197,7 @@ public: void *get () const; pthread_key (void (*)(void *)); - ~pthread_key (); + ~pthread_key (); static void fixup_before_fork(); static void fixup_after_fork(); @@ -225,23 +225,23 @@ template void List::Insert (ListNode *aNode) { if (!aNode) - return; + return; aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode); } template ListNode * List::Remove ( ListNode *aNode) { if (!aNode) - return NULL; + return NULL; if (!head) - return NULL; + return NULL; if (aNode == head) - return Pop (); + return Pop (); ListNode *resultPrev = head; while (resultPrev && resultPrev->next && !(aNode == resultPrev->next)) - resultPrev = resultPrev->next; + resultPrev = resultPrev->next; if (resultPrev) - return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next); + return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next); return NULL; } template ListNode * @@ -255,10 +255,10 @@ List::forEach (void (*callback)(ListNode *)) { ListNode *aNode = head; while (aNode) - { - callback (aNode); - aNode = aNode->next; - } + { + callback (aNode); + aNode = aNode->next; + } } class pthread_attr:public verifyable_object @@ -271,8 +271,8 @@ public: struct sched_param schedparam; size_t stacksize; - pthread_attr (); - ~pthread_attr (); + pthread_attr (); + ~pthread_attr (); }; class pthread_mutexattr:public verifyable_object @@ -281,8 +281,8 @@ public: static bool isGoodObject(pthread_mutexattr_t const *); int pshared; int mutextype; - pthread_mutexattr (); - ~pthread_mutexattr (); + pthread_mutexattr (); + ~pthread_mutexattr (); }; class pthread_mutex:public verifyable_object @@ -327,80 +327,80 @@ public: LONG *sigtodo; virtual void create (void *(*)(void *), pthread_attr *, void *); - pthread (); - virtual ~pthread (); + pthread (); + virtual ~pthread (); - static void initMainThread(pthread *, HANDLE); - static bool isGoodObject(pthread_t const *); - static void atforkprepare(); - static void atforkparent(); - static void atforkchild(); + static void initMainThread(pthread *, HANDLE); + static bool isGoodObject(pthread_t const *); + static void atforkprepare(); + static void atforkparent(); + static void atforkchild(); - /* API calls */ - static int cancel (pthread_t); - static int join (pthread_t * thread, void **return_val); - static int detach (pthread_t * thread); - static int create (pthread_t * thread, const pthread_attr_t * attr, + /* API calls */ + static int cancel (pthread_t); + static int join (pthread_t * thread, void **return_val); + static int detach (pthread_t * thread); + static int create (pthread_t * thread, const pthread_attr_t * attr, void *(*start_routine) (void *), void *arg); - static int once (pthread_once_t *, void (*)(void)); - static int atfork(void (*)(void), void (*)(void), void (*)(void)); - static int suspend (pthread_t * thread); - static int resume (pthread_t * thread); + static int once (pthread_once_t *, void (*)(void)); + static int atfork(void (*)(void), void (*)(void), void (*)(void)); + static int suspend (pthread_t * thread); + static int resume (pthread_t * thread); - virtual void exit (void *value_ptr); + virtual void exit (void *value_ptr); - virtual int cancel (); - - virtual void testcancel (); - static void static_cancel_self (); + virtual int cancel (); + + virtual void testcancel (); + static void static_cancel_self (); - virtual int setcancelstate (int state, int *oldstate); - virtual int setcanceltype (int type, int *oldtype); + virtual int setcancelstate (int state, int *oldstate); + virtual int setcanceltype (int type, int *oldtype); - virtual void push_cleanup_handler (__pthread_cleanup_handler *handler); - virtual 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 *); + static pthread* self (); + static void *thread_init_wrapper (void *); - virtual unsigned long getsequence_np(); + virtual unsigned long getsequence_np(); private: - DWORD thread_id; - __pthread_cleanup_handler *cleanup_stack; - pthread_mutex mutex; + DWORD thread_id; + __pthread_cleanup_handler *cleanup_stack; + pthread_mutex mutex; - void pop_all_cleanup_handlers (void); - void precreate (pthread_attr *); - void postcreate (); - void setThreadIdtoCurrent(); - static void setTlsSelfPointer(pthread *); - void cancel_self (); - DWORD getThreadId (); + 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(); + 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(); + /* 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; + pthreadNull (); + static pthreadNull _instance; }; class pthread_condattr:public verifyable_object @@ -432,8 +432,8 @@ public: void Signal (); void fixup_after_fork (); - pthread_cond (pthread_condattr *); - ~pthread_cond (); + pthread_cond (pthread_condattr *); + ~pthread_cond (); }; class pthread_once @@ -464,8 +464,8 @@ public: int TryWait (); void fixup_after_fork (); - semaphore (int, unsigned int); - ~semaphore (); + semaphore (int, unsigned int); + ~semaphore (); }; class callback @@ -505,11 +505,11 @@ public: void fixup_after_fork (void); MTinterface ():reent_index (0), indexallocated (0), threadcount (1) - { - pthread_prepare = NULL; - pthread_child = NULL; - pthread_parent = NULL; - } + { + pthread_prepare = NULL; + pthread_child = NULL; + pthread_parent = NULL; + } }; extern "C"