Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / libgc / pthread_support.c
index ccafb3b1169e96fa6847a794ea4b01d1421ba8b1..097d588a7b55fd77569d2def2b9e80348068085c 100644 (file)
@@ -205,7 +205,7 @@ static
 GC_key_t GC_thread_key;
 
 #ifdef USE_COMPILER_TLS
-__thread MONO_TLS_FAST void* GC_thread_tls;
+__thread void* GC_thread_tls;
 
 /*
  * gcc errors out with /tmp/ccdPMFuq.s:2994: Error: symbol `.LTLS4' is already defined
@@ -222,10 +222,6 @@ static int GC_setspecific (GC_key_t key, void *value) {
 
 static GC_bool keys_initialized;
 
-#ifdef MONO_DEBUGGER_SUPPORTED
-#include "include/libgc-mono-debugger.h"
-#endif
-
 /* Recover the contents of the freelist array fl into the global one gfl.*/
 /* Note that the indexing scheme differs, in that gfl has finer size   */
 /* resolution, even if not all entries are used.                       */
@@ -298,17 +294,17 @@ void GC_init_thread_local(GC_thread p)
        ABORT("Failed to set thread specific allocation pointers");
     }
     for (i = 1; i < NFREELISTS; ++i) {
-       p -> ptrfree_freelists[i] = (ptr_t)1;
-       p -> normal_freelists[i] = (ptr_t)1;
+       p -> tlfs.ptrfree_freelists[i] = (ptr_t)1;
+       p -> tlfs.normal_freelists[i] = (ptr_t)1;
 #      ifdef GC_GCJ_SUPPORT
-         p -> gcj_freelists[i] = (ptr_t)1;
+         p -> tlfs.gcj_freelists[i] = (ptr_t)1;
 #      endif
     }   
     /* Set up the size 0 free lists.   */
-    p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object);
-    p -> normal_freelists[0] = (ptr_t)(&size_zero_object);
+    p -> tlfs.ptrfree_freelists[0] = (ptr_t)(&size_zero_object);
+    p -> tlfs.normal_freelists[0] = (ptr_t)(&size_zero_object);
 #   ifdef GC_GCJ_SUPPORT
-        p -> gcj_freelists[0] = (ptr_t)(-1);
+       p -> tlfs.gcj_freelists[0] = (ptr_t)(-1);
 #   endif
 }
 
@@ -324,10 +320,10 @@ void GC_destroy_thread_local(GC_thread p)
 #   ifndef HANDLE_FORK
       GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p);
 #   endif
-    return_freelists(p -> ptrfree_freelists, GC_aobjfreelist);
-    return_freelists(p -> normal_freelists, GC_objfreelist);
+    return_freelists(p -> tlfs.ptrfree_freelists, GC_aobjfreelist);
+    return_freelists(p -> tlfs.normal_freelists, GC_objfreelist);
 #   ifdef GC_GCJ_SUPPORT
-       return_freelists(p -> gcj_freelists, GC_gcjobjfreelist);
+       return_freelists(p -> tlfs.gcj_freelists, GC_gcjobjfreelist);
 #   endif
 }
 
@@ -361,7 +357,7 @@ GC_PTR GC_local_malloc(size_t bytes)
          GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self()));
          UNLOCK();
 #      endif
-       my_fl = ((GC_thread)tsd) -> normal_freelists + index;
+       my_fl = ((GC_thread)tsd) -> tlfs.normal_freelists + index;
        my_entry = *my_fl;
        if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
            ptr_t next = obj_link(my_entry);
