Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / libgc / pthread_support.c
index 4b3d825fbc7b4e4f9d4a1f0a37d995385a0199bf..ccafb3b1169e96fa6847a794ea4b01d1421ba8b1 100644 (file)
     --> Macro replaced by USE_COMPILER_TLS
 # endif
 
+#ifndef USE_COMPILER_TLS
 # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
       defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \
       defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \
+      defined(GC_FREEBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \
       defined(GC_OPENBSD_THREADS)
 #   define USE_PTHREAD_SPECIFIC
 # endif
+#endif
 
 # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
 #   define _POSIX4A_DRAFT10_SOURCE 1
@@ -182,6 +185,10 @@ static GC_bool parallel_initialized = FALSE;
 
 void GC_init_parallel();
 
+static pthread_t main_pthread_self;
+static void *main_stack, *main_altstack;
+static int main_stack_size, main_altstack_size;
+
 # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
 
 /* We don't really support thread-local allocation with DBG_HDRS_ALL */
@@ -848,6 +855,30 @@ int GC_thread_is_registered (void)
        return ptr ? 1 : 0;
 }
 
+void GC_register_altstack (void *stack, int stack_size, void *altstack, int altstack_size)
+{
+       GC_thread thread;
+
+       LOCK();
+       thread = (void *)GC_lookup_thread(pthread_self());
+       if (thread) {
+               thread->stack = stack;
+               thread->stack_size = stack_size;
+               thread->altstack = altstack;
+               thread->altstack_size = altstack_size;
+       } else {
+               /*
+                * This happens if we are called before GC_thr_init ().
+                */
+               main_pthread_self = pthread_self ();
+               main_stack = stack;
+               main_stack_size = stack_size;
+               main_altstack = altstack;
+               main_altstack_size = altstack_size;
+       }
+       UNLOCK();
+}
+
 #ifdef HANDLE_FORK
 /* Remove all entries from the GC_threads table, except the    */
 /* one for the current thread.  We need to do this in the child        */
@@ -1083,6 +1114,12 @@ void GC_thr_init()
          gc_thread_vtable->thread_created (pthread_self (), &t->stop_info.stack_ptr);
 #     endif
 #endif
+                if (pthread_self () == main_pthread_self) {
+                        t->stack = main_stack;
+                        t->stack_size = main_stack_size;
+                        t->altstack = main_altstack;
+                        t->altstack_size = main_altstack_size;
+                }
 
     GC_stop_init();