+2011-05-31 Ivan Maidanski <ivmai@mail.ru>
+
+ * alloc.c (GC_add_current_malloc_heap, GC_build_back_graph,
+ GC_traverse_back_graph): Move prototype to gc_priv.h.
+ * checksums.c (GC_page_was_ever_dirty): Ditto.
+ * dbg_mlc.c (GC_default_print_heap_obj_proc): Ditto.
+ * dyn_load.c (GC_parse_map_entry, GC_get_maps,
+ GC_segment_is_thread_stack, GC_roots_present, GC_is_heap_base,
+ GC_get_next_stack): Ditto.
+ * finalize.c (GC_reset_finalizer_nested,
+ GC_check_finalizer_nested): Ditto.
+ * gcj_mlc.c (GC_start_debugging, GC_store_debug_info): Ditto.
+ * malloc.c (GC_extend_size_map, GC_text_mapping): Ditto.
+ * mark_rts.c (GC_mark_thread_local_free_lists): Ditto.
+ * misc.c (GC_register_main_static_data, GC_init_win32,
+ GC_setpagesize, GC_init_linux_data_start,
+ GC_set_and_save_fault_handler, GC_init_dyld, GC_init_netbsd_elf,
+ GC_initialize_offsets, GC_bl_init, GC_do_blocking_inner,
+ GC_bl_init_no_interiors): Ditto.
+ * os_dep.c (GC_greatest_stack_base_below, GC_push_all_stacks):
+ Ditto.
+ * reclaim.c (GC_check_leaked): Ditto.
+ * win32_threads.c (GC_gww_dirty_init): Ditto.
+ * darwin_stop_world.c (GC_is_mach_marker, GC_mprotect_stop,
+ GC_mprotect_resume): Move prototype to darwin_stop_world.h.
+ * pthread_support.c (GC_FindTopOfStack): Ditto.
+ * dyn_load.c (GC_cond_add_roots): Merge adjacent definitions.
+ * mark.c (GC_page_was_ever_dirty): Remove (as already declared).
+ * mark_rts.c (GC_roots_present): Change return type to void
+ pointer (to match the prototype); return NULL instead of FALSE.
+ * mark_rts.c (GC_add_roots_inner): Cast GC_roots_present() result.
+ * os_dep.c (NEED_PROC_MAPS): Move definition to gcconfig.h.
+ * os_dep.c (GC_write_fault_handler): Make STATIC.
+ * os_dep.c (GC_set_write_fault_handler): New function (only if
+ GC_WIN32_THREADS).
+ * pthread_start.c (GC_start_rtn_prepare_thread,
+ GC_thread_exit_proc): Move prototype to pthread_support.h.
+ * pthread_support.c (GC_nacl_initialize_gc_thread,
+ GC_nacl_shutdown_gc_thread, GC_unblock_gc_signals):
+ Ditto.
+ * pthread_support.c (GC_stop_init): Move prototype to
+ pthread_stop_world.h.
+ * thread_local_alloc.c (GC_check_tls_for): Reformat comment.
+ * win32_threads.c (GC_write_fault_handler): Remove prototype.
+ * win32_threads.c (GC_register_my_thread_inner): Call
+ GC_set_write_fault_handler instead of SetUnhandledExceptionFilter
+ (only if MPROTECT_VDB).
+ * doc/README.win32: Add information about DMC.
+ * include/private/gc_priv.h (GC_set_write_fault_handler): New
+ prototype (only if GC_WIN32_THREADS and MPROTECT_VDB).
+
2011-05-31 Ivan Maidanski <ivmai@mail.ru>
* misc.c (vsnprintf): Redirect to vsprintf() if NO_VSNPRINTF.
return(result);
}
-#if !defined(REDIRECT_MALLOC) && (defined(MSWIN32) || defined(MSWINCE))
- GC_INNER void GC_add_current_malloc_heap(void);
-#endif
-
-#ifdef MAKE_BACK_GRAPH
- GC_INNER void GC_build_back_graph(void);
-#endif
-
#ifndef SMALL_CONFIG
/* Variables for world-stop average delay time statistic computation. */
/* "divisor" is incremented every world-stop and halved when reached */
void GC_check_tls(void);
#endif
-#ifdef MAKE_BACK_GRAPH
- GC_INNER void GC_traverse_back_graph(void);
-#endif
-
/* Finish up a collection. Assumes mark bits are consistent, lock is */
/* held, but the world is otherwise running. */
STATIC void GC_finish_collection(void)
int GC_n_clean = 0;
int GC_n_dirty = 0;
-GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h);
-
STATIC void GC_update_check_page(struct hblk *h, int index)
{
page_entry *pe = GC_sums + index;
STATIC int GC_mach_threads_count = 0;
/* FIXME: it is better to implement GC_mach_threads as a hash set. */
-# ifdef PARALLEL_MARK
- GC_INNER GC_bool GC_is_mach_marker(thread_act_t thread);
-# endif
-
/* returns true if there's a thread in act_list that wasn't in old_list */
STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count,
thread_act_array_t old_list,
#endif /* !GC_NO_THREADS_DISCOVERY */
-#ifdef MPROTECT_VDB
- GC_INNER void GC_mprotect_stop(void);
- GC_INNER void GC_mprotect_resume(void);
-#endif
-
/* Caller holds allocation lock. */
GC_INNER void GC_stop_world(void)
{
#endif
#include <string.h>
-GC_INNER void GC_default_print_heap_obj_proc(ptr_t p);
-
#ifndef SHORT_DBG_HDRS
/* Check whether object with base pointer p has debugging info. */
/* p is assumed to point to a legitimate object in our part */
require the assembler. If you do have the assembler, I recommend
removing the -DUSE_GENERIC.
+Digital Mars compiler
+---------------------
+
+Same as MS Visual C++ but might require
+-DAO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE option to compile with the
+parallel marker enabled.
Watcom compiler
---------------
#define MAPS_BUF_SIZE (32*1024)
-GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
- char **prot, unsigned int *maj_dev,
- char **mapping_name);
-GC_INNER char *GC_get_maps(void); /* from os_dep.c */
-
/* Sort an array of HeapSects by start address. */
/* Unfortunately at least some versions of */
/* Linux qsort end up calling malloc by way of sysconf, and hence can't */
}
}
-#ifdef THREADS
- GC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi);
-#endif
-
STATIC word GC_register_map_entries(char *maps)
{
char *prot;
# define IRIX6
#endif
-GC_INNER void * GC_roots_present(ptr_t);
- /* The type is a lie, since the real type doesn't make sense here, */
- /* and we only test for NULL. */
-
/* We use /proc to track down all parts of the address space that are */
/* mapped by the process, and throw out regions we know we shouldn't */
/* worry about. This may also work under other SVR4 variants. */
/* We traverse the entire address space and register all segments */
/* that could possibly have been written to. */
-
- GC_INNER GC_bool GC_is_heap_base(ptr_t p);
-
-# ifdef GC_WIN32_THREADS
- GC_INNER void GC_get_next_stack(char *start, char * limit, char **lo,
- char **hi);
-
- STATIC void GC_cond_add_roots(char *base, char * limit)
- {
+ STATIC void GC_cond_add_roots(char *base, char * limit)
+ {
+# ifdef GC_WIN32_THREADS
char * curr_base = base;
char * next_stack_lo;
char * next_stack_hi;
curr_base = next_stack_hi;
}
if (curr_base < limit) GC_add_roots_inner(curr_base, limit, TRUE);
- }
-# else
- STATIC void GC_cond_add_roots(char *base, char * limit)
- {
+# else
char dummy;
char * stack_top
= (char *) ((word)(&dummy) & ~(GC_sysinfo.dwAllocationGranularity-1));
return;
}
GC_add_roots_inner(base, limit, TRUE);
- }
-# endif
+# endif
+ }
#ifdef DYNAMIC_LOADING
/* GC_register_main_static_data is not needed unless DYNAMIC_LOADING. */
}
}
}
-#endif
+#endif /* !NO_DEBUGGING */
#ifndef SMALL_CONFIG
STATIC word GC_old_dl_entries = 0; /* for stats printing */
#endif
-#ifdef THREADS
- /* Defined in pthread_support.c or win32_threads.c. Called with the */
- /* allocation lock held. */
- GC_INNER void GC_reset_finalizer_nested(void);
- GC_INNER unsigned char *GC_check_finalizer_nested(void);
-#else
+#ifndef THREADS
/* Global variables to minimize the level of recursion when a client */
/* finalizer allocates memory. */
STATIC unsigned char GC_finalizer_nested = 0;
return((void *) op);
}
-GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */
-
-/* Store debugging info into p. Return displaced pointer. */
-/* Assumes we don't hold allocation lock. */
-GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
- int linenum);
-
/* Similar to GC_gcj_malloc, but add debug info. This is allocated */
/* with GC_gcj_debug_kind. */
GC_API void * GC_CALL GC_debug_gcj_malloc(size_t lb,
ptr_t stack_ptr; /* Valid only when thread is in a "blocked" state. */
};
+#ifndef DARWIN_DONT_PARSE_STACK
+ GC_INNER ptr_t GC_FindTopOfStack(unsigned long);
+#endif
+
+#ifdef MPROTECT_VDB
+ GC_INNER void GC_mprotect_stop(void);
+ GC_INNER void GC_mprotect_resume(void);
+#endif
+
+#if defined(PARALLEL_MARK) && !defined(GC_NO_THREADS_DISCOVERY)
+ GC_INNER GC_bool GC_is_mach_marker(thread_act_t);
+#endif
+
#endif
#if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
struct _SYSTEM_INFO;
GC_EXTERN struct _SYSTEM_INFO GC_sysinfo;
+ GC_INNER GC_bool GC_is_heap_base(ptr_t p);
#endif
+
GC_EXTERN word GC_black_list_spacing;
/* Average number of bytes between blacklisted */
/* blocks. Approximate. */
/* Do not immediately deallocate object on */
/* free() in the leak-finding mode, just mark */
/* it as freed (and deallocate it after GC). */
+ GC_INNER GC_bool GC_check_leaked(ptr_t base); /* from dbg_mlc.c */
#endif
GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */
#ifdef THREAD_LOCAL_ALLOC
GC_EXTERN GC_bool GC_world_stopped; /* defined in alloc.c */
+ GC_INNER void GC_mark_thread_local_free_lists(void);
#endif
#ifdef GC_GCJ_SUPPORT
GC_EXTERN ptr_t * GC_gcjobjfreelist;
#endif
+#if defined(GWW_VDB) && defined(MPROTECT_VDB)
+ GC_INNER GC_bool GC_gww_dirty_init(void);
+ /* Defined in os_dep.c. Returns TRUE if GetWriteWatch is available. */
+ /* May be called repeatedly. */
+#endif
+
+#if defined(CHECKSUMS) || defined(PROC_VDB)
+ GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h);
+ /* Could the page contain valid heap pointers? */
+#endif
+
+GC_INNER void GC_default_print_heap_obj_proc(ptr_t p);
+
+GC_INNER void GC_extend_size_map(size_t); /* in misc.c */
+
+GC_INNER void GC_setpagesize(void);
+
+GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */
+
+GC_INNER void GC_bl_init(void);
+GC_INNER void GC_bl_init_no_interiors(void); /* defined in blacklst.c */
+
+GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */
+
+/* Store debugging info into p. Return displaced pointer. */
+/* Assumes we don't hold allocation lock. */
+GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
+ int linenum);
+
+#ifdef REDIRECT_MALLOC
+# ifdef GC_LINUX_THREADS
+ GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp);
+ /* from os_dep.c */
+# endif
+#elif defined(MSWIN32) || defined(MSWINCE)
+ GC_INNER void GC_add_current_malloc_heap(void);
+#endif /* !REDIRECT_MALLOC */
+
+#ifdef MAKE_BACK_GRAPH
+ GC_INNER void GC_build_back_graph(void);
+ GC_INNER void GC_traverse_back_graph(void);
+#endif
+
+#ifdef MSWIN32
+ GC_INNER void GC_init_win32(void);
+#endif
+
+#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32)
+ GC_INNER void * GC_roots_present(ptr_t);
+ /* The type is a lie, since the real type doesn't make sense here, */
+ /* and we only test for NULL. */
+#endif
+
+#ifdef GC_WIN32_THREADS
+ GC_INNER void GC_get_next_stack(char *start, char * limit, char **lo,
+ char **hi);
+# ifdef MPROTECT_VDB
+ GC_INNER void GC_set_write_fault_handler(void);
+# endif
+#endif /* GC_WIN32_THREADS */
+
+#ifdef THREADS
+ GC_INNER void GC_reset_finalizer_nested(void);
+ GC_INNER unsigned char *GC_check_finalizer_nested(void);
+ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context);
+ GC_INNER void GC_push_all_stacks(void);
+# ifdef USE_PROC_FOR_LIBRARIES
+ GC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi);
+# endif
+# ifdef IA64
+ GC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound);
+# endif
+#endif /* THREADS */
+
+#ifdef DYNAMIC_LOADING
+ GC_INNER GC_bool GC_register_main_static_data(void);
+# ifdef DARWIN
+ GC_INNER void GC_init_dyld(void);
+# endif
+#endif /* DYNAMIC_LOADING */
+
+#ifdef SEARCH_FOR_DATA_START
+ GC_INNER void GC_init_linux_data_start(void);
+#endif
+
+#if defined(NETBSD) && defined(__ELF__)
+ GC_INNER void GC_init_netbsd_elf(void);
+#endif
+
+#ifdef UNIX_LIKE
+ GC_INNER void GC_set_and_save_fault_handler(void (*handler)(int));
+#endif
+
+#ifdef NEED_PROC_MAPS
+ GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
+ char **prot, unsigned int *maj_dev,
+ char **mapping_name);
+ GC_INNER char *GC_get_maps(void); /* from os_dep.c */
+#endif
+
#ifdef GC_ASSERTIONS
# define GC_ASSERT(expr) \
if (!(expr)) { \
# endif
#endif
+#if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \
+ || !defined(SMALL_CONFIG))
+# define NEED_PROC_MAPS
+#endif
+
#if defined(LINUX) || defined(HURD) || defined(__GLIBC__)
# define REGISTER_LIBRARIES_EARLY
/* We sometimes use dl_iterate_phdr, which may acquire an internal */
# endif
};
+GC_INNER void GC_stop_init(void);
+
#endif
#ifdef THREAD_LOCAL_ALLOC
# include "thread_local_alloc.h"
-#endif /* THREAD_LOCAL_ALLOC */
+#endif
/* We use the allocation lock to protect thread-related data structures. */
/* Only set to TRUE while allocation lock is held. */
/* When set, it is OK to run GC from unknown thread. */
-# ifdef NACL
- GC_EXTERN __thread GC_thread GC_nacl_gc_thread_self;
-# endif
+#ifdef NACL
+ GC_EXTERN __thread GC_thread GC_nacl_gc_thread_self;
+ GC_INNER void GC_nacl_initialize_gc_thread(void);
+ GC_INNER void GC_nacl_shutdown_gc_thread(void);
+#endif
+
+#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ GC_INNER void GC_unblock_gc_signals(void);
+#endif
+
+GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *),
+ void **pstart_arg,
+ struct GC_stack_base *sb, void *arg);
+GC_INNER void GC_thread_exit_proc(void *);
#endif /* GC_PTHREADS && !GC_WIN32_THREADS */
#include <stdio.h>
#include <string.h>
-GC_INNER void GC_extend_size_map(size_t); /* in misc.c */
-
/* Allocate reclaim list for kind: */
/* Return TRUE on success */
STATIC GC_bool GC_alloc_reclaim_list(struct obj_kind *kind)
STATIC ptr_t GC_libpthread_end = 0;
STATIC ptr_t GC_libld_start = 0;
STATIC ptr_t GC_libld_end = 0;
- GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp);
- /* From os_dep.c */
STATIC void GC_init_lib_bounds(void)
{
}
}
-# ifdef PROC_VDB
- GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h);
- /* Could the page contain valid heap pointers? */
-# endif
-
GC_INNER void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all)
{
if (!all) {
/* Is a range starting at b already in the table? If so return a */
/* pointer to it, else NULL. */
- GC_INNER struct roots * GC_roots_present(ptr_t b)
+ GC_INNER void * GC_roots_present(ptr_t b)
{
int h = rt_hash(b);
struct roots *p = GC_root_index[h];
if (p -> r_start == (ptr_t)b) return(p);
p = p -> r_next;
}
- return(FALSE);
+ return NULL;
}
/* Add the given root structure to the index. */
}
}
# else
- old = GC_roots_present(b);
+ old = (struct roots *)GC_roots_present(b);
if (old != 0) {
if (e <= old -> r_end) /* already there */ return;
/* else extend */
GC_push_typed_structures();
}
-#ifdef THREAD_LOCAL_ALLOC
- GC_INNER void GC_mark_thread_local_free_lists(void);
-#endif
-
GC_INNER void GC_cond_register_dynamic_libraries(void)
{
# if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
#ifdef DYNAMIC_LOADING
/* We need to register the main data segment. Returns TRUE unless */
/* this is done implicitly as part of dynamic library registration. */
- GC_INNER GC_bool GC_register_main_static_data(void);
# define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data()
#else
/* Don't unnecessarily call GC_register_main_static_data() in case */
GC_INNER CRITICAL_SECTION GC_write_cs;
#endif
-#ifdef MSWIN32
- GC_INNER void GC_init_win32(void);
-#endif
-
-GC_INNER void GC_setpagesize(void);
-
STATIC void GC_exit_check(void)
{
GC_gcollect();
}
-#ifdef SEARCH_FOR_DATA_START
- GC_INNER void GC_init_linux_data_start(void);
-#endif
-
#ifdef UNIX_LIKE
-
- GC_INNER void GC_set_and_save_fault_handler(void (*handler)(int));
-
static void looping_handler(int sig)
{
GC_err_printf("Caught signal %d: looping in handler\n", sig);
# define maybe_install_looping_handler()
#endif
-#if defined(DYNAMIC_LOADING) && defined(DARWIN)
- GC_INNER void GC_init_dyld(void);
-#endif
-
-#if defined(NETBSD) && defined(__ELF__)
- GC_INNER void GC_init_netbsd_elf(void);
-#endif
-
#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
STATIC int GC_stdout = 1;
STATIC int GC_stderr = 2;
return result;
}
-GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */
-GC_INNER void GC_bl_init(void); /* defined in blacklst.c */
-
GC_API void GC_CALL GC_init(void)
{
/* LOCK(); -- no longer does anything this early. */
return fn(&base, arg);
}
-#ifdef THREADS
-
- /* Defined in pthread_support.c or win32_threads.c. */
- GC_INNER void GC_do_blocking_inner(ptr_t data, void * context);
-
-#else
+#ifndef THREADS
GC_INNER ptr_t GC_blocked_sp = NULL;
/* NULL value means we are not inside GC_do_blocking() call. */
return GC_find_leak;
}
-GC_INNER void GC_bl_init_no_interiors(void); /* defined in blacklst.c */
-
GC_API void GC_CALL GC_set_all_interior_pointers(int value)
{
DCL_LOCK_STATE;
#define IGNORE_PAGES_EXECUTABLE 1
/* Undefined on GC_pages_executable real use. */
-#if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \
- || !defined(SMALL_CONFIG))
-# define NEED_PROC_MAPS
-#endif
-
#ifdef NEED_PROC_MAPS
/* We need to parse /proc/self/maps, either to find dynamic libraries, */
/* and/or to find the register backing store base (IA64). Do it once */
# endif /* LINUX */
GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
}
-#endif
+#endif /* SEARCH_FOR_DATA_START */
#ifdef ECOS
# include <pthread.h>
/* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */
-# ifdef IA64
- GC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound);
- /* From pthread_support.c */
-# endif
-
GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
{
pthread_attr_t attr;
# endif /* PCR */
-
# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
-
-GC_INNER void GC_push_all_stacks(void);
-
-STATIC void GC_default_push_other_roots(void)
-{
- GC_push_all_stacks();
-}
-
+ STATIC void GC_default_push_other_roots(void)
+ {
+ GC_push_all_stacks();
+ }
# endif /* GC_WIN32_THREADS || GC_PTHREADS */
# ifdef SN_TARGET_PS3
== STATUS_ACCESS_VIOLATION)
# define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
== 1) /* Write fault */
- GC_INNER LONG WINAPI GC_write_fault_handler(
+ STATIC LONG WINAPI GC_write_fault_handler(
struct _EXCEPTION_POINTERS *exc_info)
# endif /* MSWIN32 || MSWINCE */
{
ABORT("Unexpected bus error or segmentation fault");
# endif
}
+
+# ifdef GC_WIN32_THREADS
+ GC_INNER void GC_set_write_fault_handler(void)
+ {
+ SetUnhandledExceptionFilter(GC_write_fault_handler);
+ }
+# endif
#endif /* !DARWIN */
/* We hold the allocation lock. We expect block h to be written */
#include <pthread.h>
#include <sched.h>
-GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *),
- void **pstart_arg,
- struct GC_stack_base *sb, void *arg);
-GC_INNER void GC_thread_exit_proc(void *arg);
- /* defined in pthread_support.c */
-
/* Invoked from GC_start_routine(). */
void * GC_CALLBACK GC_inner_start_routine(struct GC_stack_base *sb, void *arg)
{
/* It may not be safe to allocate when we register the first thread. */
static struct GC_Thread_Rep first_thread;
-#ifdef NACL
- GC_INNER void GC_nacl_initialize_gc_thread(void);
- GC_INNER void GC_nacl_shutdown_gc_thread(void);
-#endif
-
/* Add a thread to GC_threads. We assume it wasn't already there. */
/* Caller holds allocation lock. */
STATIC GC_thread GC_new_thread(pthread_t id)
__thread int GC_dummy_thread_local;
#endif
-#ifndef GC_DARWIN_THREADS
- GC_INNER void GC_stop_init(void); /* defined in pthread_stop_world.c */
-#endif
-
/* We hold the allocation lock. */
GC_INNER void GC_thr_init(void)
{
}
#endif /* !GC_NO_PTHREAD_SIGMASK */
-#if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
- GC_INNER ptr_t GC_FindTopOfStack(unsigned long);
-#endif
-
/* Wrapper for functions that are likely to block for an appreciable */
/* length of time. */
# endif
}
-#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
- GC_INNER void GC_unblock_gc_signals(void); /* from pthread_stop_world.c */
-#endif
-
STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
pthread_t my_pthread)
{
GC_INNER GC_bool GC_have_errors = FALSE;
-#ifndef SHORT_DBG_HDRS
- GC_INNER GC_bool GC_check_leaked(ptr_t base); /* from dbg_mlc.c */
-#endif
-
GC_INLINE void GC_add_leaked(ptr_t leaked)
{
# ifndef SHORT_DBG_HDRS
}
#if defined(GC_ASSERTIONS)
- /* Check that all thread-local free-lists in p are completely marked. */
+ /* Check that all thread-local free-lists in p are completely marked. */
void GC_check_tls_for(GC_tlfs p)
{
ptr_t q;
return(result);
}
-#ifdef MPROTECT_VDB
- GC_INNER LONG WINAPI GC_write_fault_handler(
- struct _EXCEPTION_POINTERS *exc_info);
-#endif
-
-#if defined(GWW_VDB) && defined(MPROTECT_VDB)
- GC_INNER GC_bool GC_gww_dirty_init(void);
- /* Defined in os_dep.c. Returns TRUE if GetWriteWatch is available. */
- /* may be called repeatedly. */
-#endif
-
STATIC GC_bool GC_in_thread_creation = FALSE;
/* Protected by allocation lock. */
/* documentation. There is empirical evidence that it */
/* isn't. - HB */
# if defined(MPROTECT_VDB)
-# 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
+ if (GC_incremental
+# ifdef GWW_VDB
+ && !GC_gww_dirty_init()
+# endif
+ )
+ GC_set_write_fault_handler();
# endif
# ifndef GC_NO_THREADS_DISCOVERY
/* in stack (or ADDR_LIMIT if unset) */
/* for markers. */
-#endif
+#endif /* PARALLEL_MARK */
/* Find stack with the lowest address which overlaps the */
/* interval [start, limit). */