2011-05-17 Ivan Maidanski <ivmai@mail.ru>
+ * pthread_support.c (pthread_join): Add assertion (check thread is
+ finished).
+ * pthread_support.c (GC_register_my_thread): Don't detach the
+ thread if invoked from the thread destructor.
+ * win32_threads.c (GC_register_my_thread): Ditto.
+ * win32_threads.c (GC_unregister_my_thread): Don't delete the
+ thread (just set FINISHED) if the thread is not detached (only if
+ GC_PTHREADS); add assertion (check the thread is not finished).
+ * tests/threadkey_test.c (main): Join some created threads.
+
+2011-05-17 Ivan Maidanski <ivmai@mail.ru>
+
* pthread_support.c (GC_delete_gc_thread): Rename "gc_id" local
variable to "t".
* win32_threads.c (GC_delete_gc_thread): Ditto.
if (result == 0) {
LOCK();
/* Here the pthread thread id may have been recycled. */
+ GC_ASSERT((t -> flags & FINISHED) != 0);
GC_delete_gc_thread(t);
UNLOCK();
}
LOCK();
me = GC_lookup_thread(self);
- if (0 == me || (me -> flags & FINISHED) != 0) {
- if (me == 0) {
- me = GC_register_my_thread_inner(sb, self);
- } else {
- /* This code is executed when a thread is registered from the */
- /* client thread key destructor. */
- GC_record_stack_base(me, sb);
- me -> flags &= ~FINISHED;
-# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
- /* Since this could be executed from a thread destructor, */
- /* our signals might be blocked. */
- GC_unblock_gc_signals();
-# endif
- }
+ if (0 == me) {
+ me = GC_register_my_thread_inner(sb, self);
me -> flags |= DETACHED;
/* Treat as detached, since we do not need to worry about */
/* pointer results. */
# endif
UNLOCK();
return GC_SUCCESS;
+ } else if ((me -> flags & FINISHED) != 0) {
+ /* This code is executed when a thread is registered from the */
+ /* client thread key destructor. */
+ GC_record_stack_base(me, sb);
+ me -> flags &= ~FINISHED; /* but not DETACHED */
+# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ /* Since this could be executed from a thread destructor, */
+ /* our signals might be blocked. */
+ GC_unblock_gc_signals();
+# endif
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_init_thread_local(&(me->tlfs));
+# endif
+ UNLOCK();
+ return GC_SUCCESS;
} else {
UNLOCK();
return GC_DUPLICATE;
# endif
for (i = 0; i < LIMIT; i++) {
pthread_t t;
- GC_pthread_create (&t, NULL, entry, NULL);
+ void *res;
+ if (GC_pthread_create (&t, NULL, entry, NULL) == 0
+ && (i & 1) != 0)
+ GC_pthread_join (t, &res);
}
return 0;
}
# ifdef GC_PTHREADS
/* else */ if ((me -> flags & FINISHED) != 0) {
GC_record_stack_base(me, sb);
- me -> flags = (me -> flags & ~FINISHED) | DETACHED;
+ me -> flags &= ~FINISHED; /* but not DETACHED */
# ifdef THREAD_LOCAL_ALLOC
GC_init_thread_local((GC_tlfs)(&me->tlfs));
# endif
/* Can't happen: see GC_use_threads_discovery(). */
GC_ASSERT(FALSE);
# else
+# ifdef GC_PTHREADS
+ /* FIXME: If not DETACHED then just set FINISHED. */
+# endif
/* FIXME: Should we just ignore this? */
GC_delete_thread(GetCurrentThreadId());
# endif
} else {
+# if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS)
+ GC_thread me;
+# endif
DWORD thread_id = GetCurrentThreadId();
+
LOCK();
+# if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS)
+ me = GC_lookup_thread_inner(thread_id);
+ GC_ASSERT(!(me -> flags & FINISHED));
+# endif
# if defined(THREAD_LOCAL_ALLOC)
- {
- GC_thread me = GC_lookup_thread_inner(thread_id);
- GC_destroy_thread_local(&(me->tlfs));
- }
+ GC_destroy_thread_local(&(me->tlfs));
+# endif
+# ifdef GC_PTHREADS
+ if ((me -> flags & DETACHED) == 0) {
+ me -> flags |= FINISHED;
+ } else
# endif
- GC_delete_thread(thread_id);
+ /* else */ {
+ GC_delete_thread(thread_id);
+ }
UNLOCK();
}
return GC_SUCCESS;