]> granicus.if.org Git - gc/commitdiff
2006-07-30 Hans Boehm <Hans.Boehm@hp.com>
authorhboehm <hboehm>
Sun, 30 Jul 2006 18:13:41 +0000 (18:13 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:38 +0000 (21:06 +0400)
* win32_threads.c, include/private/gc_locks.h: Fic GC_allocate_ml
declaration.
* win32_threads.c: Various fixes and cleanups.

include/private/gc_locks.h
win32_threads.c

index 4235c701d7720ef933dafea0a3cc2e04b1da5641..9a17c7535778cb0f88ebc05debb0270c03511946 100644 (file)
 #    include <windows.h>
 #    define NO_THREAD (DWORD)(-1)
      extern DWORD GC_lock_holder;
-#    if defined(GC_DLL)
-       __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
-#    else
-       CRITICAL_SECTION GC_allocate_ml;
-#    endif
+     GC_API CRITICAL_SECTION GC_allocate_ml;
 #    ifdef GC_ASSERTIONS
 #        define UNCOND_LOCK() \
                { EnterCriticalSection(&GC_allocate_ml); \
index 13b14e162e93982073e1d68166bb2ac4a147ce57..4fbfca512fa7466df43fae27ca398a9d214da56b 100644 (file)
 
 /* Allocation lock declarations.       */
 #if !defined(USE_PTHREAD_LOCKS)
-  /* GC_allocate_ml declaration in gc_locks.h suffices.        */
+# if defined(GC_DLL)
+    __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
+# else
+    CRITICAL_SECTION GC_allocate_ml;
+# endif
   DWORD GC_lock_holder = NO_THREAD;
        /* Thread id for current holder of allocation lock */
 #else
@@ -41,6 +45,7 @@
 # undef ExitThread
 # undef _beginthreadex
 # undef _endthreadex
+# include <process.h>  /* For _beginthreadex, _endthreadex */
 
 #endif
 
@@ -153,7 +158,7 @@ struct GC_Thread_Rep {
 };
 
 typedef struct GC_Thread_Rep * GC_thread;
-
+typedef volatile struct GC_Thread_Rep * GC_vthread;
 
 /*
  * We assumed that volatile ==> memory ordering, at least among
@@ -189,7 +194,7 @@ static GC_bool client_has_run = FALSE;
 /* This is a chained hash table, with much of the code borrowed        */
 /* From the Posix implementation.                              */
 # define THREAD_TABLE_SZ 256   /* Must be power of 2   */
-  volatile GC_thread GC_threads[THREAD_TABLE_SZ];
+  GC_thread GC_threads[THREAD_TABLE_SZ];
   
 
 /* Add a thread to GC_threads.  We assume it wasn't already there.     */
@@ -211,18 +216,28 @@ GC_thread GC_new_thread(DWORD id)
         GC_ASSERT(!GC_win32_dll_threads);
         result = (struct GC_Thread_Rep *)
                 GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
-       GC_ASSERT(result -> flags == 0);
+#       ifdef CYGWIN32
+         GC_ASSERT(result -> flags == 0);
+#       endif
     }
     if (result == 0) return(0);
     /* result -> id = id; Done by caller.      */
     result -> next = GC_threads[hv];
     GC_threads[hv] = result;
-    GC_ASSERT(result -> flags == 0 /* && result -> thread_blocked == 0 */);
+#   ifdef CYGWIN32
+      GC_ASSERT(result -> flags == 0 /* && result -> thread_blocked == 0 */);
+#   endif
     return(result);
 }
 
 extern LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
 
+#if defined(GWW_VDB) && defined(MPROTECT_VDB)
+  extern GC_bool GC_gww_dirty_init(void);
+  /* Defined in os_dep.c.  Returns TRUE if GetWriteWatch is available.         */
+  /* may be called repeatedly.                                         */
+#endif
+
 /*
  * This may be called from DllMain, and hence operates under unusual
  * constraints.  In particular, it must be lock-free if GC_win32_dll_threads
@@ -233,13 +248,18 @@ extern LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
 static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
                                             DWORD thread_id)
 {
-  volatile struct GC_Thread_Rep * me;
+  GC_vthread me;
 
   /* The following should be a noop according to the win32     */
   /* documentation.  There is empirical evidence that it       */
   /* isn't.            - HB                                    */
 # if defined(MPROTECT_VDB)