@@ -388,7 +384,7 @@ GC_PTR GC_local_malloc_atomic(size_t bytes)
     } else {
        int index = INDEX_FROM_BYTES(bytes);
        ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
-                       -> ptrfree_freelists + index;
+                       -> tlfs.ptrfree_freelists + index;
        ptr_t my_entry = *my_fl;
     
        if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
@@ -428,7 +424,7 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
     } else {
        int index = INDEX_FROM_BYTES(bytes);
        ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
-                       -> gcj_freelists + index;
+                       -> tlfs.gcj_freelists + index;
        ptr_t my_entry = *my_fl;
        if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
            GC_PTR result = (GC_PTR)my_entry;
@@ -467,7 +463,7 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
 void * GC_local_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
 {
        ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
-               -> gcj_freelists + lw;
+               -> tlfs.gcj_freelists + lw;
        ptr_t my_entry = *my_fl;
 
     GC_ASSERT(GC_gcj_malloc_initialized);
@@ -670,12 +666,12 @@ void GC_mark_thread_local_free_lists(void)
     for (i = 0; i < THREAD_TABLE_SZ; ++i) {
       for (p = GC_threads[i]; 0 != p; p = p -> next) {
        for (j = 1; j < NFREELISTS; ++j) {
-         q = p -> ptrfree_freelists[j];
+         q = p -> tlfs.ptrfree_freelists[j];
          if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
-         q = p -> normal_freelists[j];
+         q = p -> tlfs.normal_freelists[j];
          if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
 #        ifdef GC_GCJ_SUPPORT
-           q = p -> gcj_freelists[j];
+           q = p -> tlfs.gcj_freelists[j];
            if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
 #        endif /* GC_GCJ_SUPPORT */
        }
@@ -687,10 +683,10 @@ void GC_mark_thread_local_free_lists(void)
 static struct GC_Thread_Rep first_thread;
 
 #ifdef NACL
-extern int nacl_thread_parked[MAX_NACL_GC_THREADS];
-extern int nacl_thread_used[MAX_NACL_GC_THREADS];
-extern int nacl_thread_parking_inited;
-extern int nacl_num_gc_threads;
+extern volatile int nacl_thread_parked[MAX_NACL_GC_THREADS];
+extern volatile int nacl_thread_used[MAX_NACL_GC_THREADS];
+extern volatile int nacl_thread_parking_inited;
+extern volatile int nacl_num_gc_threads;
 extern pthread_mutex_t nacl_thread_alloc_lock;
 extern __thread int nacl_thread_idx;
 extern __thread GC_thread nacl_gc_thread_self;
@@ -699,10 +695,20 @@ extern void nacl_pre_syscall_hook();
 extern void nacl_post_syscall_hook();
 extern void nacl_register_gc_hooks(void (*pre)(), void (*post)());
 
+#include <stdio.h>
+
+struct nacl_irt_blockhook {
+  int (*register_block_hooks)(void (*pre)(void), void (*post)(void));
+};
+
+extern size_t nacl_interface_query(const char *interface_ident,
+                            void *table, size_t tablesize);
+
 void nacl_initialize_gc_thread()
 {
     int i;
-    nacl_register_gc_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook);
+    static struct nacl_irt_blockhook gc_hook;
+
     pthread_mutex_lock(&nacl_thread_alloc_lock);
     if (!nacl_thread_parking_inited)
     {
@@ -710,6 +716,10 @@ void nacl_initialize_gc_thread()
             nacl_thread_used[i] = 0;
             nacl_thread_parked[i] = 0;
         }
+        // TODO: replace with public 'register hook' function when
+        // available from glibc
+        nacl_interface_query("nacl-irt-blockhook-0.1", &gc_hook, sizeof(gc_hook));
+        gc_hook.register_block_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook);
         nacl_thread_parking_inited = 1;
     }
     GC_ASSERT(nacl_num_gc_threads <= MAX_NACL_GC_THREADS);
@@ -754,7 +764,7 @@ GC_thread GC_new_thread(pthread_t id)
     }
     if (result == 0) return(0);
     result -> id = id;
-#ifdef PLATFORM_ANDROID
+#ifdef HOST_ANDROID
     result -> kernel_id = gettid();
 #endif
     result -> next = GC_threads[hv];
@@ -790,10 +800,6 @@ void GC_delete_thread(pthread_t id)
     } else {
         prev -> next = p -> next;
     }
-#ifdef MONO_DEBUGGER_SUPPORTED
-    if (gc_thread_vtable && gc_thread_vtable->thread_exited)
-       gc_thread_vtable->thread_exited (id, &p->stop_info.stack_ptr);
-#endif
        
 #ifdef GC_DARWIN_THREADS
        mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
@@ -942,6 +948,7 @@ int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
 /* Return the number of processors, or i<= 0 if it can't be determined.        */
 int GC_get_nprocs()
 {
+#ifndef NACL
     /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that      */
     /* appears to be buggy in many cases.                              */
     /* We look for lines "cpu<n>" in /proc/stat.                       */
@@ -971,6 +978,9 @@ int GC_get_nprocs()
     }
     close(f);
     return result;
+#else /* NACL */
+    return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
 }
 #endif /* GC_LINUX_THREADS */
 
@@ -1106,14 +1116,6 @@ void GC_thr_init()
          t -> stop_info.stack_ptr = (ptr_t)(&dummy);
 #     endif
       t -> flags = DETACHED | MAIN_THREAD;
-#ifdef MONO_DEBUGGER_SUPPORTED
-      if (gc_thread_vtable && gc_thread_vtable->thread_created)
-#     ifdef GC_DARWIN_THREADS
-        gc_thread_vtable->thread_created (mach_thread_self (), &t->stop_info.stack_ptr);
-#     else
-         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;
@@ -1362,12 +1364,10 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval)
 }
 
 #ifdef NACL
-/* Native Client doesn't support pthread cleanup functions, */
-/* so wrap pthread_exit and manually cleanup the thread.    */
+/* TODO: remove, NaCl glibc now supports pthread cleanup functions. */
 void
 WRAP_FUNC(pthread_exit)(void *status)
 {
-    GC_thread_exit_proc(0); 
     REAL_FUNC(pthread_exit)(status);
 }
 #endif
@@ -1445,14 +1445,6 @@ void * GC_start_routine_head(void * arg, void *base_addr,
       /* This is also < 100% convincing.  We should also read this     */
       /* from /proc, but the hook to do so isn't there yet.            */
 #   endif /* IA64 */
-#ifdef MONO_DEBUGGER_SUPPORTED
-    if (gc_thread_vtable && gc_thread_vtable->thread_created)
-#      ifdef GC_DARWIN_THREADS
-       gc_thread_vtable->thread_created (mach_thread_self(), &me->stop_info.stack_ptr);
-#      else
-       gc_thread_vtable->thread_created (my_pthread, &me->stop_info.stack_ptr);
-#      endif
-#endif
     UNLOCK();
 
     if (start) *start = si -> start_routine;
@@ -1470,13 +1462,18 @@ void * GC_start_routine_head(void * arg, void *base_addr,
     return me;
 }
 
-int GC_thread_register_foreign (void *base_addr)
+void GC_allow_register_threads (void)
+{
+    /* No-op for GC pre-v7. */
+}
+
+int GC_register_my_thread (struct GC_stack_base *sb)
 {
     struct start_info si = { 0, }; /* stacked for legibility & locking */
     GC_thread me;
 
 #   ifdef DEBUG_THREADS
-        GC_printf1( "GC_thread_register_foreign %p\n", &si );
+        GC_printf1( "GC_register_my_thread %p\n", &si );
 #   endif
 
     si.flags = FOREIGN_THREAD;
@@ -1484,12 +1481,13 @@ int GC_thread_register_foreign (void *base_addr)
     if (!parallel_initialized) GC_init_parallel();
     LOCK();
     if (!GC_thr_initialized) GC_thr_init();
-
+    me = GC_lookup_thread(pthread_self());
     UNLOCK();
+    if (me != NULL)
+       return GC_DUPLICATE;
 
-    me = GC_start_routine_head(&si, base_addr, NULL, NULL);
-
-    return me != NULL;
+    (void)GC_start_routine_head(&si, sb -> mem_base, NULL, NULL);
+    return GC_SUCCESS;
 }
 
 void * GC_start_routine(void * arg)