* 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.
This commit is contained in:
Christopher Faylor 2002-09-29 02:19:35 +00:00
parent fc5dae1cca
commit aea1f301fc
5 changed files with 123 additions and 87 deletions

View File

@ -1,3 +1,14 @@
2002-09-28 Christopher Faylor <cgf@redhat.com>
* 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 <rbtcollins@hotmail.com> 2002-09-27 Robert Collins <rbtcollins@hotmail.com>
* thread.cc (pthread_key::run_destructor): Run_destructor is not * thread.cc (pthread_key::run_destructor): Run_destructor is not

View File

@ -19,7 +19,7 @@ static cygthread NO_COPY threads[6];
#define NTHREADS (sizeof (threads) / sizeof (threads[0])) #define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id; 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 /* Initial stub called by cygthread constructor. Performs initial
per-thread initialization and loops waiting for new thread functions per-thread initialization and loops waiting for new thread functions
@ -68,7 +68,10 @@ cygthread::stub (VOID *arg)
#endif #endif
SetEvent (info->ev); SetEvent (info->ev);
info->__name = NULL; 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) cygthread::runner (VOID *arg)
{ {
for (unsigned i = 0; i < NTHREADS; i++) for (unsigned i = 0; i < NTHREADS; i++)
threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, &threads[i], if (!initialized)
CREATE_SUSPENDED, &threads[i].avail); threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub,
cygthread::initialized = true; &threads[i], CREATE_SUSPENDED,
&threads[i].avail);
else
return 0;
initialized ^= 1;
return 0; return 0;
} }
@ -127,7 +135,10 @@ new (size_t)
for (;;) 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 */ /* Search the threads array for an empty slot to use */
for (info = threads + NTHREADS - 1; info >= threads; info--) for (info = threads + NTHREADS - 1; info >= threads; info--)
if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0)))
@ -140,6 +151,9 @@ new (size_t)
return info; return info;
} }
if (was_initialized < 0)
ExitThread (0);
if (!was_initialized) if (!was_initialized)
Sleep (0); /* thread_runner is not finished yet. */ Sleep (0); /* thread_runner is not finished yet. */
else 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);
}

View File

@ -17,7 +17,7 @@ class cygthread
VOID *arg; VOID *arg;
bool is_freerange; bool is_freerange;
static DWORD main_thread_id; static DWORD main_thread_id;
static bool initialized; static int initialized;
static DWORD WINAPI runner (VOID *); static DWORD WINAPI runner (VOID *);
static DWORD WINAPI free_runner (VOID *); static DWORD WINAPI free_runner (VOID *);
static DWORD WINAPI stub (VOID *); static DWORD WINAPI stub (VOID *);
@ -33,6 +33,7 @@ class cygthread
void * operator new (size_t); void * operator new (size_t);
static void * freerange (); static void * freerange ();
void exit_thread (); void exit_thread ();
static void terminate ();
}; };
#define cygself NULL #define cygself NULL

View File

@ -1024,6 +1024,7 @@ do_exit (int status)
window_terminate (); window_terminate ();
events_terminate (); events_terminate ();
shared_terminate (); shared_terminate ();
cygthread::terminate ();
minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n); minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
myself->exit (n); myself->exit (n);

View File

