[Gc] win32_pthreads

Romano Paolo Tenca rotenca at telvia.it
Fri May 25 07:01:55 PDT 2007


I hope this is the last version of the patch.

My conclusion about dead lock with debug options is that under mingw 
GC_printf() hangs if another thread executing GC_printf() is suspended. 
So i introduced a new macro for debugging.stack push. I think it is not 
a bug, but a limit of mingw/win32_pthread combination.

I changed THREAD_EQUAL to make it more fast using documented internal 
details of pthread library.

I changed GC_pthread_join: win32 pthread id are unique, so no need to 
Sleep waiting starting thread.

Added some missing casts to debug code.

A note: tested with LOCAL_ALLOC gctest seems to work and time execution 
is about 25% less.

-- 
Ciao
Romano Paolo Tenca

-------------- next part --------------
Index: win32_threads.c
===================================================================
RCS file: /cvsroot/bdwgc/bdwgc/win32_threads.c,v
retrieving revision 1.10
diff -u -r1.10 win32_threads.c
--- win32_threads.c	24 May 2007 05:18:06 -0000	1.10
+++ win32_threads.c	25 May 2007 13:40:57 -0000
@@ -49,6 +49,13 @@
 
 # define DEBUG_CYGWIN_THREADS 0
 # define DEBUG_WIN32_PTHREADS 0
+# define DEBUG_WIN32_PTHREADS_STACK 0
+
+# if DEBUG_WIN32_PTHREADS_STACK
+    /* It seems that is not safe to call GC_printf() if any threads */
+    /* is suspended while executing GC_printf().                    */
+#   define DEBUG_WIN32_PTHREADS 0
+# endif  
 
   void * GC_pthread_start(void * arg);
   void GC_thread_exit_proc(void *arg);
@@ -729,6 +736,7 @@
       for (i = 0; i < THREAD_TABLE_SZ; i++) {
         for (t = GC_threads[i]; t != 0; t = t -> next) {
 	  if (t -> stack_base != 0
+	  && !(t -> flags & FINISHED)
 	  && t -> id != thread_id) {
 	    GC_suspend(t);
 	  }
@@ -857,7 +865,7 @@
 	  GC_printf("Pushing thread from %p to %p for %d from %d\n",
 		    sp, thread -> stack_base, thread -> id, me);
 #       endif
-#       if DEBUG_WIN32_PTHREADS
+#       if DEBUG_WIN32_PTHREADS_STACK
 	  GC_printf("Pushing thread from %p to %p for 0x%x from 0x%x\n",
 		    sp, thread -> stack_base, thread -> id, me);
 #       endif
@@ -895,7 +903,7 @@
     for (i = 0; i < THREAD_TABLE_SZ; i++) {
       for (t = GC_threads[i]; t != 0; t = t -> next) {
         ++nthreads;
-        GC_push_stack_for(t);
+        if (!(t -> flags & FINISHED)) GC_push_stack_for(t);
         if (t -> id == me) found_me = TRUE;
       }
     }
@@ -1167,7 +1175,7 @@
 #   endif
 #   if DEBUG_WIN32_PTHREADS
       GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",
-		(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
+		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
 #   endif
 
     if (!parallel_initialized) GC_init_parallel();
@@ -1176,10 +1184,17 @@
     /* FIXME: It would be better if this worked more like	 */
     /* pthread_support.c.					 */
 
-    while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10);
+    #ifndef GC_WIN32_PTHREADS
+      while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10);
+    #endif
 
     result = pthread_join(pthread_id, retval);
 
+    #ifdef GC_WIN32_PTHREADS
+      /* win32_pthreads id are unique */
+      joinee = GC_lookup_pthread(pthread_id);
+    #endif
+
     if (!GC_win32_dll_threads) {
       LOCK();
       GC_delete_gc_thread(joinee);
@@ -1192,7 +1207,7 @@
 #   endif
 #   if DEBUG_WIN32_PTHREADS
       GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
-		(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
+		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
 #   endif
 
     return result;
@@ -1234,7 +1249,7 @@
 #   endif
 #   if DEBUG_WIN32_PTHREADS
       GC_printf("About to create a thread from 0x%x(0x%x)\n",
-		(pthread_self()).p, GetCurrentThreadId());
+		(int)(pthread_self()).p, GetCurrentThreadId());
 #   endif
     GC_need_to_lock = TRUE;
     result = pthread_create(new_thread, attr, GC_pthread_start, si); 
@@ -1289,7 +1304,7 @@
     pthread_cleanup_push(GC_thread_exit_proc, (void *)me);
     result = (*start)(start_arg);
     me -> status = result;
-    pthread_cleanup_pop(0);
+    pthread_cleanup_pop(1);
 
 #   if DEBUG_CYGWIN_THREADS
       GC_printf("thread 0x%x(0x%x) returned from start routine.\n",
Index: include/private/gc_locks.h
===================================================================
RCS file: /cvsroot/bdwgc/bdwgc/include/private/gc_locks.h,v
retrieving revision 1.9
diff -u -r1.9 gc_locks.h
--- include/private/gc_locks.h	24 May 2007 05:18:07 -0000	1.9
+++ include/private/gc_locks.h	25 May 2007 13:14:58 -0000
@@ -89,7 +89,10 @@
 #    else
 #      if defined(GC_WIN32_PTHREADS)
 #	 define NUMERIC_THREAD_ID(id) ((unsigned long)(id.p))
-#	 define THREAD_EQUAL(id1, id2) pthread_equal(id1, id2)
+	 /* Using documented internal details of win32_pthread library. */
+	 /* More fast then pthread_equal(). Should not change with new  */
+	 /* future versions of win32_pthread library.                   */
+#	 define THREAD_EQUAL(id1, id2) ((id1.p == id2.p) && (id1.x == id2.x))
 #        undef NUMERIC_THREAD_ID_UNIQUE
 #      else
 	 /* Generic definitions that always work, but will result in	*/


More information about the Gc mailing list