summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore3
-rw-r--r--ChangeLog32
-rw-r--r--darwin_stop_world.c33
-rw-r--r--include/private/.cvsignore1
-rw-r--r--include/private/gcconfig.h41
-rw-r--r--misc.c2
-rw-r--r--os_dep.c185
-rw-r--r--pthread_support.c205
8 files changed, 268 insertions, 234 deletions
diff --git a/.cvsignore b/.cvsignore
index 2b0e71ae..d1ce9d22 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -9,8 +9,9 @@ hugetest
leaktest
libcord.la
libgc.la
+libstaticrootslib.la
libtool
middletest
smashtest
+staticrootstest
threadleaktest
-libstaticrootslib.la
diff --git a/ChangeLog b/ChangeLog
index 193635e6..fed5fa0c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2011-01-07 Ivan Maidanski <ivmai@mail.ru>
+
+ * .cvsignore: Add more auto-generated files.
+ * include/private/.cvsignore: Ditto.
+ * darwin_stop_world.c (GC_mach_handler_thread,
+ GC_use_mach_handler_thread,
+ GC_darwin_register_mach_handler_thread): Define only if
+ MPROTECT_VDB.
+ * darwin_stop_world.c (GC_suspend_thread_list): Use
+ GC_mach_handler_thread and GC_use_mach_handler_thread only if
+ MPROTECT_VDB.
+ * darwin_stop_world.c (GC_stop_world): Reset GC_mach_threads_count
+ only if defined (i.e. unless GC_NO_THREADS_DISCOVERY).
+ * misc.c (GC_init): Fix comment for GWW_VDB.
+ * os_dep.c (GC_mprotect_state_t): Reformat the code.
+ * os_dep.c (DARWIN_EXC_STATE, DARWIN_EXC_STATE_COUNT,
+ DARWIN_EXC_STATE_T, DARWIN_EXC_STATE_DAR): New macros.
+ * os_dep.c (catch_exception_raise): Use DARWIN_EXC_STATE,
+ DARWIN_EXC_STATE_COUNT, DARWIN_EXC_STATE_T, DARWIN_EXC_STATE_DAR;
+ reformat the comment.
+ * pthread_support.c (GC_thr_init): Define "dummy" local variable
+ only unless GC_DARWIN_THREADS; reformat the code.
+ * include/private/gcconfig.h (MPROTECT_VDB): Define for Darwin
+ even in the single-threaded mode; define for iPhone/iPad.
+ * include/private/gcconfig.h (IA64): Remove unnecessary "ifdef"
+ around "undef".
+ * include/private/gcconfig.h (HEURISTIC1): Remove unused for
+ Cygwin.
+ * include/private/gcconfig.h (STACKBOTTOM): Use fixed address for
+ Darwin/arm (instead of HEURISTIC1).
+ * include/private/gcconfig.h (GET_MEM): Reformat the code.
+
2011-01-05 Ivan Maidanski <ivmai@mail.ru>
* misc.c (GC_write): Replace multiple "ifdef/endif" with "elif"
diff --git a/darwin_stop_world.c b/darwin_stop_world.c
index 5f152688..6af69184 100644
--- a/darwin_stop_world.c
+++ b/darwin_stop_world.c
@@ -328,14 +328,16 @@ GC_INNER void GC_push_all_stacks(void)
#ifndef GC_NO_THREADS_DISCOVERY
- STATIC mach_port_t GC_mach_handler_thread = 0;
- STATIC GC_bool GC_use_mach_handler_thread = FALSE;
+# ifdef MPROTECT_VDB
+ STATIC mach_port_t GC_mach_handler_thread = 0;
+ STATIC GC_bool GC_use_mach_handler_thread = FALSE;
- GC_INNER void GC_darwin_register_mach_handler_thread(mach_port_t thread)
- {
- GC_mach_handler_thread = thread;
- GC_use_mach_handler_thread = TRUE;
- }
+ GC_INNER void GC_darwin_register_mach_handler_thread(mach_port_t thread)
+ {
+ GC_mach_handler_thread = thread;
+ GC_use_mach_handler_thread = TRUE;
+ }
+# endif /* MPROTECT_VDB */
# ifndef GC_MAX_MACH_THREADS
# define GC_MAX_MACH_THREADS THREAD_TABLE_SZ
@@ -370,8 +372,11 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count,
mach_msg_type_number_t outCount;
kern_return_t kern_result;
- if (thread == my_thread || (GC_mach_handler_thread == thread
- && GC_use_mach_handler_thread)) {
+ if (thread == my_thread
+# ifdef MPROTECT_VDB
+ || (GC_mach_handler_thread == thread && GC_use_mach_handler_thread)
+# endif
+ ) {
/* Don't add our and the handler threads. */
continue;
}
@@ -472,11 +477,6 @@ GC_INNER void GC_stop_world(void)
GC_printf("Stopping the world from thread 0x%lx\n",
(unsigned long)my_thread);
# endif
- /* Clear out the mach threads list table. We do not need to really */
- /* clear GC_mach_threads[] as it is used only in the range from 0 to */
- /* GC_mach_threads_count-1, inclusive. */
- GC_mach_threads_count = 0;
-
# ifdef PARALLEL_MARK
if (GC_parallel) {
/* Make sure all free list construction has stopped before we */
@@ -495,6 +495,11 @@ GC_INNER void GC_stop_world(void)
thread_act_array_t act_list, prev_list;
mach_msg_type_number_t listcount, prevcount;
+ /* Clear out the mach threads list table. We do not need to */
+ /* really clear GC_mach_threads[] as it is used only in the range */
+ /* from 0 to GC_mach_threads_count-1, inclusive. */
+ GC_mach_threads_count = 0;
+
/* Loop stopping threads until you have gone over the whole list */
/* twice without a new one appearing. thread_create() won't */
/* return (and thus the thread stop) until the new thread exists, */
diff --git a/include/private/.cvsignore b/include/private/.cvsignore
index f6115486..fbe81bc9 100644
--- a/include/private/.cvsignore
+++ b/include/private/.cvsignore
@@ -1,2 +1,3 @@
config.h
+config.h.in~
stamp-h1
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 401d58b7..653416fd 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -23,8 +23,7 @@
*/
#ifndef GCCONFIG_H
-
-# define GCCONFIG_H
+#define GCCONFIG_H
# ifndef GC_PRIVATE_H
/* Fake ptr_t declaration, just to avoid compilation errors. */
@@ -811,9 +810,7 @@
# define USE_MMAP
# endif
# define USE_MMAP_ANON
-# ifdef GC_DARWIN_THREADS
-# define MPROTECT_VDB
-# endif
+# define MPROTECT_VDB
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
@@ -888,11 +885,9 @@
# ifdef AIX
# define OS_TYPE "AIX"
# undef ALIGNMENT /* in case it's defined */
-# ifdef IA64
-# undef IA64
- /* DOB: some AIX installs stupidly define IA64 in */
- /* /usr/include/sys/systemcfg.h */
-# endif
+# undef IA64
+ /* DOB: some AIX installs stupidly define IA64 in */
+ /* /usr/include/sys/systemcfg.h */
# ifdef __64BIT__
# define ALIGNMENT 8
# define CPP_WORDSZ 64
@@ -1163,9 +1158,9 @@
# define MAP_FAILED (void *) ((word)-1)
# ifdef USE_MMAP
# define HEAP_START (ptr_t)0x40000000
-# else /* USE_MMAP */
+# else
# define HEAP_START DATAEND
-# endif /* USE_MMAP */
+# endif
# endif /* DGUX */
# ifdef LINUX
@@ -1247,7 +1242,6 @@
# define DATAEND ((ptr_t)GC_DATAEND)
# undef STACK_GRAN
# define STACK_GRAN 0x10000
-# define HEURISTIC1
# ifdef USE_MMAP
# define NEED_FIND_LIMIT
# define USE_MMAP_ANON
@@ -1384,9 +1378,7 @@
# define USE_MMAP
# endif
# define USE_MMAP_ANON
-# ifdef GC_DARWIN_THREADS
-# define MPROTECT_VDB
-# endif
+# define MPROTECT_VDB
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
/* There seems to be some issues with trylock hanging on darwin. This
@@ -1900,12 +1892,12 @@
# define OS_TYPE "DARWIN"
# define DATASTART ((ptr_t) get_etext())
# define DATAEND ((ptr_t) get_end())
-/* #define STACKBOTTOM ((ptr_t) 0x30000000) */ /* FIXME: Is this needed? */
-# define HEURISTIC1
+# define STACKBOTTOM ((ptr_t) 0x30000000)
# ifndef USE_MMAP
# define USE_MMAP
# endif
# define USE_MMAP_ANON
+# define MPROTECT_VDB
# endif
# ifdef OPENBSD
# define ALIGNMENT 4
@@ -2085,9 +2077,7 @@
# define USE_MMAP
# endif
# define USE_MMAP_ANON
-# ifdef GC_DARWIN_THREADS
-# define MPROTECT_VDB
-# endif
+# define MPROTECT_VDB
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
/* There seems to be some issues with trylock hanging on darwin. This
@@ -2609,7 +2599,7 @@
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
(defined(SOLARIS) && !defined(USE_MMAP))
# define GET_MEM(bytes) HBLKPTR((size_t) calloc(1, (size_t)bytes + GC_page_size) \
- + GC_page_size-1)
+ + GC_page_size-1)
# elif defined(MSWIN32) || defined(CYGWIN32)
ptr_t GC_win32_get_mem(GC_word bytes);
# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
@@ -2620,8 +2610,8 @@
GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \
+ GC_page_size-1)
# else
-# define GET_MEM(bytes) HBLKPTR( \
- NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
+# define GET_MEM(bytes) HBLKPTR(NewPtrClear(bytes + GC_page_size) \
+ + GC_page_size-1)
# endif
# elif defined(MSWINCE)
ptr_t GC_wince_get_mem(GC_word bytes);
@@ -2638,7 +2628,6 @@
ptr_t GC_unix_get_mem(GC_word bytes);
# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
# endif
-
#endif /* GC_PRIVATE_H */
-# endif /* GCCONFIG_H */
+#endif /* GCCONFIG_H */
diff --git a/misc.c b/misc.c
index 7b38ee13..d350b733 100644
--- a/misc.c
+++ b/misc.c
@@ -891,7 +891,7 @@ GC_API void GC_CALL GC_init(void)
GC_STATIC_ASSERT((signed_word)(-1) < (signed_word)0);
# ifndef GC_DISABLE_INCREMENTAL
if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
- /* For GWW_MPROTECT on Win32, this needs to happen before any */
+ /* For GWW_VDB on Win32, this needs to happen before any */
/* heap memory is allocated. */
GC_dirty_init();
GC_ASSERT(GC_bytes_allocd == 0)
diff --git a/os_dep.c b/os_dep.c
index b7f0fe9a..17aec6f7 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -3334,12 +3334,11 @@ GC_API int GC_CALL GC_incremental_protection_needs(void)
return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
}
}
-
#define HAVE_INCREMENTAL_PROTECTION_NEEDS
#define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
-
#define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
+
STATIC void GC_protect_heap(void)
{
ptr_t start;
@@ -3849,7 +3848,9 @@ typedef struct {
} GC_msg_t;
typedef enum {
- GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
+ GC_MP_NORMAL,
+ GC_MP_DISCARDING,
+ GC_MP_STOPPED
} GC_mprotect_state_t;
/* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
@@ -4182,8 +4183,40 @@ STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
#define FWD() GC_forward_exception(thread, task, exception, code, code_count)
-/* This violates the namespace rules but there isn't anything that can be done
- about it. The exception handling stuff is hard coded to call this. */
+#ifdef ARM32
+# define DARWIN_EXC_STATE ARM_EXCEPTION_STATE
+# define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE_COUNT
+# define DARWIN_EXC_STATE_T arm_exception_state_t
+# define DARWIN_EXC_STATE_DAR THREAD_FLD(far)
+#elif defined(POWERPC)
+# if CPP_WORDSZ == 32
+# define DARWIN_EXC_STATE PPC_EXCEPTION_STATE
+# define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
+# define DARWIN_EXC_STATE_T ppc_exception_state_t
+# else
+# define DARWIN_EXC_STATE PPC_EXCEPTION_STATE64
+# define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT
+# define DARWIN_EXC_STATE_T ppc_exception_state64_t
+# endif
+# define DARWIN_EXC_STATE_DAR THREAD_FLD(dar)
+#elif defined(I386) || defined(X86_64)
+# if CPP_WORDSZ == 32
+# define DARWIN_EXC_STATE x86_EXCEPTION_STATE32
+# define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE32_COUNT
+# define DARWIN_EXC_STATE_T x86_exception_state32_t
+# else
+# define DARWIN_EXC_STATE x86_EXCEPTION_STATE64
+# define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
+# define DARWIN_EXC_STATE_T x86_exception_state64_t
+# endif
+# define DARWIN_EXC_STATE_DAR THREAD_FLD(faultvaddr)
+#else
+# error FIXME for non-arm/ppc/x86 darwin
+#endif
+
+/* This violates the namespace rules but there isn't anything that can */
+/* be done about it. The exception handling stuff is hard coded to */
+/* call this. */
kern_return_t
catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
mach_port_t task, exception_type_t exception,
@@ -4193,30 +4226,9 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
char *addr;
struct hblk *h;
unsigned int i;
-# if defined(POWERPC)
-# if CPP_WORDSZ == 32
- thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
- mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
- ppc_exception_state_t exc_state;
-# else
- thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
- mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
- ppc_exception_state64_t exc_state;
-# endif
-# elif defined(I386) || defined(X86_64)
-# if CPP_WORDSZ == 32
- thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
- mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
- x86_exception_state32_t exc_state;
-# else
- thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
- mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
- x86_exception_state64_t exc_state;
-# endif
-# else
-# error FIXME for non-ppc/x86 darwin
-# endif
-
+ thread_state_flavor_t flavor = DARWIN_EXC_STATE;
+ mach_msg_type_number_t exc_state_count = DARWIN_EXC_STATE_COUNT;
+ DARWIN_EXC_STATE_T exc_state;
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
# ifdef DEBUG_EXCEPTION_HANDLING
@@ -4240,70 +4252,63 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
# endif
}
- /* This is the address that caused the fault */
-# if defined(POWERPC)
- addr = (char*) exc_state. THREAD_FLD(dar);
-# elif defined (I386) || defined (X86_64)
- addr = (char*) exc_state. THREAD_FLD(faultvaddr);
-# else
-# error FIXME for non POWERPC/I386
-# endif
-
- if((HDR(addr)) == 0) {
- /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
- KERN_PROTECTION_FAILURE every once and a while. We wait till we get
- a bunch in a row before doing anything about it. If a "real" fault
- ever occurs it'll just keep faulting over and over and we'll hit
- the limit pretty quickly. */
-# ifdef BROKEN_EXCEPTION_HANDLING
- static char *last_fault;
- static int last_fault_count;
-
- if(addr != last_fault) {
- last_fault = addr;
- last_fault_count = 0;
- }
- if(++last_fault_count < 32) {
- if(last_fault_count == 1)
- WARN("Ignoring KERN_PROTECTION_FAILURE at %p\n", addr);
- return KERN_SUCCESS;
- }
-
- GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n"
- "Aborting...\n", addr);
- /* Can't pass it along to the signal handler because that is
- ignoring SIGBUS signals. We also shouldn't call ABORT here as
- signals don't always work too well from the exception handler. */
- exit(EXIT_FAILURE);
-# else /* BROKEN_EXCEPTION_HANDLING */
- /* Pass it along to the next exception handler
- (which should call SIGBUS/SIGSEGV) */
- return FWD();
-# endif /* !BROKEN_EXCEPTION_HANDLING */
- }
-
+ /* This is the address that caused the fault */
+ addr = (char*) exc_state.DARWIN_EXC_STATE_DAR;
+ if ((HDR(addr)) == 0) {
+ /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
+ KERN_PROTECTION_FAILURE every once and a while. We wait till we get
+ a bunch in a row before doing anything about it. If a "real" fault
+ ever occurs it'll just keep faulting over and over and we'll hit
+ the limit pretty quickly. */
# ifdef BROKEN_EXCEPTION_HANDLING
- /* Reset the number of consecutive SIGBUSs */
- GC_sigbus_count = 0;
-# endif
+ static char *last_fault;
+ static int last_fault_count;
- if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
- h = (struct hblk*)((word)addr & ~(GC_page_size-1));
- UNPROTECT(h, GC_page_size);
- for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
- register int index = PHT_HASH(h+i);
- async_set_pht_entry_from_index(GC_dirty_pages, index);
+ if(addr != last_fault) {
+ last_fault = addr;
+ last_fault_count = 0;
}
- } else if(GC_mprotect_state == GC_MP_DISCARDING) {
- /* Lie to the thread for now. No sense UNPROTECT()ing the memory
- when we're just going to PROTECT() it again later. The thread
- will just fault again once it resumes */
- } else {
- /* Shouldn't happen, i don't think */
- GC_err_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
+ if(++last_fault_count < 32) {
+ if(last_fault_count == 1)
+ WARN("Ignoring KERN_PROTECTION_FAILURE at %p\n", addr);
+ return KERN_SUCCESS;
+ }
+
+ GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n"
+ "Aborting...\n", addr);
+ /* Can't pass it along to the signal handler because that is
+ ignoring SIGBUS signals. We also shouldn't call ABORT here as
+ signals don't always work too well from the exception handler. */
+ exit(EXIT_FAILURE);
+# else /* BROKEN_EXCEPTION_HANDLING */
+ /* Pass it along to the next exception handler
+ (which should call SIGBUS/SIGSEGV) */
return FWD();
+# endif /* !BROKEN_EXCEPTION_HANDLING */
+ }
+
+# ifdef BROKEN_EXCEPTION_HANDLING
+ /* Reset the number of consecutive SIGBUSs */
+ GC_sigbus_count = 0;
+# endif
+
+ if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
+ h = (struct hblk*)((word)addr & ~(GC_page_size-1));
+ UNPROTECT(h, GC_page_size);
+ for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
+ register int index = PHT_HASH(h+i);
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
}
- return KERN_SUCCESS;
+ } else if(GC_mprotect_state == GC_MP_DISCARDING) {
+ /* Lie to the thread for now. No sense UNPROTECT()ing the memory
+ when we're just going to PROTECT() it again later. The thread
+ will just fault again once it resumes */
+ } else {
+ /* Shouldn't happen, i don't think */
+ GC_err_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
+ return FWD();
+ }
+ return KERN_SUCCESS;
}
#undef FWD
@@ -4333,12 +4338,12 @@ catch_exception_raise_state_identity(mach_port_name_t exception_port,
#endif /* DARWIN && MPROTECT_VDB */
-# ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
+#ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
GC_API int GC_CALL GC_incremental_protection_needs(void)
{
return GC_PROTECTS_NONE;
}
-# endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
+#endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
#ifdef ECOS
/* Undo sbrk() redirection. */
diff --git a/pthread_support.c b/pthread_support.c
index 26460a79..37e5d95f 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -856,119 +856,120 @@ STATIC void GC_fork_child_proc(void)
/* We hold the allocation lock. */
GC_INNER void GC_thr_init(void)
{
+# ifndef GC_DARWIN_THREADS
int dummy;
+# endif
+ if (GC_thr_initialized) return;
+ GC_thr_initialized = TRUE;
- if (GC_thr_initialized) return;
- GC_thr_initialized = TRUE;
-
-# ifdef HANDLE_FORK
- /* Prepare for a possible fork. */
- pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
- GC_fork_child_proc);
-# endif /* HANDLE_FORK */
-# if defined(INCLUDE_LINUX_THREAD_DESCR)
- /* Explicitly register the region including the address */
- /* of a thread local variable. This should include thread */
- /* locals for the main thread, except for those allocated */
- /* in response to dlopen calls. */
- {
- ptr_t thread_local_addr = (ptr_t)(&GC_dummy_thread_local);
- ptr_t main_thread_start, main_thread_end;
- if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start,
- &main_thread_end)) {
- ABORT("Failed to find mapping for main thread thread locals");
- }
- GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);
- }
-# endif
- /* Add the initial thread, so we can stop it. */
+# ifdef HANDLE_FORK
+ /* Prepare for a possible fork. */
+ pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
+ GC_fork_child_proc);
+# endif
+# ifdef INCLUDE_LINUX_THREAD_DESCR
+ /* Explicitly register the region including the address */
+ /* of a thread local variable. This should include thread */
+ /* locals for the main thread, except for those allocated */
+ /* in response to dlopen calls. */
{
- GC_thread t = GC_new_thread(pthread_self());
-# ifdef GC_DARWIN_THREADS
- t -> stop_info.mach_thread = mach_thread_self();
-# else
- t -> stop_info.stack_ptr = (ptr_t)(&dummy);
-# endif
- t -> flags = DETACHED | MAIN_THREAD;
+ ptr_t thread_local_addr = (ptr_t)(&GC_dummy_thread_local);
+ ptr_t main_thread_start, main_thread_end;
+ if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start,
+ &main_thread_end)) {
+ ABORT("Failed to find mapping for main thread thread locals");
+ }
+ GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);
}
-
-# ifndef GC_DARWIN_THREADS
- GC_stop_init();
+# endif
+ /* Add the initial thread, so we can stop it. */
+ {
+ GC_thread t = GC_new_thread(pthread_self());
+# ifdef GC_DARWIN_THREADS
+ t -> stop_info.mach_thread = mach_thread_self();
+# else
+ t -> stop_info.stack_ptr = (ptr_t)(&dummy);
# endif
+ t -> flags = DETACHED | MAIN_THREAD;
+ }
- /* Set GC_nprocs. */
- {
- char * nprocs_string = GETENV("GC_NPROCS");
- GC_nprocs = -1;
- if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
- }
- if (GC_nprocs <= 0) {
-# if defined(GC_HPUX_THREADS)
- GC_nprocs = pthread_num_processors_np();
-# endif
-# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \
- || defined(GC_SOLARIS_THREADS) || defined(GC_GNU_THREADS)
- GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
- if (GC_nprocs <= 0) GC_nprocs = 1;
-# endif
-# if defined(GC_IRIX_THREADS)
- GC_nprocs = sysconf(_SC_NPROC_ONLN);
- if (GC_nprocs <= 0) GC_nprocs = 1;
-# endif
-# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) \
- || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS)
- GC_nprocs = get_ncpu();
-# endif
-# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
- GC_nprocs = GC_get_nprocs();
-# endif
- }
- if (GC_nprocs <= 0) {
- WARN("GC_get_nprocs() returned %" GC_PRIdPTR "\n", GC_nprocs);
- GC_nprocs = 2;
-# ifdef PARALLEL_MARK
- GC_markers = 1;
-# endif
- } else {
-# ifdef PARALLEL_MARK
- {
- char * markers_string = GETENV("GC_MARKERS");
- if (markers_string != NULL) {
- GC_markers = atoi(markers_string);
- if (GC_markers > MAX_MARKERS) {
- WARN("Limiting number of mark threads\n", 0);
- GC_markers = MAX_MARKERS;
- }
- } else {
- GC_markers = GC_nprocs;
- if (GC_markers >= MAX_MARKERS)
- GC_markers = MAX_MARKERS; /* silently limit GC_markers value */
- }
- }
-# endif
- }
+# ifndef GC_DARWIN_THREADS
+ GC_stop_init();
+# endif
+
+ /* Set GC_nprocs. */
+ {
+ char * nprocs_string = GETENV("GC_NPROCS");
+ GC_nprocs = -1;
+ if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
+ }
+ if (GC_nprocs <= 0) {
+# if defined(GC_HPUX_THREADS)
+ GC_nprocs = pthread_num_processors_np();
+# endif
+# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \
+ || defined(GC_SOLARIS_THREADS) || defined(GC_GNU_THREADS)
+ GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
+ if (GC_nprocs <= 0) GC_nprocs = 1;
+# endif
+# if defined(GC_IRIX_THREADS)
+ GC_nprocs = sysconf(_SC_NPROC_ONLN);
+ if (GC_nprocs <= 0) GC_nprocs = 1;
+# endif
+# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) \
+ || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS)
+ GC_nprocs = get_ncpu();
+# endif
+# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
+ GC_nprocs = GC_get_nprocs();
+# endif
+ }
+ if (GC_nprocs <= 0) {
+ WARN("GC_get_nprocs() returned %" GC_PRIdPTR "\n", GC_nprocs);
+ GC_nprocs = 2;
# ifdef PARALLEL_MARK
+ GC_markers = 1;
+# endif
+ } else {
+# ifdef PARALLEL_MARK
+ {
+ char * markers_string = GETENV("GC_MARKERS");
+ if (markers_string != NULL) {
+ GC_markers = atoi(markers_string);
+ if (GC_markers > MAX_MARKERS) {
+ WARN("Limiting number of mark threads\n", 0);
+ GC_markers = MAX_MARKERS;
+ }
+ } else {
+ GC_markers = GC_nprocs;
+ if (GC_markers >= MAX_MARKERS)
+ GC_markers = MAX_MARKERS; /* silently limit GC_markers value */
+ }
+ }
+# endif
+ }
+# ifdef PARALLEL_MARK
+ if (GC_print_stats) {
+ GC_log_printf("Number of processors = %ld, "
+ "number of marker threads = %ld\n", GC_nprocs, GC_markers);
+ }
+ if (GC_markers <= 1) {
+ GC_parallel = FALSE;
if (GC_print_stats) {
- GC_log_printf("Number of processors = %ld, "
- "number of marker threads = %ld\n", GC_nprocs, GC_markers);
- }
- if (GC_markers <= 1) {
- GC_parallel = FALSE;
- if (GC_print_stats) {
- GC_log_printf(
- "Single marker thread, turning off parallel marking\n");
- }
- } else {
- GC_parallel = TRUE;
- /* Disable true incremental collection, but generational is OK. */
- GC_time_limit = GC_TIME_UNLIMITED;
+ GC_log_printf("Single marker thread, turning off parallel marking\n");
}
- /* If we are using a parallel marker, actually start helper threads. */
- if (GC_parallel) start_mark_threads();
-# endif
+ } else {
+ GC_parallel = TRUE;
+ /* Disable true incremental collection, but generational is OK. */
+ GC_time_limit = GC_TIME_UNLIMITED;
+ }
+ /* If we are using a parallel marker, actually start helper threads. */
+ if (GC_parallel) {
+ start_mark_threads();
+ }
+# endif
}
-
/* Perform all initializations, including those that */
/* may require allocation. */
/* Called without allocation lock. */