+2002-04-18 Thomas Pfaff <tpfaff@gmx.net>
+
+ * thread.h (pthread::joiner): New member.
+ * thread.cc (pthread::pthread): Initialize joiner to NULL
+ (pthread::create): Increment of thread counter moved from
+ __pthread_create to this location.
+ (__pthread_create): Increment thread counter removed.
+ (thread_init_wrapper): Set joiner to self when thread was created
+ detached.
+ (__pthread_exit): delete thread when it is detached and not
+ joined.
+ (__pthread_join): Check for deadlock and delete thread when it has
+ terminated.
+ (__pthread_detach): Set joiner to self when thread state
+ changed to detached.
+
2002-06-05 Corinna Vinschen <corinna@vinschen.de>
* grp.cc (read_etc_group): When emulating nonexisting group file on
}
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
-cancelstate (0), canceltype (0)
+cancelstate (0), canceltype (0), joiner(NULL)
{
}
magic = 0;
else
{
+ InterlockedIncrement (&MT_INTERFACE->threadcount);
/*FIXME: set the priority appropriately for system contention scope */
if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
{
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
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();
+
#ifdef _CYG_THREAD_FAILSAFE
if (_REENT == _impure_ptr)
system_printf ("local storage for thread isn't setup correctly");
*thread = NULL;
return EAGAIN;
}
- InterlockedIncrement (&MT_INTERFACE->threadcount);
return 0;
}
void
__pthread_exit (void *value_ptr)
{
- class pthread *thread = __pthread_self ();
+ pthread_t thread = __pthread_self ();
MT_INTERFACE->destructors.IterateNull ();
- thread->return_ptr = value_ptr;
+ // cleanup if thread is in detached state and not joined
+ if( __pthread_equal(&thread->joiner, &thread ) )
+ delete thread;
+ else
+ thread->return_ptr = value_ptr;
+
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
exit (0);
else
int
__pthread_join (pthread_t *thread, void **return_val)
{
+ 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)
return ESRCH;
if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
{
if (return_val)
- *return_val = NULL;
+ *return_val = NULL;
return EINVAL;
}
+
+ else if( __pthread_equal(thread, &joiner ) )
+ {
+ if (return_val)
+ *return_val = NULL;
+ return EDEADLK;
+ }
+
else
{
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
+ (*thread)->joiner = joiner;
WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);
if (return_val)
- *return_val = (*thread)->return_ptr;
+ *return_val = (*thread)->return_ptr;
+ // cleanup
+ delete (*thread);
} /*End if */
pthread_testcancel ();
if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
{
- (*thread)->return_ptr = NULL;
return EINVAL;
}
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
+ // force cleanup on exit
+ (*thread)->joiner = *thread;
+
return 0;
}