diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 613799b23..417839378 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,42 @@ +2002-06-10 Robert Collins + + * cygwin.din: Add _pthread_cleanup_push and _pthread_cleanup_pop. + * pthread.cc: Change __pthread_self to pthread::self() thruoghout. + (_pthread_cleanup_push): New function. + (_pthread_cleanup_pop): Ditto. + * thread.cc: Thanks to Thomas Pfaff for the pthread cleanup_push,_pop + patch, this work is derived from that. + Change __pthread_self to pthread::self() thruoghout. + (__pthread_self): Rename to pthread::self. + (pthread::self): New method. + (pthread::pthread): Initialize new member. + (pthread::push_cleanup_handler): New method. + (pthread::pop_cleanup_handler): New method. + (pthread::pop_all_cleanup_handlers): New method. + (__pthread_exit): Pop all cleanup handlers. + * thread.h (pthread::push_cleanup_handler): Declare. + (pthread::pop_cleanup_handler): Ditto. + (pthread::pop_all_cleanup_handlers): Ditto. + (pthread::self): New static method. + (__pthread_exit): Give C++ linkage. + (__pthread_join): Ditto. + (__pthread_detach): Ditto. + (__pthread_self): Remove. + +2002-04-24 Thomas Pfaff + + * include/pthread.h (__pthread_cleanup_handler): New structure + (pthread_cleanup_push): Rewritten . + (pthread_cleanup_pop): Ditto. + (_pthread_cleanup_push): New prototype. + (_pthread_cleanup_pop) Ditto. + +2002-04-24 Thomas Pfaff + + * thread.cc (thread_init_wrapper): Check if thread is already joined. + (__pthread_join): Set joiner first. + (__pthread_detach): Ditto. + 2002-06-10 Robert Collins * cygserver_transport.cc (create_server_transport): Finish the split diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 9bbfa5f4e..c687f7223 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -1186,6 +1186,8 @@ pthread_attr_setschedpolicy pthread_attr_setscope pthread_attr_setstacksize pthread_cancel +_pthread_cleanup_push +_pthread_cleanup_pop pthread_cond_broadcast pthread_cond_destroy pthread_cond_init diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index 102ba650c..acdde4fc3 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -103,10 +103,20 @@ void pthread_cleanup_push (void (*routine)(void*), void *arg); void pthread_cleanup_pop (int execute); */ typedef void (*__cleanup_routine_type) (void *); +typedef struct _pthread_cleanup_handler +{ + __cleanup_routine_type function; + void *arg; + struct _pthread_cleanup_handler *next; +} __pthread_cleanup_handler; -#define pthread_cleanup_push(fn, arg) { __cleanup_routine_type __cleanup_routine=fn; \ -void *__cleanup_param=arg; -#define pthread_cleanup_pop(execute) if (execute) __cleanup_routine(__cleanup_param); } +void _pthread_cleanup_push (__pthread_cleanup_handler *handler); +void _pthread_cleanup_pop (int execute); + +#define pthread_cleanup_push(_fn, _arg) { __pthread_cleanup_handler __cleanup_handler = \ + { _fn, _arg, NULL }; \ + _pthread_cleanup_push( &__cleanup_handler ); +#define pthread_cleanup_pop(_execute) _pthread_cleanup_pop( _execute ); } /* Condition variables */ int pthread_cond_broadcast (pthread_cond_t *); diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc index 7d8ca1ae6..ab7fd1fbe 100644 --- a/winsup/cygwin/pthread.cc +++ b/winsup/cygwin/pthread.cc @@ -218,7 +218,7 @@ pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) pthread_t pthread_self () { - return __pthread_self (); + return pthread::self(); } int @@ -425,8 +425,6 @@ pthread_cancel (pthread_t thread) return __pthread_cancel (thread); } - - int pthread_setcancelstate (int state, int *oldstate) { @@ -445,6 +443,18 @@ pthread_testcancel (void) __pthread_testcancel (); } +void +_pthread_cleanup_push (__pthread_cleanup_handler *handler) +{ + pthread::self()->push_cleanup_handler(handler); +} + +void +_pthread_cleanup_pop (int execute) +{ + pthread::self()->pop_cleanup_handler (execute); +} + /* Semaphores */ int sem_init (sem_t * sem, int pshared, unsigned int value) diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 5428d674d..dbcfc5a9e 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -343,8 +343,19 @@ MTinterface::fixup_after_fork (void) } } +/* pthread calls */ + +/* static methods */ + +pthread * +pthread::self () +{ + return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); +} + +/* member methods */ pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0), -cancelstate (0), canceltype (0), joiner(NULL) +cancelstate (0), canceltype (0), joiner (NULL), cleanup_handlers(NULL) { } @@ -392,6 +403,41 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, } } +void +pthread::push_cleanup_handler (__pthread_cleanup_handler *handler) +{ + if (this != self ()) + // TODO: do it? + api_fatal ("Attempt to push a cleanup handler across threads"); + handler->next = cleanup_handlers; + cleanup_handlers = handler; +} + +void +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"); + + if (cleanup_handlers != NULL ) + { + __pthread_cleanup_handler *handler = cleanup_handlers; + + if (execute) + (*handler->function) (handler->arg); + + cleanup_handlers = handler->next; + } +} + +void +pthread::pop_all_cleanup_handlers () +{ + while (cleanup_handlers != NULL) + pop_cleanup_handler (1); +} + pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS), inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0) @@ -910,8 +956,8 @@ thread_init_wrapper (void *_arg) TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); // if thread is detached force cleanup on exit - if (thread->attr.joinable == PTHREAD_CREATE_DETACHED) - thread->joiner = __pthread_self(); + if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL) + thread->joiner = pthread::self (); #ifdef _CYG_THREAD_FAILSAFE if (_REENT == _impure_ptr) @@ -1191,7 +1237,7 @@ opengroup specs. int __pthread_setcancelstate (int state, int *oldstate) { - class pthread *thread = __pthread_self (); + class pthread *thread = pthread::self (); if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE) return EINVAL; *oldstate = thread->cancelstate; @@ -1202,7 +1248,7 @@ __pthread_setcancelstate (int state, int *oldstate) int __pthread_setcanceltype (int type, int *oldtype) { - class pthread *thread = __pthread_self (); + class pthread *thread = pthread::self (); if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS) return EINVAL; *oldtype = thread->canceltype; @@ -1214,7 +1260,7 @@ __pthread_setcanceltype (int type, int *oldtype) void __pthread_testcancel (void) { - class pthread *thread = __pthread_self (); + class pthread *thread = pthread::self (); if (thread->cancelstate == PTHREAD_CANCEL_DISABLE) return; /*check the cancellation event object here - not neededuntil pthread_cancel actually @@ -1495,7 +1541,10 @@ __pthread_attr_destroy (pthread_attr_t *attr) void __pthread_exit (void *value_ptr) { - pthread_t thread = __pthread_self (); + pthread * thread = pthread::self (); + + // run cleanup handlers + thread->pop_all_cleanup_handlers(); MT_INTERFACE->destructors.IterateNull (); @@ -1514,7 +1563,7 @@ __pthread_exit (void *value_ptr) int __pthread_join (pthread_t *thread, void **return_val) { - pthread_t joiner = __pthread_self(); + pthread_t joiner = pthread::self (); /*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/ if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) @@ -1536,8 +1585,8 @@ __pthread_join (pthread_t *thread, void **return_val) else { - (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->joiner = joiner; + (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; WaitForSingleObject ((*thread)->win32_obj_id, INFINITE); if (return_val) *return_val = (*thread)->return_ptr; @@ -1561,9 +1610,9 @@ __pthread_detach (pthread_t *thread) return EINVAL; } - (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; // force cleanup on exit (*thread)->joiner = *thread; + (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; return 0; } @@ -1925,7 +1974,7 @@ __pthread_kill (pthread_t thread, int sig) int __pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set) { - pthread *thread = __pthread_self (); + pthread *thread = pthread::self (); // lock this myself, for the use of thread2signal // two differt kills might clash: FIXME @@ -1941,11 +1990,6 @@ __pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set) } /* ID */ -pthread_t -__pthread_self () -{ - return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); -} int __pthread_equal (pthread_t *t1, pthread_t *t2) diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index b71c3a31b..25f20b482 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -260,8 +260,17 @@ public: pthread (); ~pthread (); + void push_cleanup_handler (__pthread_cleanup_handler *handler); + void pop_cleanup_handler (int const execute); + + static pthread* self (); + private: DWORD thread_id; + __pthread_cleanup_handler *cleanup_handlers; + + friend void __pthread_exit (void *value_ptr); + void pop_all_cleanup_handlers (void); }; class pthread_mutexattr:public verifyable_object @@ -394,6 +403,11 @@ void __pthread_atforkprepare(void); void __pthread_atforkparent(void); void __pthread_atforkchild(void); +/* Thread Exit */ +void __pthread_exit (void *value_ptr); +int __pthread_join (pthread_t * thread, void **return_val); +int __pthread_detach (pthread_t * thread); + extern "C" { void *thread_init_wrapper (void *); @@ -424,15 +438,7 @@ int __pthread_attr_setschedpolicy (pthread_attr_t *, int); int __pthread_attr_setscope (pthread_attr_t *, int); int __pthread_attr_setstackaddr (pthread_attr_t *, void *); - - -/* Thread Exit */ -void __pthread_exit (void *value_ptr); -int __pthread_join (pthread_t * thread, void **return_val); -int __pthread_detach (pthread_t * thread); - /* Thread suspend */ - int __pthread_suspend (pthread_t * thread); int __pthread_continue (pthread_t * thread); @@ -462,10 +468,8 @@ int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set); /* ID */ -pthread_t __pthread_self (); int __pthread_equal (pthread_t * t1, pthread_t * t2); - /* Mutexes */ int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); int __pthread_mutex_lock (pthread_mutex_t *); @@ -504,7 +508,6 @@ int __pthread_setcancelstate (int state, int *oldstate); int __pthread_setcanceltype (int type, int *oldtype); void __pthread_testcancel (void); - /* Semaphores */ int __sem_init (sem_t * sem, int pshared, unsigned int value); int __sem_destroy (sem_t * sem);