* 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:
parent
fc5dae1cca
commit
aea1f301fc
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue