--> 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_OPENBSD_THREADS)
# define USE_PTHREAD_SPECIFIC
# endif
+#endif
# if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
# define _POSIX4A_DRAFT10_SOURCE 1
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
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. */
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
}
# 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
}
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);
} 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)) {
} 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;
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);
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 */
}
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;
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)
{
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);
}
if (result == 0) return(0);
result -> id = id;
-#ifdef PLATFORM_ANDROID
+#ifdef HOST_ANDROID
result -> kernel_id = gettid();
#endif
result -> next = GC_threads[hv];
} 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);
/* 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. */
}
close(f);
return result;
+#else /* NACL */
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
}
#endif /* GC_LINUX_THREADS */
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;
}
#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
/* 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;
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;
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)