@ -159,8 +159,8 @@ class verifyable_object
public: public:
long magic; long magic;
verifyable_object (long); verifyable_object (long);
~verifyable_object (); virtual ~verifyable_object ();
}; };
typedef enum typedef enum
@ -197,7 +197,7 @@ public:
void *get () const; void *get () const;
pthread_key (void (*)(void *)); pthread_key (void (*)(void *));
~pthread_key (); ~pthread_key ();
static void fixup_before_fork(); static void fixup_before_fork();
static void fixup_after_fork(); static void fixup_after_fork();
@ -225,23 +225,23 @@ template <class ListNode> void
List<ListNode>::Insert (ListNode *aNode) List<ListNode>::Insert (ListNode *aNode)
{ {
if (!aNode) if (!aNode)
return; return;
aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode); aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode);
} }
template <class ListNode> ListNode * template <class ListNode> ListNode *
List<ListNode>::Remove ( ListNode *aNode) List<ListNode>::Remove ( ListNode *aNode)
{ {
if (!aNode) if (!aNode)
return NULL; return NULL;
if (!head) if (!head)
return NULL; return NULL;
if (aNode == head) if (aNode == head)
return Pop (); return Pop ();
ListNode *resultPrev = head; ListNode *resultPrev = head;
while (resultPrev && resultPrev->next && !(aNode == resultPrev->next)) while (resultPrev && resultPrev->next && !(aNode == resultPrev->next))
resultPrev = resultPrev->next; resultPrev = resultPrev->next;
if (resultPrev) if (resultPrev)
return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next); return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next);
return NULL; return NULL;
} }
template <class ListNode> ListNode * template <class ListNode> ListNode *
@ -255,10 +255,10 @@ List<ListNode>::forEach (void (*callback)(ListNode *))
{ {
ListNode *aNode = head; ListNode *aNode = head;
while (aNode) while (aNode)
{ {
callback (aNode); callback (aNode);
aNode = aNode->next; aNode = aNode->next;
} }
} }
class pthread_attr:public verifyable_object class pthread_attr:public verifyable_object
@ -271,8 +271,8 @@ public:
struct sched_param schedparam; struct sched_param schedparam;
size_t stacksize; size_t stacksize;
pthread_attr (); pthread_attr ();
~pthread_attr (); ~pthread_attr ();
}; };
class pthread_mutexattr:public verifyable_object class pthread_mutexattr:public verifyable_object
@ -281,8 +281,8 @@ public:
static bool isGoodObject(pthread_mutexattr_t const *); static bool isGoodObject(pthread_mutexattr_t const *);
int pshared; int pshared;
int mutextype; int mutextype;
pthread_mutexattr (); pthread_mutexattr ();
~pthread_mutexattr (); ~pthread_mutexattr ();
}; };
class pthread_mutex:public verifyable_object class pthread_mutex:public verifyable_object
@ -327,80 +327,80 @@ public:
LONG *sigtodo; LONG *sigtodo;
virtual void create (void *(*)(void *), pthread_attr *, void *); virtual void create (void *(*)(void *), pthread_attr *, void *);
pthread (); pthread ();
virtual ~pthread (); virtual ~pthread ();
static void initMainThread(pthread *, HANDLE); static void initMainThread(pthread *, HANDLE);
static bool isGoodObject(pthread_t const *); static bool isGoodObject(pthread_t const *);
static void atforkprepare(); static void atforkprepare();
static void atforkparent(); static void atforkparent();
static void atforkchild(); static void atforkchild();
/* API calls */ /* API calls */
static int cancel (pthread_t); static int cancel (pthread_t);
static int join (pthread_t * thread, void **return_val); static int join (pthread_t * thread, void **return_val);
static int detach (pthread_t * thread); static int detach (pthread_t * thread);
static int create (pthread_t * thread, const pthread_attr_t * attr, static int create (pthread_t * thread, const pthread_attr_t * attr,
void *(*start_routine) (void *), void *arg); void *(*start_routine) (void *), void *arg);
static int once (pthread_once_t *, void (*)(void)); static int once (pthread_once_t *, void (*)(void));
static int atfork(void (*)(void), void (*)(void), void (*)(void)); static int atfork(void (*)(void), void (*)(void), void (*)(void));
static int suspend (pthread_t * thread); static int suspend (pthread_t * thread);
static int resume (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 int cancel ();
virtual void testcancel (); virtual void testcancel ();
static void static_cancel_self (); static void static_cancel_self ();
virtual int setcancelstate (int state, int *oldstate); virtual int setcancelstate (int state, int *oldstate);
virtual int setcanceltype (int type, int *oldtype); virtual int setcanceltype (int type, int *oldtype);
virtual void push_cleanup_handler (__pthread_cleanup_handler *handler); virtual void push_cleanup_handler (__pthread_cleanup_handler *handler);
virtual void pop_cleanup_handler (int const execute); virtual void pop_cleanup_handler (int const execute);
static pthread* self (); static pthread* self ();
static void *thread_init_wrapper (void *); static void *thread_init_wrapper (void *);
virtual unsigned long getsequence_np(); virtual unsigned long getsequence_np();
private: private:
DWORD thread_id; DWORD thread_id;
__pthread_cleanup_handler *cleanup_stack; __pthread_cleanup_handler *cleanup_stack;
pthread_mutex mutex; pthread_mutex mutex;
void pop_all_cleanup_handlers (void); void pop_all_cleanup_handlers (void);
void precreate (pthread_attr *); void precreate (pthread_attr *);
void postcreate (); void postcreate ();
void setThreadIdtoCurrent(); void setThreadIdtoCurrent();
static void setTlsSelfPointer(pthread *); static void setTlsSelfPointer(pthread *);
void cancel_self (); void cancel_self ();
DWORD getThreadId (); DWORD getThreadId ();
}; };
class pthreadNull : public pthread class pthreadNull : public pthread
{ {
public: public:
static pthread *getNullpthread(); static pthread *getNullpthread();
~pthreadNull(); ~pthreadNull();
/* From pthread These should never get called /* From pthread These should never get called
* as the ojbect is not verifyable * as the ojbect is not verifyable
*/ */
void create (void *(*)(void *), pthread_attr *, void *); void create (void *(*)(void *), pthread_attr *, void *);
void exit (void *value_ptr); void exit (void *value_ptr);
int cancel (); int cancel ();
void testcancel (); void testcancel ();
int setcancelstate (int state, int *oldstate); int setcancelstate (int state, int *oldstate);
int setcanceltype (int type, int *oldtype); int setcanceltype (int type, int *oldtype);
void push_cleanup_handler (__pthread_cleanup_handler *handler); void push_cleanup_handler (__pthread_cleanup_handler *handler);
void pop_cleanup_handler (int const execute); void pop_cleanup_handler (int const execute);
unsigned long getsequence_np(); unsigned long getsequence_np();
private: private:
pthreadNull (); pthreadNull ();
static pthreadNull _instance; static pthreadNull _instance;
}; };
class pthread_condattr:public verifyable_object class pthread_condattr:public verifyable_object
@ -432,8 +432,8 @@ public:
void Signal (); void Signal ();
void fixup_after_fork (); void fixup_after_fork ();
pthread_cond (pthread_condattr *); pthread_cond (pthread_condattr *);
~pthread_cond (); ~pthread_cond ();
}; };
class pthread_once class pthread_once
@ -464,8 +464,8 @@ public:
int TryWait (); int TryWait ();
void fixup_after_fork (); void fixup_after_fork ();
semaphore (int, unsigned int); semaphore (int, unsigned int);
~semaphore (); ~semaphore ();
}; };
class callback class callback
@ -505,11 +505,11 @@ public:
void fixup_after_fork (void); void fixup_after_fork (void);
MTinterface ():reent_index (0), indexallocated (0), threadcount (1) MTinterface ():reent_index (0), indexallocated (0), threadcount (1)
{ {
pthread_prepare = NULL; pthread_prepare = NULL;
pthread_child = NULL; pthread_child = NULL;
pthread_parent = NULL; pthread_parent = NULL;
} }
}; };
extern "C" extern "C"