-   if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
+#   if defined(GWW_VDB)
+      if (GC_incremental && !GC_gww_dirty_init())
+       SetUnhandledExceptionFilter(GC_write_fault_handler);
+#   else
+      if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
+#   endif
 # endif
 
   if (GC_win32_dll_threads || !client_has_run) {
@@ -395,14 +415,14 @@ static GC_thread GC_lookup_thread(DWORD thread_id)
 /* GC_win32_dll_threads is set.                                        */
 /* If GC_win32_dll_threads is set it should be called from the */
 /* thread being deleted.                                       */
-void GC_delete_gc_thread(GC_thread gc_id)
+void GC_delete_gc_thread(GC_vthread gc_id)
 {
   if (GC_win32_dll_threads) {
     /* This is intended to be lock-free.                               */
     /* It is either called synchronously from the thread being deleted,        */
     /* or by the joining thread.                                       */
+    /* In this branch asynchronosu changes to *gc_id are possible.     */
     CloseHandle(gc_id->handle);
-      /* cast away volatile qualifier */
     gc_id -> stack_base = 0;
     gc_id -> id = 0;
 #   ifdef CYGWIN32
@@ -410,13 +430,15 @@ void GC_delete_gc_thread(GC_thread gc_id)
 #   endif /* CYGWIN32 */
     AO_store_release(&(gc_id->in_use), FALSE);
   } else {
-    DWORD id = gc_id -> id;
+    /* Cast away volatile qualifier, since we have lock. */
+    GC_thread gc_nvid = (GC_thread)gc_id;
+    DWORD id = gc_nvid -> id;
     int hv = ((word)id) % THREAD_TABLE_SZ;
     register GC_thread p = GC_threads[hv];
     register GC_thread prev = 0;
 
     GC_ASSERT(I_HOLD_LOCK());
-    while (p != gc_id) {
+    while (p != gc_nvid) {
         prev = p;
         p = p -> next;
     }
@@ -480,22 +502,24 @@ int GC_register_my_thread(struct GC_stack_base *sb) {
 
 int GC_unregister_my_thread(void)
 {
-    if (GC_win32_dll_threads) {
-      /* Should we just ignore this? */
-      GC_delete_thread(GetCurrentThreadId());
-    } else {
-      LOCK();
-      GC_delete_thread(GetCurrentThreadId());
-      UNLOCK();
-    }
+    DWORD t = GetCurrentThreadId();
+
 #   if defined(THREAD_LOCAL_ALLOC)
       LOCK();
       {
-       GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId());
+       GC_thread me = GC_lookup_thread_inner(t);
         GC_destroy_thread_local(&(me->tlfs));
       }
       UNLOCK();
 #   endif
+    if (GC_win32_dll_threads) {
+      /* Should we just ignore this? */
+      GC_delete_thread(t);
+    } else {
+      LOCK();
+      GC_delete_thread(t);
+      UNLOCK();
+    }
     return GC_SUCCESS;
 }
 
@@ -640,7 +664,7 @@ void GC_stop_world(void)
     /* in the thread registration code until GC_please_stop becomes    */
     /* false.  This is not ideal, but hopefully correct.               */
     for (i = 0; i <= GC_get_max_thread_index(); i++) {
-      volatile struct GC_Thread_Rep * t = dll_thread_table + i;
+      GC_vthread t = dll_thread_table + i;
       if (t -> stack_base != 0
          && t -> id != thread_id) {
          GC_suspend((GC_thread)t);
@@ -887,13 +911,8 @@ void * GC_win32_start_inner(struct GC_stack_base *sb, LPVOID arg)
 #ifndef __GNUC__
     } __finally {
 #endif /* __GNUC__ */
-#       if defined(THREAD_LOCAL_ALLOC)
-          LOCK();
-          GC_destroy_thread_local(&(me->tlfs));
-          UNLOCK();
-#       endif
+       GC_unregister_my_thread();
        GC_free(args);
-       GC_delete_thread(GetCurrentThreadId());
 #ifndef __GNUC__
     }
 #endif /* __GNUC__ */