From c06769bfb05036d0ab57114d3b4568d8f743ad49 Mon Sep 17 00:00:00 2001 From: ivmai Date: Thu, 22 Oct 2009 15:00:59 +0000 Subject: [PATCH] 2009-10-22 Ivan Maidanski * alloc.c (GC_collection_in_progress): Move the prototype to gc_priv.h. * gc_dlopen.c (GC_collection_in_progress): Ditto. * pthread_support.c (GC_collection_in_progress): Ditto. * misc.c (GC_init_parallel): Ditto. * pthread_support.c (GC_init_parallel): Ditto. * win32_threads.c (GC_init_parallel): Ditto. * darwin_stop_world.c (GC_thr_init): Ditto. * misc.c (GC_thr_init): Ditto. * pthread_stop_world.c (GC_thr_init): Ditto. * pthread_support.c (GC_thr_init): Ditto. * blacklst.c (GC_clear_bl, GC_copy_bl, GC_number_stack_black_listed): Make STATIC. * dbg_mlc.c (GC_print_obj, GC_make_closure, GC_debug_invoke_finalizer): Ditto. * malloc.c (GC_alloc_large_and_clear): Ditto. * mark.c (GC_push_selected, GC_push_marked1, GC_push_marked2, GC_push_marked4, GC_push_marked, GC_push_next_marked, GC_push_next_marked_dirty, GC_push_next_marked_uncollectable): Ditto. * misc.c (GC_clear_stack_inner): Ditto. * os_dep.c (GC_repeat_read, GC_default_push_other_roots): Ditto. * darwin_stop_world.c (FindTopOfStack): Make static; define only if not DARWIN_DONT_PARSE_STACK. * dbg_mlc.c (GC_debug_free_inner): Define only if DBG_HDRS_ALL. * dyn_load.c (GC_repeat_read): Remove unused prototype. * include/private/gc_pmark.h (GC_find_start): Ditto. * misc.c (GC_read, GC_register_finalizer_no_order): Ditto. * dyn_load.c (GC_segment_is_thread_stack): Add prototype (only if THREADS). * dyn_load.c (GC_register_main_static_data): Define only if DYNAMIC_LOADING. * finalize.c (GC_enqueue_all_finalizers): Remove unnecessary tail "return" statement. * gc_dlopen.c (GC_SOLARIS_THREADS): Don't recognize (since implies GC_PTHREADS). * include/gc.h: Fix a typo. * include/gc_inline.h (GC_ASSERT): Define (if not defined) since the header is public. * include/gc_inline.h (GC_generic_malloc_many): New public function declaration. * mallocx.c (GC_generic_malloc_many): Make public. * include/private/gc_priv.h (GC_INNER): Use visibility attribute (if available). * include/private/gc_priv.h (GC_EXTERN): Define using GC_INNER. * include/private/gc_priv.h: Include atomic_ops.h if THREADS and MPROTECT_VDB. * os_dep.c: Don't include atomic_ops.h * win32_threads.c: Ditto. * include/private/gc_priv.h (GC_push_selected, GC_push_regs, GC_push_marked, GC_number_stack_black_listed, GC_alloc_large_and_clear, GC_reclaim_or_delete_all, GC_generic_malloc_many, GC_make_closure, GC_debug_invoke_finalizer, GC_print_obj, GC_page_was_ever_dirty): Remove the prototype. * mark.c (GC_page_was_ever_dirty): Add prototype (only if PROC_VDB). * include/private/gc_priv.h (GC_push_next_marked_dirty, GC_push_next_marked, GC_push_next_marked_uncollectable): Move the prototype to mark.c. * include/private/gc_priv.h (GC_is_static_root): Declare only if not THREADS. * include/private/gc_priv.h (GC_free_inner): Declare only if THREADS. * include/private/gc_priv.h (GC_debug_free_inner): Declare only if THREADS and DBG_HDRS_ALL. * include/private/gc_priv.h (GC_markers): Declare GC_markers only if PARALLEL_MARK. * include/private/gc_priv.h (GC_register_main_static_data): Move the prototype to misc.c. * mach_dep.c (GC_push_regs): Make STATIC; define only along with HAVE_PUSH_REGS definition. * mach_dep.c (GC_clear_stack_inner): Replace K&R-style function definition with the ANSI C one. * mark.c (GC_started_thread_while_stopped): Declared only if not GNU C. * win32_threads.c (GC_started_thread_while_stopped): Don't define if GNU C. * mark.c (GC_mark_from): Avoid unbalanced brackets in #if-#else-#endif blocks. * mark_rts.c (GC_is_static_root): Define only if not THREADS. * os_dep.c (GC_get_stack_base): Make public (for OpenBSD). * os_dep.c (GC_page_was_ever_dirty): Comment out the function except for PROC_VDB. * tests/test.c (main): Don't reference GC_print_obj, GC_make_closure, GC_debug_invoke_finalizer, GC_page_was_ever_dirty, GC_is_fresh (in GC_noop). * thread_local_alloc.c: Don't include "gc_inline.h". * win32_threads.c (GC_write_fault_handler): Declare only if MPROTECT_VDB. --- ChangeLog | 109 ++++++++++++++++++++-- alloc.c | 9 +- blacklst.c | 14 ++- darwin_stop_world.c | 101 ++++++++++---------- dbg_mlc.c | 119 ++++++++++++------------ dyn_load.c | 90 +++++++++--------- finalize.c | 2 - gc_dlopen.c | 8 +- include/gc.h | 8 +- include/gc_inline.h | 12 ++- include/private/gc_pmark.h | 12 +-- include/private/gc_priv.h | 227 +++++++++++++++++++-------------------------- mach_dep.c | 65 +++++++------ malloc.c | 30 +++--- mallocx.c | 18 ++-- mark.c | 101 +++++++++++--------- mark_rts.c | 88 +++++++++--------- misc.c | 119 +++++++++++------------- os_dep.c | 138 ++++++++++++--------------- pthread_stop_world.c | 18 ++-- pthread_support.c | 51 +++++----- tests/test.c | 8 +- thread_local_alloc.c | 1 - win32_threads.c | 47 +++++----- 24 files changed, 709 insertions(+), 686 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b1bae3..e579099 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,96 @@ +2009-10-22 Ivan Maidanski + + * alloc.c (GC_collection_in_progress): Move the prototype to + gc_priv.h. + * gc_dlopen.c (GC_collection_in_progress): Ditto. + * pthread_support.c (GC_collection_in_progress): Ditto. + * misc.c (GC_init_parallel): Ditto. + * pthread_support.c (GC_init_parallel): Ditto. + * win32_threads.c (GC_init_parallel): Ditto. + * darwin_stop_world.c (GC_thr_init): Ditto. + * misc.c (GC_thr_init): Ditto. + * pthread_stop_world.c (GC_thr_init): Ditto. + * pthread_support.c (GC_thr_init): Ditto. + * blacklst.c (GC_clear_bl, GC_copy_bl, + GC_number_stack_black_listed): Make STATIC. + * dbg_mlc.c (GC_print_obj, GC_make_closure, + GC_debug_invoke_finalizer): Ditto. + * malloc.c (GC_alloc_large_and_clear): Ditto. + * mark.c (GC_push_selected, GC_push_marked1, GC_push_marked2, + GC_push_marked4, GC_push_marked, GC_push_next_marked, + GC_push_next_marked_dirty, GC_push_next_marked_uncollectable): + Ditto. + * misc.c (GC_clear_stack_inner): Ditto. + * os_dep.c (GC_repeat_read, GC_default_push_other_roots): Ditto. + * darwin_stop_world.c (FindTopOfStack): Make static; define only + if not DARWIN_DONT_PARSE_STACK. + * dbg_mlc.c (GC_debug_free_inner): Define only if DBG_HDRS_ALL. + * dyn_load.c (GC_repeat_read): Remove unused prototype. + * include/private/gc_pmark.h (GC_find_start): Ditto. + * misc.c (GC_read, GC_register_finalizer_no_order): Ditto. + * dyn_load.c (GC_segment_is_thread_stack): Add prototype (only if + THREADS). + * dyn_load.c (GC_register_main_static_data): Define only if + DYNAMIC_LOADING. + * finalize.c (GC_enqueue_all_finalizers): Remove unnecessary tail + "return" statement. + * gc_dlopen.c (GC_SOLARIS_THREADS): Don't recognize (since implies + GC_PTHREADS). + * include/gc.h: Fix a typo. + * include/gc_inline.h (GC_ASSERT): Define (if not defined) since + the header is public. + * include/gc_inline.h (GC_generic_malloc_many): New public + function declaration. + * mallocx.c (GC_generic_malloc_many): Make public. + * include/private/gc_priv.h (GC_INNER): Use visibility attribute + (if available). + * include/private/gc_priv.h (GC_EXTERN): Define using GC_INNER. + * include/private/gc_priv.h: Include atomic_ops.h if THREADS and + MPROTECT_VDB. + * os_dep.c: Don't include atomic_ops.h + * win32_threads.c: Ditto. + * include/private/gc_priv.h (GC_push_selected, GC_push_regs, + GC_push_marked, GC_number_stack_black_listed, + GC_alloc_large_and_clear, GC_reclaim_or_delete_all, + GC_generic_malloc_many, GC_make_closure, + GC_debug_invoke_finalizer, GC_print_obj, GC_page_was_ever_dirty): + Remove the prototype. + * mark.c (GC_page_was_ever_dirty): Add prototype (only if + PROC_VDB). + * include/private/gc_priv.h (GC_push_next_marked_dirty, + GC_push_next_marked, GC_push_next_marked_uncollectable): Move + the prototype to mark.c. + * include/private/gc_priv.h (GC_is_static_root): Declare only if + not THREADS. + * include/private/gc_priv.h (GC_free_inner): Declare only if + THREADS. + * include/private/gc_priv.h (GC_debug_free_inner): Declare only if + THREADS and DBG_HDRS_ALL. + * include/private/gc_priv.h (GC_markers): Declare GC_markers only + if PARALLEL_MARK. + * include/private/gc_priv.h (GC_register_main_static_data): Move + the prototype to misc.c. + * mach_dep.c (GC_push_regs): Make STATIC; define only along with + HAVE_PUSH_REGS definition. + * mach_dep.c (GC_clear_stack_inner): Replace K&R-style function + definition with the ANSI C one. + * mark.c (GC_started_thread_while_stopped): Declared only if not + GNU C. + * win32_threads.c (GC_started_thread_while_stopped): Don't define + if GNU C. + * mark.c (GC_mark_from): Avoid unbalanced brackets in + #if-#else-#endif blocks. + * mark_rts.c (GC_is_static_root): Define only if not THREADS. + * os_dep.c (GC_get_stack_base): Make public (for OpenBSD). + * os_dep.c (GC_page_was_ever_dirty): Comment out the function + except for PROC_VDB. + * tests/test.c (main): Don't reference GC_print_obj, + GC_make_closure, GC_debug_invoke_finalizer, + GC_page_was_ever_dirty, GC_is_fresh (in GC_noop). + * thread_local_alloc.c: Don't include "gc_inline.h". + * win32_threads.c (GC_write_fault_handler): Declare only if + MPROTECT_VDB. + 2009-10-21 Ivan Maidanski * allchblk.c (DEBUG): Remove macro (since unused). @@ -2318,7 +2411,7 @@ between blocks. (GC_split_block): Remove dead code setting hb_flags. Add comment. (GC_allochblk): Split blocks also in generational-only mode. - * os_dep.c (GC_unmap_gap): Dont really use munmap. + * os_dep.c (GC_unmap_gap): Don't really use munmap. 2009-08-08 Hans Boehm (Really Ivan Maidanski) (Mistakenly omitted from last check-in) @@ -2866,7 +2959,7 @@ (before closing "extern C"). * pthread_support.c: Fix out of memory handling for Thread_Reps. * win32_threads.c: Don't include process.h on winCE, - improve out of memory handling for thread structures, dont + improve out of memory handling for thread structures, don't define GC_beginthreadex and GC_endthreadex for winCE. 2009-05-22 Hans Boehm (Really Ivan Maidanski @@ -2880,7 +2973,7 @@ * gcj_mlc.c: Add comment. * tests/test.c: Change NTEST to NTHREADS. Fork 5 threads by default. Run reverse_test a second time in each thread.Add comments. - Dont rely on AO_fetch_and_add. + Don't rely on AO_fetch_and_add. 2009-05-22 Hans Boehm (Largely from Ludovic Cortes) @@ -3028,7 +3121,7 @@ * include/private/gcconfig.h: Add FIXME comment. * tests/test.c (run_ine_test): Replace LOCK/UNLOCK use with AO_fetch_and_add1_full. Declare n_tests as AO_t. - (WinMain): Dont call GC_use_DllMain. + (WinMain): Don't call GC_use_DllMain. with PARALLEL_MARK or THREAD_LOCAL_ALLOC. 2008-11-10 Hans Boehm (Really Ivan Maidansky) @@ -3182,7 +3275,7 @@ * win32_threads.c (GC_pthread_join, GC_pthread_start_inner): Remove unused variables. * darwin_stop_world.c: Always declare GC_thr_init(). - * dbg_mlc.c (GC_debug_free_inner): Dont touch oh_sz if + * dbg_mlc.c (GC_debug_free_inner): Don't touch oh_sz if SHORT_DBG_HDRS is defined. * include/private/gc_pmark.h (OR_WORD_EXIT_IF_SET, parallel mark, USE_MARK_BITS version): Refer to correct parameter name. @@ -3552,7 +3645,7 @@ * configure.ac: Put libatomic_ops links in build directory. * configure: Regenerate. - * Makefile.am: Dont mention atomic_ops.c and atomic_ops_sysdeps.S + * Makefile.am: Don't mention atomic_ops.c and atomic_ops_sysdeps.S as nodist sources. 2007-12-20 Hans Boehm @@ -3785,7 +3878,7 @@ * Makefile.am, Makefile.direct: Add NT_X64_STATIC_THREADS_MAKEFILE. * Makefile.in: Regenerate. * NT_X64_STATIC_THREADS_MAKEFILE: Fix warning flags. - * allochblk.c, alloc.c, blacklst.c, dbg_malc.c, dyn_load.c, + * allochblk.c, alloc.c, blacklst.c, dbg_mlc.c, dyn_load.c, finalize.c, headers.c, mach_dep.c, malloc.c, mark.c, misc.c, obj_map.c, os_dep.c, ptr_chck.c, reclaim.c, typd_mlc.c, win32_threads.c, cord/de_win.c, include/gc_mark.h, @@ -3927,7 +4020,7 @@ 2007-05-08 Hans Boehm - * Makefile.am: Dont distribute copied atomic_ops files. Include + * Makefile.am: Don't distribute copied atomic_ops files. Include libatomic_ops with "make dist". * Makefile.in: Regenerate. * configure: Regenerate. diff --git a/alloc.c b/alloc.c index 5756ce3..7c4b8ee 100644 --- a/alloc.c +++ b/alloc.c @@ -44,7 +44,7 @@ */ /* - * The allocator uses GC_allochblk to allocate large chunks of objects. + * The allocator uses GC_allochblk to allocate large chunks of objects. * These chunks all start on addresses which are multiples of * HBLKSZ. Each allocated chunk has an associated header, * which can be located quickly based on the address of the chunk. @@ -118,9 +118,6 @@ GC_API unsigned GC_CALL GC_get_version(void) word GC_free_space_divisor = GC_FREE_SPACE_DIVISOR; -GC_bool GC_collection_in_progress(void); - /* Collection is in progress, or was abandoned. */ - int GC_CALLBACK GC_never_stop_func(void) { return(0); @@ -1281,8 +1278,8 @@ ptr_t GC_allocobj(size_t gran, int kind) ENTER_GC(); if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED && !tried_minor) { - GC_collect_a_little_inner(1); - tried_minor = TRUE; + GC_collect_a_little_inner(1); + tried_minor = TRUE; } else { if (!GC_collect_or_expand(1, FALSE, retry)) { EXIT_GC(); diff --git a/blacklst.c b/blacklst.c index d0dcf45..80583a4 100644 --- a/blacklst.c +++ b/blacklst.c @@ -52,12 +52,11 @@ STATIC word GC_total_stack_black_listed = 0; GC_INNER word GC_black_list_spacing = MINHINCR * HBLKSIZE; /* Initial rough guess. */ -void GC_clear_bl(word *); +STATIC void GC_clear_bl(word *); void GC_default_print_heap_obj_proc(ptr_t p) { ptr_t base = GC_base(p); - GC_err_printf("start: %p, appr. length: %ld", base, (unsigned long)GC_size(base)); } @@ -109,12 +108,12 @@ void GC_bl_init(void) GC_clear_bl(GC_incomplete_stack_bl); } -void GC_clear_bl(word *doomed) +STATIC void GC_clear_bl(word *doomed) { BZERO(doomed, sizeof(page_hash_table)); } -void GC_copy_bl(word *old, word *new) +STATIC void GC_copy_bl(word *old, word *new) { BCOPY(old, new, sizeof(page_hash_table)); } @@ -237,7 +236,7 @@ struct hblk * GC_is_black_listed(struct hblk *h, word len) } } - for (i = 0; ; ) { + for (i = 0;;) { if (GC_old_stack_bl[divWORDSZ(index)] == 0 && GC_incomplete_stack_bl[divWORDSZ(index)] == 0) { /* An easy case */ @@ -255,11 +254,11 @@ struct hblk * GC_is_black_listed(struct hblk *h, word len) return(0); } - /* Return the number of blacklisted blocks in a given range. */ /* Used only for statistical purposes. */ /* Looks only at the GC_incomplete_stack_bl. */ -word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1) +STATIC word GC_number_stack_black_listed(struct hblk *start, + struct hblk *endp1) { register struct hblk * h; word result = 0; @@ -272,7 +271,6 @@ word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1) return(result); } - /* Return the total number of (stack) black-listed bytes. */ static word total_stack_black_listed(void) { diff --git a/darwin_stop_world.c b/darwin_stop_world.c index b39ef5f..d6a745e 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -39,58 +39,6 @@ # endif #endif -typedef struct StackFrame { - unsigned long savedSP; - unsigned long savedCR; - unsigned long savedLR; - unsigned long reserved[2]; - unsigned long savedRTOC; -} StackFrame; - -unsigned long FindTopOfStack(unsigned long stack_start) -{ - StackFrame *frame; - - if (stack_start == 0) { -# ifdef POWERPC -# if CPP_WORDSZ == 32 - __asm__ volatile("lwz %0,0(r1)" : "=r" (frame)); -# else - __asm__ volatile("ld %0,0(r1)" : "=r" (frame)); -# endif -# endif - } else { - frame = (StackFrame *)stack_start; - } - -# ifdef DEBUG_THREADS - /* GC_printf("FindTopOfStack start at sp = %p\n", frame); */ -# endif - do { - if (frame->savedSP == 0) - break; - /* if there are no more stack frames, stop */ - - frame = (StackFrame*)frame->savedSP; - - /* we do these next two checks after going to the next frame - because the LR for the first stack frame in the loop - is not set up on purpose, so we shouldn't check it. */ - if ((frame->savedLR & ~3) == 0) - break; /* if the next LR is bogus, stop */ - if ((~(frame->savedLR) & ~3) == 0) - break; /* ditto */ - } while (1); - -# ifdef DEBUG_THREADS - /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */ -# endif - - return (unsigned long)frame; -} - -void GC_thr_init(void); - #ifdef DARWIN_DONT_PARSE_STACK void GC_push_all_stacks(void) @@ -236,6 +184,55 @@ void GC_push_all_stacks(void) #else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */ +typedef struct StackFrame { + unsigned long savedSP; + unsigned long savedCR; + unsigned long savedLR; + unsigned long reserved[2]; + unsigned long savedRTOC; +} StackFrame; + +static unsigned long FindTopOfStack(unsigned long stack_start) +{ + StackFrame *frame; + + if (stack_start == 0) { +# ifdef POWERPC +# if CPP_WORDSZ == 32 + __asm__ volatile("lwz %0,0(r1)" : "=r" (frame)); +# else + __asm__ volatile("ld %0,0(r1)" : "=r" (frame)); +# endif +# endif + } else { + frame = (StackFrame *)stack_start; + } + +# ifdef DEBUG_THREADS + /* GC_printf("FindTopOfStack start at sp = %p\n", frame); */ +# endif + do { + if (frame->savedSP == 0) + break; + /* if there are no more stack frames, stop */ + + frame = (StackFrame*)frame->savedSP; + + /* we do these next two checks after going to the next frame + because the LR for the first stack frame in the loop + is not set up on purpose, so we shouldn't check it. */ + if ((frame->savedLR & ~3) == 0) + break; /* if the next LR is bogus, stop */ + if ((~(frame->savedLR) & ~3) == 0) + break; /* ditto */ + } while (1); + +# ifdef DEBUG_THREADS + /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */ +# endif + return (unsigned long)frame; +} + void GC_push_all_stacks(void) { unsigned int i; diff --git a/dbg_mlc.c b/dbg_mlc.c index bbcb44f..9f8f2c1 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -23,23 +23,23 @@ #include void GC_default_print_heap_obj_proc(ptr_t p); -GC_API void GC_CALL GC_register_finalizer_no_order - (void * obj, GC_finalization_proc fn, void * cd, - GC_finalization_proc *ofn, void * *ocd); +GC_API void GC_CALL GC_register_finalizer_no_order(void * obj, + GC_finalization_proc fn, void * cd, + GC_finalization_proc *ofn, void * *ocd); #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 */ -/* of the heap. */ -/* This excludes the check as to whether the back pointer is */ -/* odd, which is added by the GC_HAS_DEBUG_INFO macro. */ -/* Note that if DBG_HDRS_ALL is set, uncollectable objects */ -/* on free lists may not have debug information set. Thus it's */ -/* not always safe to return TRUE, even if the client does */ -/* its part. */ -GC_bool GC_has_other_debug_info(ptr_t p) -{ + /* Check whether object with base pointer p has debugging info */ + /* p is assumed to point to a legitimate object in our part */ + /* of the heap. */ + /* This excludes the check as to whether the back pointer is */ + /* odd, which is added by the GC_HAS_DEBUG_INFO macro. */ + /* Note that if DBG_HDRS_ALL is set, uncollectable objects */ + /* on free lists may not have debug information set. Thus it's */ + /* not always safe to return TRUE, even if the client does */ + /* its part. */ + GC_bool GC_has_other_debug_info(ptr_t p) + { oh * ohdr = (oh *)p; ptr_t body = (ptr_t)(ohdr + 1); word sz = GC_size((ptr_t) ohdr); @@ -57,7 +57,7 @@ GC_bool GC_has_other_debug_info(ptr_t p) return(TRUE); } return(FALSE); -} + } #endif #ifdef KEEP_BACK_PTRS @@ -305,11 +305,11 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string, #endif #ifndef SHORT_DBG_HDRS -/* Check the object with debugging info at ohdr */ -/* return NIL if it's OK. Else return clobbered */ -/* address. */ -STATIC ptr_t GC_check_annotated_obj(oh *ohdr) -{ + /* Check the object with debugging info at ohdr */ + /* return NIL if it's OK. Else return clobbered */ + /* address. */ + STATIC ptr_t GC_check_annotated_obj(oh *ohdr) + { ptr_t body = (ptr_t)(ohdr + 1); word gc_sz = GC_size((ptr_t)ohdr); if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) { @@ -323,10 +323,10 @@ STATIC ptr_t GC_check_annotated_obj(oh *ohdr) } if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)] != (END_FLAG ^ (word)body)) { - return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz))); + return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr->oh_sz))); } return(0); -} + } #endif /* !SHORT_DBG_HDRS */ STATIC GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0}; @@ -378,7 +378,9 @@ STATIC void GC_print_type(ptr_t p) } } -void GC_print_obj(ptr_t p) +/* Print a human-readable description of the object to stderr. p points */ +/* to somewhere inside an object with the debugging info. */ +STATIC void GC_print_obj(ptr_t p) { oh * ohdr = (oh *)GC_base(p); @@ -407,11 +409,11 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) } #ifndef SHORT_DBG_HDRS -/* Use GC_err_printf and friends to print a description of the object */ -/* whose client-visible address is p, and which was smashed at */ -/* clobbered_addr. */ -STATIC void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr) -{ + /* Use GC_err_printf and friends to print a description of the object */ + /* whose client-visible address is p, and which was smashed at */ + /* clobbered_addr. */ + STATIC void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr) + { oh * ohdr = (oh *)GC_base(p); GC_ASSERT(I_DONT_HOLD_LOCK()); @@ -431,7 +433,7 @@ STATIC void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr) (unsigned long)(ohdr -> oh_sz)); PRINT_CALL_CHAIN(ohdr); } -} + } #endif #ifndef SHORT_DBG_HDRS @@ -519,15 +521,15 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, return (GC_store_debug_info(result, (word)lb, s, (word)i)); } -# ifdef DBG_HDRS_ALL -/* - * An allocation function for internal use. - * Normally internally allocated objects do not have debug information. - * But in this case, we need to make sure that all objects have debug - * headers. - * We assume debugging was started in collector initialization, - * and we already hold the GC lock. - */ +#ifdef DBG_HDRS_ALL + /* + * An allocation function for internal use. + * Normally internally allocated objects do not have debug information. + * But in this case, we need to make sure that all objects have debug + * headers. + * We assume debugging was started in collector initialization, + * and we already hold the GC lock. + */ void * GC_debug_generic_malloc_inner(size_t lb, int k) { void * result = GC_generic_malloc_inner(lb + DEBUG_BYTES, k); @@ -554,7 +556,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, ADD_CALL_CHAIN(result, GC_RETURN_ADDR); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } -# endif +#endif #ifdef STUBBORN_ALLOC GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) @@ -617,14 +619,10 @@ GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) } /*ARGSUSED*/ -GC_API void GC_CALL GC_debug_change_stubborn(void *p) -{ -} +GC_API void GC_CALL GC_debug_change_stubborn(void *p) {} /*ARGSUSED*/ -GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) -{ -} +GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) {} #endif /* !STUBBORN_ALLOC */ @@ -687,8 +685,8 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS) } #ifdef ATOMIC_UNCOLLECTABLE -void * GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS) -{ + void * GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS) + { void * result = GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); @@ -705,7 +703,7 @@ void * GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS) } ADD_CALL_CHAIN(result, ra); return (GC_store_debug_info(result, (word)lb, s, (word)i)); -} + } #endif /* ATOMIC_UNCOLLECTABLE */ GC_API void GC_CALL GC_debug_free(void * p) @@ -766,13 +764,10 @@ GC_API void GC_CALL GC_debug_free(void * p) } /* !GC_find_leak */ } -#ifdef THREADS - -void GC_free_inner(void * p); - -/* Used internally; we assume it's called correctly. */ -void GC_debug_free_inner(void * p) -{ +#if defined(THREADS) && defined(DBG_HDRS_ALL) + /* Used internally; we assume it's called correctly. */ + void GC_debug_free_inner(void * p) + { ptr_t base = GC_base(p); GC_ASSERT((ptr_t)p - (ptr_t)base == sizeof(oh)); # ifndef SHORT_DBG_HDRS @@ -780,7 +775,7 @@ void GC_debug_free_inner(void * p) ((oh *)base) -> oh_sz = GC_size(base); # endif GC_free_inner(base); -} + } #endif GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) @@ -914,7 +909,6 @@ STATIC void GC_check_heap_block(struct hblk *hbp, word dummy) } } - /* This assumes that all accessible objects are marked, and that */ /* I hold the allocation lock. Normally called by collector. */ STATIC void GC_check_heap_proc(void) @@ -933,7 +927,7 @@ struct closure { void * cl_data; }; -void * GC_make_closure(GC_finalization_proc fn, void * data) +STATIC void * GC_make_closure(GC_finalization_proc fn, void * data) { struct closure * result = # ifdef DBG_HDRS_ALL @@ -948,10 +942,11 @@ void * GC_make_closure(GC_finalization_proc fn, void * data) return((void *)result); } -void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data) +/* An auxiliary fns to make finalization work correctly with displaced */ +/* pointers introduced by the debugging allocators. */ +STATIC void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data) { struct closure * cl = (struct closure *) data; - (*(cl -> cl_fn))((void *)((char *)obj + sizeof(oh)), cl -> cl_data); } @@ -1093,8 +1088,8 @@ GC_API void GC_CALL GC_debug_register_finalizer_ignore_self GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd); } else { GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, - GC_make_closure(fn,cd), &my_old_fn, - &my_old_cd); + GC_make_closure(fn,cd), &my_old_fn, + &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); } diff --git a/dyn_load.c b/dyn_load.c index 73f9ac6..89edcaf 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -130,7 +130,7 @@ GC_FirstDLOpenedLinkMap(void) struct r_debug *r; static struct link_map * cachedResult = 0; static ElfW(Dyn) *dynStructureAddr = 0; - /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */ + /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */ # ifdef SUNOS53_SHARED_LIB /* BTL: Avoid the Solaris 5.3 bug that _DYNAMIC isn't being set */ @@ -230,15 +230,10 @@ void GC_register_dynamic_libraries(void) #define MAPS_BUF_SIZE (32*1024) -ssize_t GC_repeat_read(int fd, char *buf, size_t count); - /* Repeatedly read until buffer is filled, or EOF is encountered */ - /* Defined in os_dep.c. */ - char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, - char **prot, unsigned int *maj_dev, - char **mapping_name); -char *GC_get_maps(void); - /* From os_dep.c */ + char **prot, unsigned int *maj_dev, + char **mapping_name); +char *GC_get_maps(void); /* from os_dep.c */ /* Sort an array of HeapSects by start address. */ /* Unfortunately at least some versions of */ @@ -270,6 +265,10 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements) } } +#ifdef THREADS + GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi); +#endif + STATIC word GC_register_map_entries(char *maps) { char *prot; @@ -288,7 +287,8 @@ STATIC word GC_register_map_entries(char *maps) + GC_our_memory[GC_n_memory-1].hs_bytes; for (;;) { - buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, &maj_dev, 0); + buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, + &maj_dev, 0); if (buf_ptr == NULL) return 1; if (prot[1] == 'w') { /* This is a writable mapping. Add it to */ @@ -329,7 +329,7 @@ STATIC word GC_register_map_entries(char *maps) GC_add_roots_inner((char *)start, (char *)end, TRUE); continue; } - /* Add sections that dont belong to us. */ + /* Add sections that don't belong to us. */ i = 0; while (GC_our_memory[i].hs_start + GC_our_memory[i].hs_bytes < start) @@ -606,7 +606,6 @@ GC_FirstDLOpenedLinkMap(void) return cachedResult; } - void GC_register_dynamic_libraries(void) { struct link_map *lm; @@ -665,7 +664,6 @@ 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. */ @@ -703,8 +701,8 @@ void GC_register_dynamic_libraries(void) if (needed_sz >= current_sz) { current_sz = needed_sz * 2 + 1; /* Expansion, plus room for 0 record */ - addr_map = (prmap_t *)GC_scratch_alloc((word) - (current_sz * sizeof(prmap_t))); + addr_map = (prmap_t *)GC_scratch_alloc( + (word)current_sz * sizeof(prmap_t)); } if (ioctl(fd, PIOCMAP, addr_map) < 0) { GC_err_printf("fd = %d, errno = %d, needed_sz = %d, addr_map = %p\n", @@ -772,8 +770,8 @@ void GC_register_dynamic_libraries(void) GC_add_roots_inner(start, limit, TRUE); irrelevant: ; } - /* Dont keep cached descriptor, for now. Some kernels don't like us */ - /* to keep a /proc file descriptor around during kill -9. */ + /* Don't keep cached descriptor, for now. Some kernels don't like us */ + /* to keep a /proc file descriptor around during kill -9. */ if (close(fd) < 0) ABORT("Couldnt close /proc file"); fd = -1; } @@ -826,17 +824,19 @@ void GC_register_dynamic_libraries(void) } # endif -GC_bool GC_register_main_static_data(void) -{ -# ifdef MSWINCE - /* Do we need to separately register the main static data segment? */ - return FALSE; -# else - return GC_no_win32_dlls; -# endif -} +#ifdef DYNAMIC_LOADING + GC_bool GC_register_main_static_data(void) + { +# ifdef MSWINCE + /* Do we need to separately register the main static data segment? */ + return FALSE; +# else + return GC_no_win32_dlls; +# endif + } +#endif /* DYNAMIC_LOADING */ -# define HAVE_REGISTER_MAIN_STATIC_DATA +#define HAVE_REGISTER_MAIN_STATIC_DATA # ifdef DEBUG_VIRTUALQUERY void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf) @@ -1090,11 +1090,11 @@ void GC_register_dynamic_libraries(void) #endif /* HPUX */ #ifdef AIX -#pragma alloca -#include -#include -void GC_register_dynamic_libraries(void) -{ +# pragma alloca +# include +# include + void GC_register_dynamic_libraries(void) + { int len; char *ldibuf; int ldibuflen; @@ -1119,7 +1119,7 @@ void GC_register_dynamic_libraries(void) TRUE); ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; } -} + } #endif /* AIX */ #ifdef DARWIN @@ -1281,12 +1281,12 @@ GC_bool GC_register_main_static_data(void) #ifdef PCR -# include "il/PCR_IL.h" -# include "th/PCR_ThCtl.h" -# include "mm/PCR_MM.h" +# include "il/PCR_IL.h" +# include "th/PCR_ThCtl.h" +# include "mm/PCR_MM.h" -void GC_register_dynamic_libraries(void) -{ + void GC_register_dynamic_libraries(void) + { /* Add new static data areas of dynamically loaded modules. */ { PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile(); @@ -1313,7 +1313,7 @@ void GC_register_dynamic_libraries(void) } } } -} + } #else /* !PCR */ @@ -1324,13 +1324,11 @@ void GC_register_dynamic_libraries(void) {} #endif /* !DYNAMIC_LOADING */ #ifndef HAVE_REGISTER_MAIN_STATIC_DATA - -/* Do we need to separately register the main static data segment? */ -GC_bool GC_register_main_static_data(void) -{ - return TRUE; -} - + /* Do we need to separately register the main static data segment? */ + GC_bool GC_register_main_static_data(void) + { + return TRUE; + } #endif /* HAVE_REGISTER_MAIN_STATIC_DATA */ /* Register a routine to filter dynamic library registration. */ diff --git a/finalize.c b/finalize.c index 0647590..8367053 100644 --- a/finalize.c +++ b/finalize.c @@ -743,8 +743,6 @@ void GC_finalize(void) curr_fo = next_fo; } } - - return; } /* Invoke all remaining finalizers that haven't yet been run. diff --git a/gc_dlopen.c b/gc_dlopen.c index 216838b..3e0b1a3 100644 --- a/gc_dlopen.c +++ b/gc_dlopen.c @@ -25,8 +25,8 @@ * library. -HB */ -# if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) && !defined(GC_WIN32_PTHREADS)\ - || defined(GC_SOLARIS_THREADS) +# if defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS) \ + && !defined(GC_WIN32_PTHREADS) # undef GC_MUST_RESTORE_REDEFINED_DLOPEN # if defined(dlopen) && !defined(GC_USE_LD_WRAP) @@ -39,8 +39,6 @@ # define GC_MUST_RESTORE_REDEFINED_DLOPEN # endif - GC_bool GC_collection_in_progress(void); - /* Make sure we're not in the middle of a collection, and make */ /* sure we don't start any. Returns previous value of GC_dont_gc. */ /* This is invoked prior to a dlopen call to avoid synchronization */ @@ -103,4 +101,4 @@ GC_API void * WRAP_DLFUNC(dlopen)(const char *path, int mode) # define dlopen GC_dlopen # endif -#endif /* GC_PTHREADS || GC_SOLARIS_THREADS ... */ +#endif /* GC_PTHREADS */ diff --git a/include/gc.h b/include/gc.h index b5009a0..6923c53 100644 --- a/include/gc.h +++ b/include/gc.h @@ -175,7 +175,7 @@ GC_API GC_finalizer_notifier_proc GC_finalizer_notifier; GC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc); GC_API GC_finalizer_notifier_proc GC_CALL GC_get_finalizer_notifier(void); -GC_API int GC_dont_gc; /* != 0 ==> Dont collect. In versions 6.2a1+, */ +GC_API int GC_dont_gc; /* != 0 ==> Don't collect. In versions 6.2a1+, */ /* this overrides explicit GC_gcollect() calls. */ /* Used as a counter, so that nested enabling */ /* and disabling work correctly. Should */ @@ -185,9 +185,9 @@ GC_API int GC_dont_gc; /* != 0 ==> Dont collect. In versions 6.2a1+, */ /* deprecated. */ GC_API int GC_dont_expand; - /* Dont expand heap unless explicitly requested */ - /* or forced to. */ - /* The setter and getter are unsynchronized, so */ + /* Don't expand the heap unless explicitly */ + /* requested or forced to. The setter and */ + /* getter are unsynchronized, so */ /* GC_call_with_alloc_lock() is required to */ /* avoid data races (if the value is modified */ /* after the GC is put to multi-threaded mode). */ diff --git a/include/gc_inline.h b/include/gc_inline.h index 4b8e3b5..312ed61 100644 --- a/include/gc_inline.h +++ b/include/gc_inline.h @@ -38,6 +38,16 @@ # define GC_EXPECT(expr, outcome) (expr) #endif /* __GNUC__ */ +#ifndef GC_ASSERT +# define GC_ASSERT(expr) /* empty */ +#endif + +/* Store a pointer to a list of newly allocated objects of kind k and */ +/* size lb in *result. The caller must make sure that *result is */ +/* traced even if objects are ptrfree. */ +GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, + void ** /* result */); + /* The ultimately general inline allocation macro. Allocate an object */ /* of size granules, putting the resulting pointer in result. Tiny_fl */ /* is a "tiny" free list array, which will be used first, if the size */ @@ -77,7 +87,7 @@ } else { \ /* Large counter or NULL */ \ GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \ - GC_RAW_BYTES_FROM_INDEX(granules)), \ + GC_RAW_BYTES_FROM_INDEX(granules)), \ kind, my_fl); \ my_entry = *my_fl; \ if (my_entry == 0) { \ diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index 83aa2ea..22bc08a 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -129,10 +129,6 @@ GC_EXTERN mse * GC_mark_stack; */ #endif /* PARALLEL_MARK */ -/* Return a pointer to within 1st page of object. */ -/* Set *new_hdr_p to corr. hdr. */ -ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p); - mse * GC_signal_mark_stack_overflow(mse *msp); /* Push the object obj with corresponding heap block header hhdr onto */ @@ -275,7 +271,6 @@ exit_label: ; \ GC_ASSERT(obj_displ < hhdr -> hb_sz); \ /* Must be in all_interior_pointer case, not first block */ \ /* already did validity check on cache miss. */ \ - ; \ } else { \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ @@ -305,8 +300,8 @@ exit_label: ; \ TRACE(source, GC_log_printf("GC:%u: previously unmarked\n", \ (unsigned)GC_gc_no)); \ TRACE_TARGET(base, \ - GC_log_printf("GC:%u: marking %p from %p instead\n", (unsigned)GC_gc_no, \ - base, source)); \ + GC_log_printf("GC:%u: marking %p from %p instead\n", \ + (unsigned)GC_gc_no, base, source)); \ INCR_MARKS(hhdr); \ GC_STORE_BACK_PTR((ptr_t)source, base); \ PUSH_OBJ(base, hhdr, mark_stack_top, mark_stack_limit); \ @@ -333,7 +328,6 @@ exit_label: ; \ GC_ASSERT(obj_displ < hhdr -> hb_sz); \ /* Must be in all_interior_pointer case, not first block */ \ /* already did validity check on cache miss. */ \ - ; \ } else { \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ @@ -346,7 +340,7 @@ exit_label: ; \ } else { \ /* Accurate enough if HBLKSIZE <= 2**15. */ \ GC_STATIC_ASSERT(HBLKSIZE <= (1 << 15)); \ - size_t obj_displ = (((low_prod >> 16) + 1) * (hhdr -> hb_sz)) >> 16; \ + size_t obj_displ = (((low_prod >> 16) + 1) * (hhdr->hb_sz)) >> 16; \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ goto exit_label; \ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index a573d5a..cbe39bb 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -90,33 +90,31 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # include "gcconfig.h" #endif -#ifndef GC_EXTERN - /* Used only for the GC-scope variables (prefixed with "GC_") */ - /* declared in the header files. Must not be used for thread-local */ - /* variables. Must not be used in gcconfig.h. Shouldn't be used for */ - /* the debugging-only or profiling-only variables. Currently, not */ - /* used for the variables accessed from the "dated" source files */ - /* (pcr_interface.c, specific.c/h, and in the "extra" folder). */ - /* The corresponding variable definition must start with GC_INNER. */ +#ifndef GC_INNER + /* This tagging macro must be used at the start of every variable */ + /* definition which is declared with GC_EXTERN. */ # if defined(GC_DLL) && defined(__GNUC__) && !defined(MSWIN32) \ && !defined(MSWINCE) # if __GNUC__ >= 4 /* See the corresponding GC_API definition. */ -# define GC_EXTERN extern __attribute__((__visibility__("hidden"))) +# define GC_INNER __attribute__((__visibility__("hidden"))) # else /* The attribute is unsupported. */ -# define GC_EXTERN extern +# define GC_INNER /* empty */ # endif # else -# define GC_EXTERN extern +# define GC_INNER /* empty */ # endif -#endif -#ifndef GC_INNER - /* This tagging macro must be used at the start of every variable */ - /* definition which is declared with GC_EXTERN. */ -# define GC_INNER /* empty */ -#endif +# define GC_EXTERN extern GC_INNER + /* Used only for the GC-scope variables (prefixed with "GC_") */ + /* declared in the header files. Must not be used for thread-local */ + /* variables. Must not be used in gcconfig.h. Shouldn't be used for */ + /* the debugging-only or profiling-only variables. Currently, not */ + /* used for the variables accessed from the "dated" source files */ + /* (pcr_interface.c, specific.c/h, and in the "extra" folder). */ + /* The corresponding variable definition must start with GC_INNER. */ +#endif /* !GC_INNER */ #ifndef HEADERS_H # include "gc_hdrs.h" @@ -264,13 +262,10 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ #endif #ifdef SAVE_CALL_CHAIN - -/* Fill in the pc and argument information for up to NFRAMES of my */ -/* callers. Ignore my frame and my callers frame. */ -void GC_save_callers(struct callinfo info[NFRAMES]); - -void GC_print_callers(struct callinfo info[NFRAMES]); - + /* Fill in the pc and argument information for up to NFRAMES of my */ + /* callers. Ignore my frame and my callers frame. */ + void GC_save_callers(struct callinfo info[NFRAMES]); + void GC_print_callers(struct callinfo info[NFRAMES]); #endif @@ -552,7 +547,7 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; #define SIGNB ((word)1 << (WORDSZ-1)) #define BYTES_PER_WORD ((word)(sizeof (word))) #define ONES ((word)(signed_word)(-1)) -#define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */ +#define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */ #if GRANULE_BYTES == 8 # define BYTES_TO_GRANULES(n) ((n)>>3) @@ -676,7 +671,6 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define MIN_WORDS 2 /* FIXME: obsolete */ # endif - /* * Hash table representation of sets of pages. * Implements a map from aligned HBLKSIZE chunks of the address space to one @@ -766,6 +760,9 @@ typedef word page_hash_table[PHT_SIZE]; typedef AO_t counter_t; #else typedef size_t counter_t; +# if defined(THREADS) && defined(MPROTECT_VDB) +# include "atomic_ops.h" +# endif #endif /* We maintain layout maps for heap blocks containing objects of a given */ @@ -1065,8 +1062,8 @@ struct _GC_arrays { # endif # if defined(PROC_VDB) || defined(MPROTECT_VDB) || \ defined(GWW_VDB) || defined(MANUAL_VDB) - page_hash_table _grungy_pages; /* Pages that were dirty at last */ - /* GC_read_dirty. */ + page_hash_table _grungy_pages; /* Pages that were dirty at last */ + /* GC_read_dirty. */ # endif # if defined(MPROTECT_VDB) || defined(MANUAL_VDB) volatile page_hash_table _dirty_pages; @@ -1348,8 +1345,8 @@ struct GC_activation_frame_s { #ifdef IA64 /* Similar to GC_push_all_stack_frames() but for IA-64 registers store. */ - void GC_push_all_register_frames(ptr_t bs_lo, ptr_t bs_hi, int eager, - struct GC_activation_frame_s *activation_frame); + void GC_push_all_register_frames(ptr_t bs_lo, ptr_t bs_hi, + int eager, struct GC_activation_frame_s *activation_frame); #endif /* Marks are in a reserved area in */ @@ -1404,7 +1401,7 @@ struct GC_activation_frame_s { # define IF_PER_OBJ(x) # define FINAL_MARK_BIT(sz) \ ((sz) > MAXOBJBYTES? MARK_BITS_PER_HBLK \ - : BYTES_TO_GRANULES(sz * HBLK_OBJS(sz))) + : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) #endif /* Important internal collector routines */ @@ -1424,13 +1421,13 @@ struct hblk * GC_prev_block(struct hblk * h); /* is managed by GC, but may or may not be in */ /* use. */ void GC_mark_init(void); -void GC_clear_marks(void); /* Clear mark bits for all heap objects. */ +void GC_clear_marks(void); + /* Clear mark bits for all heap objects. */ void GC_invalidate_mark_state(void); - /* Tell the marker that marked */ - /* objects may point to unmarked */ - /* ones, and roots may point to */ - /* unmarked objects. */ - /* Reset mark stack. */ + /* Tell the marker that marked */ + /* objects may point to unmarked */ + /* ones, and roots may point to */ + /* unmarked objects. Reset mark stack. */ GC_bool GC_mark_stack_empty(void); GC_bool GC_mark_some(ptr_t cold_gc_frame); /* Perform about one pages worth of marking */ @@ -1442,14 +1439,13 @@ void GC_initiate_gc(void); /* If the mark state is invalid, this */ /* becomes full collection. Otherwise */ /* it's partial. */ + +GC_bool GC_collection_in_progress(void); + /* Collection is in progress, or was abandoned. */ + void GC_push_all(ptr_t bottom, ptr_t top); /* Push everything in a range */ /* onto mark stack. */ -void GC_push_selected(ptr_t bottom, ptr_t top, - int (*dirty_fn) (struct hblk *h), - void (*push_fn) (ptr_t bottom, ptr_t top)); - /* Push all pages h in [b,t) s.t. */ - /* select_fn(h) != 0 onto mark stack. */ #ifndef SMALL_CONFIG void GC_push_conditional(ptr_t b, ptr_t t, GC_bool all); #else @@ -1473,7 +1469,8 @@ void GC_push_all_eager(ptr_t b, ptr_t t); /* is thread-package-specific. */ void GC_push_roots(GC_bool all, ptr_t cold_gc_frame); - /* Push all or dirty roots. */ + /* Push all or dirty roots. */ + GC_EXTERN void (*GC_push_other_roots)(void); /* Push system or application specific roots */ /* onto the mark stack. In some environments */ @@ -1490,20 +1487,18 @@ GC_EXTERN void (*GC_push_typed_structures)(void); /* A pointer such that we can avoid linking in */ /* the typed allocation support if unused. */ -void GC_push_regs(void); - void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), ptr_t arg); -# if defined(SPARC) || defined(IA64) +#if defined(SPARC) || defined(IA64) /* Cause all stacked registers to be saved in memory. Return a */ /* pointer to the top of the corresponding memory stack. */ ptr_t GC_save_regs_in_stack(void); -# endif +#endif /* Push register contents onto mark stack. */ -# if defined(MSWIN32) || defined(MSWINCE) +#if defined(MSWIN32) || defined(MSWINCE) void __cdecl GC_push_one(word p); -# else +#else void GC_push_one(word p); /* If p points to an object, mark it */ /* and push contents on the mark stack */ @@ -1511,27 +1506,15 @@ void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), ptr_t arg); /* accepts interior pointers, i.e. this */ /* is appropriate for pointers found on */ /* stack. */ -# endif -# if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS) +#endif + +#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS) void GC_mark_and_push_stack(ptr_t p, ptr_t source); /* Ditto, omits plausibility test */ -# else - void GC_mark_and_push_stack(ptr_t p); -# endif -void GC_push_marked(struct hblk * h, hdr * hhdr); - /* Push contents of all marked objects in h onto */ - /* mark stack. */ -#ifdef SMALL_CONFIG -# define GC_push_next_marked_dirty(h) GC_push_next_marked(h) #else - struct hblk * GC_push_next_marked_dirty(struct hblk * h); - /* Invoke GC_push_marked on next dirty block above h. */ - /* Return a pointer just past the end of this block. */ -#endif /* !SMALL_CONFIG */ -struct hblk * GC_push_next_marked(struct hblk * h); - /* Ditto, but also mark from clean pages. */ -struct hblk * GC_push_next_marked_uncollectable(struct hblk * h); - /* Ditto, but mark only from uncollectable pages. */ + void GC_mark_and_push_stack(ptr_t p); +#endif + void GC_clear_hdr_marks(hdr * hhdr); /* Clear the mark bits in a header */ void GC_set_hdr_marks(hdr * hhdr); @@ -1541,26 +1524,18 @@ void GC_set_fl_marks(ptr_t p); /* a free list. */ #ifdef GC_ASSERTIONS void GC_check_fl_marks(ptr_t p); - /* Check that all mark bits */ + /* Check that all mark bits */ /* associated with a free list are */ /* set. Abort if not. */ #endif void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp); void GC_exclude_static_roots_inner(void *start, void *finish); -GC_bool GC_is_static_root(ptr_t p); - /* Is the address p in one of the registered static */ - /* root sections? */ void GC_register_dynamic_libraries(void); /* Add dynamic library data sections to the root set. */ void GC_cond_register_dynamic_libraries(void); /* Remove and reregister dynamic libraries if we're */ /* configured to do that at each GC. */ -GC_bool GC_register_main_static_data(void); - /* We need to register the main data segment. Returns */ - /* TRUE unless this is done implicitly as part of */ - /* dynamic library registration. */ - /* Machine dependent startup routines */ ptr_t GC_get_main_stack_base(void); /* Cold end of stack. */ #ifdef IA64 @@ -1569,6 +1544,15 @@ ptr_t GC_get_main_stack_base(void); /* Cold end of stack. */ #endif void GC_register_data_segments(void); +#ifdef THREADS + void GC_thr_init(void); + void GC_init_parallel(void); +#else + GC_bool GC_is_static_root(ptr_t p); + /* Is the address p in one of the registered static */ + /* root sections? */ +#endif + /* Black listing: */ void GC_bl_init(void); # ifdef PRINT_BLACK_LIST @@ -1612,10 +1596,6 @@ void GC_unpromote_black_lists(void); /* Approximately undo the effect of the above. */ /* This actually loses some information, but */ /* only in a reasonably safe way. */ -word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1); - /* Return the number of (stack) blacklisted */ - /* blocks in the range for statistical */ - /* purposes. */ ptr_t GC_scratch_alloc(size_t bytes); /* GC internal memory allocation for */ @@ -1664,10 +1644,6 @@ ptr_t GC_alloc_large(size_t lb, int k, unsigned flags); /* Does not update GC_bytes_allocd, but does */ /* other accounting. */ -ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags); - /* As above, but clear block if appropriate */ - /* for kind k. */ - void GC_freehblk(struct hblk * p); /* Deallocate a heap block and mark it */ /* as invalid. */ @@ -1685,10 +1661,7 @@ void GC_continue_reclaim(size_t sz, int kind); /* kind, as long as possible, and */ /* as long as the corr. free list is */ /* empty. Sz is in granules. */ -void GC_reclaim_or_delete_all(void); - /* Arrange for all reclaim lists to be */ - /* empty. Judiciously choose between */ - /* sweeping and discarding each page. */ + GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old); /* Reclaim all blocks. Abort (in a */ /* consistent state) if f returns TRUE. */ @@ -1710,7 +1683,7 @@ GC_bool GC_try_to_collect_inner(GC_stop_func f); /* returns TRUE. Returns TRUE if it */ /* completes successfully. */ # define GC_gcollect_inner() \ - (void) GC_try_to_collect_inner(GC_never_stop_func) + (void)GC_try_to_collect_inner(GC_never_stop_func) GC_EXTERN GC_bool GC_is_initialized; /* GC_init() has been run. */ @@ -1748,18 +1721,14 @@ void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k); /* will always be a pointer to the */ /* beginning of the object while the */ /* object is live. */ -void GC_generic_malloc_many(size_t lb, int k, void **result); - /* Store a pointer to a list of newly */ - /* allocated objects of kind k and size */ - /* lb in *result. */ - /* Caler must make sure that *result is */ - /* traced even if objects are ptrfree. */ + ptr_t GC_allocobj(size_t sz, int kind); /* Make the indicated */ /* free list nonempty, and return its */ /* head. Sz is in granules. */ -void * GC_clear_stack(void *); /* in misc.c, behaves like identity. */ +void * GC_clear_stack(void *); + /* in misc.c, behaves like identity. */ /* We make the GC_clear_stack() call a tail one, hoping to get more of */ /* the stack. */ @@ -1769,18 +1738,14 @@ void * GC_clear_stack(void *); /* in misc.c, behaves like identity. */ GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k)) /* Allocation routines that bypass the thread local cache. */ -/* Used internally. */ #ifdef THREAD_LOCAL_ALLOC void * GC_core_malloc(size_t); void * GC_core_malloc_atomic(size_t); # ifdef GC_GCJ_SUPPORT - void *GC_core_gcj_malloc(size_t, void *); + void * GC_core_gcj_malloc(size_t, void *); # endif #endif /* THREAD_LOCAL_ALLOC */ -void GC_free_inner(void * p); -void GC_debug_free_inner(void * p); - void GC_init_headers(void); struct hblkhdr * GC_install_header(struct hblk *h); /* Install a header for block h. */ @@ -1794,7 +1759,7 @@ void GC_remove_header(struct hblk * h); /* Remove the header for block h. */ void GC_remove_counts(struct hblk * h, size_t sz); /* Remove forwarding counts for h. */ -hdr * GC_find_header(ptr_t h); /* Debugging only. */ +hdr * GC_find_header(ptr_t h); void GC_finalize(void); /* Perform all indicated finalization actions */ @@ -1810,12 +1775,6 @@ void GC_notify_or_invoke_finalizers(void); /* finalizers to be run, and we haven't called */ /* this procedure yet this GC cycle. */ -void * GC_make_closure(GC_finalization_proc fn, void * data); -void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data); - /* Auxiliary fns to make finalization work */ - /* correctly with displaced pointers introduced */ - /* by the debugging allocators. */ - void GC_add_to_heap(struct hblk *p, size_t bytes); /* Add a HBLKSIZE aligned chunk to the heap. */ @@ -1827,10 +1786,10 @@ void GC_add_to_heap(struct hblk *p, size_t bytes); # define GC_add_to_our_memory(p, bytes) #endif -void GC_print_obj(ptr_t p); - /* P points to somewhere inside an object with */ - /* debugging info. Print a human readable */ - /* description of the object to stderr. */ +void GC_print_all_errors(void); + /* Print smashed and leaked objects, if any. */ + /* Clear the lists of such objects. */ + GC_EXTERN void (*GC_check_heap)(void); /* Check that all objects in the heap with */ /* debugging info are intact. */ @@ -1838,13 +1797,11 @@ GC_EXTERN void (*GC_check_heap)(void); GC_EXTERN void (*GC_print_all_smashed)(void); /* Print GC_smashed if it's not empty. */ /* Clear GC_smashed list. */ -void GC_print_all_errors(void); - /* Print smashed and leaked objects, if any. */ - /* Clear the lists of such objects. */ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); /* If possible print s followed by a more */ /* detailed description of the object */ /* referred to by p. */ + #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) void GC_print_address_map(void); /* Print an address map of the process. */ @@ -1884,6 +1841,10 @@ GC_EXTERN GC_bool GC_print_back_height; void GC_print_back_graph_stats(void); #endif +#ifdef THREADS + void GC_free_inner(void * p); +#endif + /* Macros used for collector internal allocation. */ /* These assume the collector lock is held. */ #ifdef DBG_HDRS_ALL @@ -1893,6 +1854,7 @@ GC_EXTERN GC_bool GC_print_back_height; # define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \ GC_debug_generic_malloc_inner_ignore_off_page # ifdef THREADS + void GC_debug_free_inner(void * p); # define GC_INTERNAL_FREE GC_debug_free_inner # else # define GC_INTERNAL_FREE GC_debug_free @@ -1908,8 +1870,8 @@ GC_EXTERN GC_bool GC_print_back_height; # endif #endif -/* Memory unmapping: */ #ifdef USE_MUNMAP + /* Memory unmapping: */ void GC_unmap_old(void); void GC_merge_unmapped(void); void GC_unmap(ptr_t start, size_t bytes); @@ -1923,9 +1885,8 @@ void GC_read_dirty(void); /* Retrieve dirty bits. */ GC_bool GC_page_was_dirty(struct hblk *h); /* Read retrieved dirty bits. */ -GC_bool GC_page_was_ever_dirty(struct hblk *h); - /* Could the page contain valid heap pointers? */ -void GC_remove_protection(struct hblk *h, word nblocks, GC_bool pointerfree); +void GC_remove_protection(struct hblk *h, word nblocks, + GC_bool pointerfree); /* h is about to be written or allocated. Ensure */ /* that it's not write protected by the virtual */ /* dirty bit implementation. */ @@ -2028,9 +1989,6 @@ GC_EXTERN signed_word GC_bytes_found; #endif #ifdef THREADS - GC_EXTERN long GC_markers; /* Number of mark threads we would like */ - /* to have. Includes the initiating */ - /* thread. Defined in mark.c. */ # if defined(MSWIN32) || defined(MSWINCE) GC_EXTERN CRITICAL_SECTION GC_write_cs; /* defined in misc.c */ # endif @@ -2070,7 +2028,8 @@ GC_EXTERN signed_word GC_bytes_found; #if defined(mips) && !defined(__GNUC__) /* DOB: MIPSPro C gets an internal error taking the sizeof an array type. This code works correctly (ugliness is to avoid "unused var" warnings) */ -# define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0) +# define GC_STATIC_ASSERT(expr) \ + do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0) #else # define GC_STATIC_ASSERT(expr) (void)sizeof(char[(expr)? 1 : -1]) #endif @@ -2081,6 +2040,10 @@ GC_EXTERN signed_word GC_bytes_found; /* than the main garbage collector lock; standard pthreads-based */ /* implementations should be sufficient. */ + GC_EXTERN long GC_markers; /* Number of mark threads we would like */ + /* to have. Includes the initiating */ + /* thread. Defined in mark.c. */ + /* The mark lock and condition variable. If the GC lock is also */ /* acquired, the GC lock must be acquired first. The mark lock is */ /* used to both protect some variables used by the parallel */ @@ -2092,18 +2055,18 @@ GC_EXTERN signed_word GC_bytes_found; /* GC_notify_all_builder() is called when GC_fl_builder_count */ /* reaches 0. */ - void GC_acquire_mark_lock(void); - void GC_release_mark_lock(void); - void GC_notify_all_builder(void); - void GC_wait_for_reclaim(void); + void GC_acquire_mark_lock(void); + void GC_release_mark_lock(void); + void GC_notify_all_builder(void); + void GC_wait_for_reclaim(void); - GC_EXTERN word GC_fl_builder_count; /* Protected by mark lock. */ + GC_EXTERN word GC_fl_builder_count; /* Protected by mark lock. */ - void GC_notify_all_marker(void); - void GC_wait_marker(void); - GC_EXTERN word GC_mark_no; /* Protected by mark lock. */ + void GC_notify_all_marker(void); + void GC_wait_marker(void); + GC_EXTERN word GC_mark_no; /* Protected by mark lock. */ - void GC_help_marker(word my_mark_no); + void GC_help_marker(word my_mark_no); /* Try to help out parallel marker for mark cycle */ /* my_mark_no. Returns if the mark cycle finishes or */ /* was already done, or there was nothing to do for */ diff --git a/mach_dep.c b/mach_dep.c index 0d12d7c..782fdc5 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -79,15 +79,16 @@ asm static void PushMacRegisters() #undef HAVE_PUSH_REGS #if defined(USE_ASM_PUSH_REGS) -# define HAVE_PUSH_REGS +# define HAVE_PUSH_REGS #else /* No asm implementation */ -void GC_push_regs() -{ -# if defined(M68K) && defined(AMIGA) + +# if defined(M68K) && defined(AMIGA) + STATIC void GC_push_regs(void) + { /* AMIGA - could be replaced by generic code */ /* a0, a1, d0 and d1 are caller save */ -# ifdef __GNUC__ +# ifdef __GNUC__ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */ asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one"); @@ -104,12 +105,11 @@ void GC_push_regs() asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one"); asm("addq.w &0x4,%sp"); /* put stack back where it was */ -# define HAVE_PUSH_REGS -# else /* !__GNUC__ */ +# else /* !__GNUC__ */ GC_push_one(getreg(REG_A2)); GC_push_one(getreg(REG_A3)); # ifndef __SASC - /* Can probably be changed to #if 0 -Kjetil M. (a4=globals)*/ + /* Can probably be changed to #if 0 -Kjetil M. (a4=globals) */ GC_push_one(getreg(REG_A4)); # endif GC_push_one(getreg(REG_A5)); @@ -121,17 +121,20 @@ void GC_push_regs() GC_push_one(getreg(REG_D5)); GC_push_one(getreg(REG_D6)); GC_push_one(getreg(REG_D7)); -# define HAVE_PUSH_REGS -# endif /* !__GNUC__ */ -# endif /* AMIGA */ +# endif /* !__GNUC__ */ + } +# define HAVE_PUSH_REGS + +# elif defined(M68K) && defined(MACOS) -# if defined(M68K) && defined(MACOS) -# if defined(THINK_C) -# define PushMacReg(reg) \ +# if defined(THINK_C) +# define PushMacReg(reg) \ move.l reg,(sp) \ jsr GC_push_one + STATIC void GC_push_regs(void) + { asm { - sub.w #4,sp ; reserve space for one parameter. + sub.w #4,sp ; reserve space for one parameter. PushMacReg(a2); PushMacReg(a3); PushMacReg(a4); @@ -142,17 +145,20 @@ void GC_push_regs() PushMacReg(d5); PushMacReg(d6); PushMacReg(d7); - add.w #4,sp ; fix stack. + add.w #4,sp ; fix stack. } -# define HAVE_PUSH_REGS -# undef PushMacReg -# endif /* THINK_C */ -# if defined(__MWERKS__) + } +# define HAVE_PUSH_REGS +# undef PushMacReg +# elif defined(__MWERKS__) + STATIC void GC_push_regs(void) + { PushMacRegisters(); -# define HAVE_PUSH_REGS -# endif /* __MWERKS__ */ -# endif /* MACOS */ -} + } +# define HAVE_PUSH_REGS +# endif /* __MWERKS__ */ +# endif /* MACOS */ + #endif /* !USE_ASM_PUSH_REGS */ #if defined(HAVE_PUSH_REGS) && defined(THREADS) @@ -236,8 +242,8 @@ void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), ptr_t arg) /* _setjmp won't, but is less portable. */ # endif # endif /* !HAVE_PUSH_REGS ... */ - /* FIXME: context here is sometimes just zero. At the moment the callees */ - /* don't really need it. */ + /* FIXME: context here is sometimes just zero. At the moment the */ + /* callees don't really need it. */ fn(arg, context); /* Strongly discourage the compiler from treating the above */ /* as a tail-call, since that would pop the register */ @@ -248,9 +254,10 @@ void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), ptr_t arg) #if defined(ASM_CLEAR_CODE) # ifdef LINT /*ARGSUSED*/ - ptr_t GC_clear_stack_inner(arg, limit) - ptr_t arg; word limit; - { return(arg); } + ptr_t GC_clear_stack_inner(ptr_t arg, word limit) + { + return(arg); + } /* The real version is in a .S file */ # endif #endif /* ASM_CLEAR_CODE */ diff --git a/malloc.c b/malloc.c index cf330a8..041a3e1 100644 --- a/malloc.c +++ b/malloc.c @@ -21,7 +21,7 @@ # include #endif -void GC_extend_size_map(size_t); /* in misc.c. */ +void GC_extend_size_map(size_t); /* in misc.c. */ /* Allocate reclaim list for kind: */ /* Return TRUE on success */ @@ -82,11 +82,10 @@ ptr_t GC_alloc_large(size_t lb, int k, unsigned flags) return result; } - /* Allocate a large block of size lb bytes. Clear if appropriate. */ /* We hold the allocation lock. */ /* EXTRA_BYTES were already added to lb. */ -ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags) +STATIC ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags) { ptr_t result = GC_alloc_large(lb, k, flags); word n_blocks = OBJ_SZ_TO_BLOCKS(lb); @@ -302,10 +301,10 @@ GC_API char * GC_CALL GC_strdup(const char *s) # define RA # endif # define GC_debug_malloc_replacement(lb) \ - GC_debug_malloc(lb, RA "unknown", 0) + GC_debug_malloc(lb, RA "unknown", 0) void * malloc(size_t lb) - { +{ /* It might help to manually inline the GC_malloc call here. */ /* But any decent compiler should reduce the extra procedure call */ /* to at most a jump instruction in this case. */ @@ -320,7 +319,7 @@ void * malloc(size_t lb) if (!GC_is_initialized) return sbrk(lb); # endif /* I386 && GC_SOLARIS_THREADS */ return((void *)REDIRECT_MALLOC(lb)); - } +} #if defined(GC_LINUX_THREADS) /* && !defined(USE_PROC_FOR_LIBRARIES) */ STATIC ptr_t GC_libpthread_start = 0; @@ -328,7 +327,7 @@ void * malloc(size_t lb) STATIC ptr_t GC_libld_start = 0; STATIC ptr_t GC_libld_end = 0; GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp); - /* From os_dep.c */ + /* From os_dep.c */ STATIC void GC_init_lib_bounds(void) { @@ -457,8 +456,8 @@ GC_API void GC_CALL GC_free(void * p) /* Only used for internally allocated objects, so we can take some */ /* shortcuts. */ #ifdef THREADS -void GC_free_inner(void * p) -{ + void GC_free_inner(void * p) + { struct hblk *h; hdr *hhdr; size_t sz; /* bytes */ @@ -492,13 +491,14 @@ void GC_free_inner(void * p) } GC_freehblk(h); } -} + } #endif /* THREADS */ -# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE) -# define REDIRECT_FREE GC_free -# endif -# ifdef REDIRECT_FREE +#if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE) +# define REDIRECT_FREE GC_free +#endif + +#ifdef REDIRECT_FREE void free(void * p) { # if defined(GC_LINUX_THREADS) && !defined(USE_PROC_FOR_LIBRARIES) @@ -520,4 +520,4 @@ void GC_free_inner(void * p) REDIRECT_FREE(p); # endif } -# endif /* REDIRECT_MALLOC */ +#endif /* REDIRECT_FREE */ diff --git a/mallocx.c b/mallocx.c index f73735b..9f44a1d 100644 --- a/mallocx.c +++ b/mallocx.c @@ -58,7 +58,6 @@ STATIC void * GC_generic_or_special_malloc(size_t lb, int knd) } } - /* Change the size of the block pointed to by p to contain at least */ /* lb bytes. The object may be (and quite likely will be) moved. */ /* The kind (e.g. atomic) is the same as that of the old. */ @@ -262,7 +261,7 @@ GC_API void GC_CALL GC_incr_bytes_freed(size_t n) /* since the collector would not retain the entire list if it were */ /* invoked just as we were returning. */ /* Note that the client should usually clear the link field. */ -void GC_generic_malloc_many(size_t lb, int k, void **result) +GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result) { void *op; void *p; @@ -522,12 +521,12 @@ GC_API void * GC_CALL GC_memalign(size_t align, size_t lb) return result; } -# ifdef ATOMIC_UNCOLLECTABLE -/* Allocate lb bytes of pointerfree, untraced, uncollectable data */ -/* This is normally roughly equivalent to the system malloc. */ -/* But it may be useful if malloc is redefined. */ -GC_API void * GC_CALL GC_malloc_atomic_uncollectable(size_t lb) -{ +#ifdef ATOMIC_UNCOLLECTABLE + /* Allocate lb bytes of pointerfree, untraced, uncollectable data */ + /* This is normally roughly equivalent to the system malloc. */ + /* But it may be useful if malloc is redefined. */ + GC_API void * GC_CALL GC_malloc_atomic_uncollectable(size_t lb) + { void *op; void **opp; size_t lg; @@ -569,6 +568,5 @@ GC_API void * GC_CALL GC_malloc_atomic_uncollectable(size_t lb) UNLOCK(); return((void *) op); } -} - + } #endif /* ATOMIC_UNCOLLECTABLE */ diff --git a/mark.c b/mark.c index bf19a78..ae05761 100644 --- a/mark.c +++ b/mark.c @@ -280,6 +280,18 @@ void GC_initiate_gc(void) STATIC void GC_do_parallel_mark(void); /* initiate parallel marking. */ #endif /* PARALLEL_MARK */ +#ifdef SMALL_CONFIG +# define GC_push_next_marked_dirty(h) GC_push_next_marked(h) +#else + STATIC struct hblk * GC_push_next_marked_dirty(struct hblk *h); + /* Invoke GC_push_marked on next dirty block above h. */ + /* Return a pointer just past the end of this block. */ +#endif /* !SMALL_CONFIG */ +STATIC struct hblk * GC_push_next_marked(struct hblk *h); + /* Ditto, but also mark from clean pages. */ +STATIC struct hblk * GC_push_next_marked_uncollectable(struct hblk *h); + /* Ditto, but mark only from uncollectable pages. */ + static void alloc_mark_stack(size_t); # if (defined(MSWIN32) || defined(MSWINCE)) && !defined(__GNUC__) \ @@ -472,7 +484,7 @@ static void alloc_mark_stack(size_t); } # endif /* __GNUC__ && MSWIN32 */ -#ifdef GC_WIN32_THREADS +#if defined(GC_WIN32_THREADS) && !defined(__GNUC__) GC_bool GC_started_thread_while_stopped(void); /* In win32_threads.c. Did we invalidate mark phase with an */ /* unexpected thread start? */ @@ -576,7 +588,6 @@ handle_ex: } #endif /* WRAP_MARK_SOME */ - GC_bool GC_mark_stack_empty(void) { return(GC_mark_stack_top < GC_mark_stack); @@ -630,11 +641,11 @@ mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, mse *mark_stack_limit) GC_objects_are_marked = TRUE; INIT_HDR_CACHE; # ifdef OS2 /* Use untweaked version to circumvent compiler problem */ - while (mark_stack_top >= mark_stack && credit >= 0) { + while (mark_stack_top >= mark_stack && credit >= 0) # else - while ((((ptr_t)mark_stack_top - (ptr_t)mark_stack) | credit) - >= 0) { + while ((((ptr_t)mark_stack_top - (ptr_t)mark_stack) | credit) >= 0) # endif + { current_p = mark_stack_top -> mse_start; descr = mark_stack_top -> mse_descr; retry: @@ -1277,20 +1288,22 @@ void GC_push_all(ptr_t bottom, ptr_t top) GC_mark_stack_top -> mse_descr = length; } -/* - * Analogous to the above, but push only those pages h with dirty_fn(h) != 0. - * We use push_fn to actually push the block. - * Used both to selectively push dirty pages, or to push a block - * in piecemeal fashion, to allow for more marking concurrency. - * Will not overflow mark stack if push_fn pushes a small fixed number - * of entries. (This is invoked only if push_fn pushes a single entry, - * or if it marks each object before pushing it, thus ensuring progress - * in the event of a stack overflow.) - */ -void GC_push_selected(ptr_t bottom, ptr_t top, - int (*dirty_fn) (struct hblk *), - void (*push_fn) (ptr_t, ptr_t)) -{ +#ifndef SMALL_CONFIG + + /* + * Analogous to the above, but push only those pages h with + * dirty_fn(h) != 0. We use push_fn to actually push the block. + * Used both to selectively push dirty pages, or to push a block + * in piecemeal fashion, to allow for more marking concurrency. + * Will not overflow mark stack if push_fn pushes a small fixed number + * of entries. (This is invoked only if push_fn pushes a single entry, + * or if it marks each object before pushing it, thus ensuring progress + * in the event of a stack overflow.) + */ + STATIC void GC_push_selected(ptr_t bottom, ptr_t top, + int (*dirty_fn)(struct hblk *), + void (*push_fn)(ptr_t, ptr_t)) + { struct hblk * h; bottom = (ptr_t)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1)); @@ -1328,17 +1341,21 @@ void GC_push_selected(ptr_t bottom, ptr_t top, if (GC_mark_stack_top >= GC_mark_stack_limit) { ABORT("unexpected mark stack overflow"); } -} + } -# ifndef SMALL_CONFIG +# ifdef PROC_VDB + GC_bool GC_page_was_ever_dirty(struct hblk *h); + /* Could the page contain valid heap pointers? */ +# endif -void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all) -{ + void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all) + { if (all) { if (GC_dirty_maintained) { # ifdef PROC_VDB /* Pages that were never dirtied cannot contain pointers */ - GC_push_selected(bottom, top, GC_page_was_ever_dirty, GC_push_all); + GC_push_selected(bottom, top, GC_page_was_ever_dirty, + GC_push_all); # else GC_push_all(bottom, top); # endif @@ -1348,23 +1365,23 @@ void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all) } else { GC_push_selected(bottom, top, GC_page_was_dirty, GC_push_all); } -} -#endif + } +#endif /* !SMALL_CONFIG */ -# if defined(MSWIN32) || defined(MSWINCE) +#if defined(MSWIN32) || defined(MSWINCE) void __cdecl GC_push_one(word p) -# else +#else void GC_push_one(word p) -# endif +#endif { GC_PUSH_ONE_STACK(p, MARKED_FROM_REGISTER); } /*ARGSUSED*/ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, - mse *mark_stack_ptr, - mse *mark_stack_limit, - void **src) + mse *mark_stack_ptr, + mse *mark_stack_limit, + void **src) { hdr * hhdr; @@ -1560,7 +1577,7 @@ void GC_push_all_stack(ptr_t bottom, ptr_t top) #ifdef USE_PUSH_MARKED_ACCELERATORS /* Push all objects reachable from marked objects in the given block */ /* containing objects of size 1 granule. */ -void GC_push_marked1(struct hblk *h, hdr *hhdr) +STATIC void GC_push_marked1(struct hblk *h, hdr *hhdr) { word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; @@ -1610,7 +1627,7 @@ void GC_push_marked1(struct hblk *h, hdr *hhdr) /* Push all objects reachable from marked objects in the given block */ /* of size 2 (granules) objects. */ -void GC_push_marked2(struct hblk *h, hdr *hhdr) +STATIC void GC_push_marked2(struct hblk *h, hdr *hhdr) { word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; @@ -1659,7 +1676,7 @@ void GC_push_marked2(struct hblk *h, hdr *hhdr) /* of size 4 (granules) objects. */ /* There is a risk of mark stack overflow here. But we handle that. */ /* And only unmarked objects get pushed, so it's not very likely. */ -void GC_push_marked4(struct hblk *h, hdr *hhdr) +STATIC void GC_push_marked4(struct hblk *h, hdr *hhdr) { word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; @@ -1709,7 +1726,7 @@ void GC_push_marked4(struct hblk *h, hdr *hhdr) #endif /* USE_PUSH_MARKED_ACCELERATORS */ /* Push all objects reachable from marked objects in the given block */ -void GC_push_marked(struct hblk *h, hdr *hhdr) +STATIC void GC_push_marked(struct hblk *h, hdr *hhdr) { size_t sz = hhdr -> hb_sz; word descr = hhdr -> hb_descr; @@ -1780,7 +1797,7 @@ STATIC GC_bool GC_block_was_dirty(struct hblk *h, hdr *hhdr) /* Similar to GC_push_marked, but skip over unallocated blocks */ /* and return address of next plausible block. */ -struct hblk * GC_push_next_marked(struct hblk *h) +STATIC struct hblk * GC_push_next_marked(struct hblk *h) { hdr * hhdr = HDR(h); @@ -1794,9 +1811,9 @@ struct hblk * GC_push_next_marked(struct hblk *h) } #ifndef SMALL_CONFIG -/* Identical to above, but mark only from dirty pages */ -struct hblk * GC_push_next_marked_dirty(struct hblk *h) -{ + /* Identical to above, but mark only from dirty pages */ + STATIC struct hblk * GC_push_next_marked_dirty(struct hblk *h) + { hdr * hhdr = HDR(h); if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); } @@ -1823,12 +1840,12 @@ struct hblk * GC_push_next_marked_dirty(struct hblk *h) } GC_push_marked(h, hhdr); return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz)); -} + } #endif /* Similar to above, but for uncollectable pages. Needed since we */ /* do not clear marks for such pages, even for full collections. */ -struct hblk * GC_push_next_marked_uncollectable(struct hblk *h) +STATIC struct hblk * GC_push_next_marked_uncollectable(struct hblk *h) { hdr * hhdr = HDR(h); diff --git a/mark_rts.c b/mark_rts.c index b872319..41b942f 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -24,9 +24,9 @@ struct roots { ptr_t r_start; ptr_t r_end; - # if !defined(MSWIN32) && !defined(MSWINCE) +# if !defined(MSWIN32) && !defined(MSWINCE) struct roots * r_next; - # endif +# endif GC_bool r_tmp; -- Delete before registering new dynamic libraries }; @@ -61,10 +61,11 @@ static int n_root_sets = 0; } #endif /* !NO_DEBUGGING */ -/* Primarily for debugging support: */ -/* Is the address p in one of the registered static root sections? */ -GC_bool GC_is_static_root(ptr_t p) -{ +#ifndef THREADS + /* Primarily for debugging support: */ + /* Is the address p in one of the registered static root sections? */ + GC_bool GC_is_static_root(ptr_t p) + { static int last_root_set = MAX_ROOT_SETS; int i; @@ -79,7 +80,8 @@ GC_bool GC_is_static_root(ptr_t p) } } return(FALSE); -} + } +#endif /* !THREADS */ #if !defined(MSWIN32) && !defined(MSWINCE) /* @@ -92,8 +94,8 @@ GC_bool GC_is_static_root(ptr_t p) -- really defined in gc_priv.h */ -GC_INLINE int rt_hash(ptr_t addr) -{ + GC_INLINE int rt_hash(ptr_t addr) + { word result = (word) addr; # if CPP_WORDSZ > 8*LOG_RT_SIZE result ^= result >> 8*LOG_RT_SIZE; @@ -105,12 +107,12 @@ GC_INLINE int rt_hash(ptr_t addr) result ^= result >> LOG_RT_SIZE; result &= (RT_SIZE-1); return(result); -} + } -/* Is a range starting at b already in the table? If so return a */ -/* pointer to it, else NIL. */ -struct roots * GC_roots_present(ptr_t b) -{ + /* Is a range starting at b already in the table? If so return a */ + /* pointer to it, else NIL. */ + struct roots * GC_roots_present(ptr_t b) + { int h = rt_hash(b); struct roots *p = GC_root_index[h]; @@ -119,18 +121,17 @@ struct roots * GC_roots_present(ptr_t b) p = p -> r_next; } return(FALSE); -} + } -/* Add the given root structure to the index. */ -GC_INLINE void add_roots_to_index(struct roots *p) -{ + /* Add the given root structure to the index. */ + GC_INLINE void add_roots_to_index(struct roots *p) + { int h = rt_hash(p -> r_start); p -> r_next = GC_root_index[h]; GC_root_index[h] = p; -} - -# endif + } +#endif /* !MSWIN32 */ GC_INNER word GC_root_size = 0; @@ -300,10 +301,10 @@ STATIC void GC_remove_tmp_roots(void) #endif #if !defined(MSWIN32) && !defined(MSWINCE) -STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e); + STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e); -GC_API void GC_CALL GC_remove_roots(void *b, void *e) -{ + GC_API void GC_CALL GC_remove_roots(void *b, void *e) + { DCL_LOCK_STATE; /* Quick check whether has nothing to do */ @@ -314,11 +315,11 @@ GC_API void GC_CALL GC_remove_roots(void *b, void *e) LOCK(); GC_remove_roots_inner((ptr_t)b, (ptr_t)e); UNLOCK(); -} + } -/* Should only be called when the lock is held */ -STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e) -{ + /* Should only be called when the lock is held */ + STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e) + { int i; for (i = 0; i < n_root_sets; ) { if (GC_static_roots[i].r_start >= b @@ -329,15 +330,15 @@ STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e) } } GC_rebuild_root_index(); -} + } #endif /* !defined(MSWIN32) && !defined(MSWINCE) */ #if (defined(MSWIN32) || defined(MSWINCE)) && !defined(NO_DEBUGGING) -/* Not used at present (except for, may be, debugging purpose). */ -/* Workaround for the OS mapping and unmapping behind our back: */ -/* Is the address p in one of the temporary static root sections? */ -GC_bool GC_is_tmp_root(ptr_t p) -{ + /* Not used at present (except for, may be, debugging purpose). */ + /* Workaround for the OS mapping and unmapping behind our back: */ + /* Is the address p in one of the temporary static root sections? */ + GC_bool GC_is_tmp_root(ptr_t p) + { static int last_root_set = MAX_ROOT_SETS; register int i; @@ -353,7 +354,7 @@ GC_bool GC_is_tmp_root(ptr_t p) } } return(FALSE); -} + } #endif /* MSWIN32 || MSWINCE */ ptr_t GC_approx_sp(void) @@ -363,7 +364,6 @@ ptr_t GC_approx_sp(void) /* Also force stack to grow if necessary. Otherwise the */ /* later accesses might cause the kernel to think we're */ /* doing something wrong. */ - return((ptr_t)sp); } @@ -477,10 +477,10 @@ STATIC void GC_push_conditional_with_exclusions(ptr_t bottom, ptr_t top, } #ifdef IA64 -/* Similar to GC_push_all_stack_frames() but for IA-64 registers store. */ -void GC_push_all_register_frames(ptr_t bs_lo, ptr_t bs_hi, int eager, - struct GC_activation_frame_s *activation_frame) -{ + /* Similar to GC_push_all_stack_frames() but for IA-64 registers store. */ + void GC_push_all_register_frames(ptr_t bs_lo, ptr_t bs_hi, + int eager, struct GC_activation_frame_s *activation_frame) + { while (activation_frame != NULL) { ptr_t frame_bs_lo = activation_frame -> backing_store_end; GC_ASSERT(frame_bs_lo <= bs_hi); @@ -498,7 +498,7 @@ void GC_push_all_register_frames(ptr_t bs_lo, ptr_t bs_hi, int eager, } else { GC_push_all_stack(bs_lo, bs_hi); } -} + } #endif /* IA64 */ #ifdef THREADS @@ -549,7 +549,7 @@ void GC_push_all_stack_frames(ptr_t lo, ptr_t hi, * GC_dirty() call. */ STATIC void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top, - ptr_t cold_gc_frame) + ptr_t cold_gc_frame) { if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) { /* Push the hot end of the stack eagerly, so that register values */ @@ -634,7 +634,7 @@ STATIC void GC_push_current_stack(ptr_t cold_gc_frame, void * context) /* For IA64, the register stack backing store is handled */ /* in the thread-specific code. */ # else - GC_push_all_eager( cold_gc_frame, GC_approx_sp() ); + GC_push_all_eager(cold_gc_frame, GC_approx_sp()); # endif # else GC_push_all_stack_part_eager_frames(GC_approx_sp(), GC_stackbottom, @@ -664,7 +664,7 @@ STATIC void GC_push_current_stack(ptr_t cold_gc_frame, void * context) TRUE /* eager */, GC_activation_frame); } /* All values should be sufficiently aligned that we */ - /* dont have to worry about the boundary. */ + /* don't have to worry about the boundary. */ } # endif # endif /* !THREADS */ diff --git a/misc.c b/misc.c index 0454ed8..34d0b90 100644 --- a/misc.c +++ b/misc.c @@ -49,11 +49,14 @@ /* For other platforms with threads, the lock and possibly */ /* GC_lock_holder variables are defined in the thread support code. */ -/* Dont unnecessarily call GC_register_main_static_data() in case */ -/* dyn_load.c isn't linked in. */ #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_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 */ + /* dyn_load.c isn't linked in. */ # define GC_REGISTER_MAIN_STATIC_DATA() TRUE #endif @@ -63,7 +66,6 @@ GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */; - GC_INNER GC_bool GC_debugging_started = FALSE; /* defined here so we don't have to load debug_malloc.o */ @@ -235,10 +237,10 @@ void GC_extend_size_map(size_t i) #if defined(ASM_CLEAR_CODE) void *GC_clear_stack_inner(void *, ptr_t); #else -/* Clear the stack up to about limit. Return arg. */ -/*ARGSUSED*/ -void * GC_clear_stack_inner(void *arg, ptr_t limit) -{ + /* Clear the stack up to about limit. Return arg. */ + /*ARGSUSED*/ + STATIC void * GC_clear_stack_inner(void *arg, ptr_t limit) + { word dummy[CLEAR_SIZE]; BZERO(dummy, CLEAR_SIZE*sizeof(word)); @@ -249,7 +251,7 @@ void * GC_clear_stack_inner(void *arg, ptr_t limit) /* call is not recognized as dead code. */ GC_noop1((word)dummy); return(arg); -} + } #endif /* Clear some of the inaccessible part of the stack. Returns its */ @@ -451,10 +453,6 @@ GC_API size_t GC_CALL GC_get_total_bytes(void) GC_INNER GC_bool GC_is_initialized = FALSE; -# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) - void GC_init_parallel(void); -# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ - #if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS) GC_INNER CRITICAL_SECTION GC_write_cs; #endif @@ -476,39 +474,28 @@ STATIC void GC_exit_check(void) #ifdef UNIX_LIKE -void GC_set_and_save_fault_handler(void (*handler)(int)); + void GC_set_and_save_fault_handler(void (*handler)(int)); -static void looping_handler(int sig) -{ + static void looping_handler(int sig) + { GC_err_printf("Caught signal %d: looping in handler\n", sig); for (;;) {} -} + } -static GC_bool installed_looping_handler = FALSE; + static GC_bool installed_looping_handler = FALSE; -static void maybe_install_looping_handler(void) -{ + static void maybe_install_looping_handler(void) + { /* Install looping handler before the write fault handler, so we */ /* handle write faults correctly. */ - if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { - GC_set_and_save_fault_handler(looping_handler); - installed_looping_handler = TRUE; - } -} + if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { + GC_set_and_save_fault_handler(looping_handler); + installed_looping_handler = TRUE; + } + } #else /* !UNIX_LIKE */ - # define maybe_install_looping_handler() - -#endif - -#if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) - void GC_thr_init(void); -#endif - -#ifdef LINT - int GC_read(void); - void GC_register_finalizer_no_order(void); #endif #if defined(DYNAMIC_LOADING) && defined(DARWIN) @@ -846,9 +833,8 @@ GC_API void GC_CALL GC_init(void) # ifdef LINT { extern char * const GC_copyright[]; - GC_noop(GC_copyright, GC_find_header, - GC_push_one, GC_call_with_alloc_lock, GC_read, - GC_dont_expand, + GC_noop(GC_copyright, GC_find_header, GC_push_one, + GC_call_with_alloc_lock, GC_dont_expand, # ifndef NO_DEBUGGING GC_dump, # endif @@ -861,7 +847,7 @@ GC_API void GC_CALL GC_init(void) # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) /* Make sure marker threads are started and thread local */ /* allocation is initialized, in case we didn't get */ - /* called from GC_init_parallel(); */ + /* called from GC_init_parallel. */ GC_init_parallel(); # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ @@ -1026,12 +1012,12 @@ out: return tmp ? (int)written : -1; } -#endif +#endif /* MSWIN32 */ #if defined(OS2) || defined(MACOS) -STATIC FILE * GC_stdout = NULL; -STATIC FILE * GC_stderr = NULL; -STATIC FILE * GC_log = NULL; + STATIC FILE * GC_stdout = NULL; + STATIC FILE * GC_stderr = NULL; + STATIC FILE * GC_log = NULL; STATIC void GC_set_files(void) { @@ -1091,11 +1077,11 @@ STATIC int GC_write(int fd, const char *buf, size_t len) #endif #ifdef NOSYS -STATIC int GC_write(int fd, const char *buf, size_t len) -{ - /* No writing. */ - return len; -} + STATIC int GC_write(int fd, const char *buf, size_t len) + { + /* No writing. */ + return len; + } #endif @@ -1138,7 +1124,8 @@ void GC_printf(const char *format, ...) (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); - if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed"); + if (WRITE(GC_stdout, buf, strlen(buf)) < 0) + ABORT("write to stdout failed"); } void GC_err_printf(const char *format, ...) @@ -1151,7 +1138,8 @@ void GC_err_printf(const char *format, ...) (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); - if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed"); + if (WRITE(GC_stderr, buf, strlen(buf)) < 0) + ABORT("write to stderr failed"); } void GC_log_printf(const char *format, ...) @@ -1164,7 +1152,8 @@ void GC_log_printf(const char *format, ...) (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); - if (WRITE(GC_log, buf, strlen(buf)) < 0) ABORT("write to log failed"); + if (WRITE(GC_log, buf, strlen(buf)) < 0) + ABORT("write to log failed"); } void GC_err_puts(const char *s) @@ -1173,10 +1162,10 @@ void GC_err_puts(const char *s) } #if defined(LINUX) && !defined(SMALL_CONFIG) -void GC_err_write(const char *buf, size_t len) -{ + void GC_err_write(const char *buf, size_t len) + { if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed"); -} + } #endif STATIC void GC_CALLBACK GC_default_warn_proc(char *msg, GC_word arg) @@ -1221,9 +1210,9 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void) } #if !defined(PCR) && !defined(SMALL_CONFIG) -/* Abort the program with a message. msg must not be NULL. */ -void GC_abort(const char *msg) -{ + /* Abort the program with a message. msg must not be NULL. */ + void GC_abort(const char *msg) + { # if defined(MSWIN32) # ifndef DONT_USE_USER32_DLL /* Use static binding to "user32.dll". */ @@ -1264,7 +1253,7 @@ void GC_abort(const char *msg) # else (void) abort(); # endif -} + } #endif GC_API void GC_CALL GC_enable(void) @@ -1358,8 +1347,8 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn, void *arg) #ifdef THREADS -/* Defined in pthread_support.c or win32_threads.c. */ -void GC_do_blocking_inner(ptr_t data, void * context); + /* Defined in pthread_support.c or win32_threads.c. */ + void GC_do_blocking_inner(ptr_t data, void * context); #else @@ -1463,9 +1452,8 @@ GC_API void * GC_CALL GC_do_blocking(GC_fn_type fn, void * client_data) } #if !defined(NO_DEBUGGING) - -GC_API void GC_CALL GC_dump(void) -{ + GC_API void GC_CALL GC_dump(void) + { GC_printf("***Static roots:\n"); GC_print_static_roots(); GC_printf("\n***Heap sections:\n"); @@ -1474,9 +1462,8 @@ GC_API void GC_CALL GC_dump(void) GC_print_hblkfreelist(); GC_printf("\n***Blocks in use:\n"); GC_print_block_list(); -} - -#endif /* NO_DEBUGGING */ + } +#endif /* !NO_DEBUGGING */ /* Getter functions for the public Read-only variables. */ diff --git a/os_dep.c b/os_dep.c index 5b1ab04..81eb0e7 100644 --- a/os_dep.c +++ b/os_dep.c @@ -16,10 +16,6 @@ #include "private/gc_priv.h" -#if defined(THREADS) && defined(MPROTECT_VDB) -# include "atomic_ops.h" -#endif - #if defined(LINUX) && !defined(POWERPC) # include # if (LINUX_VERSION_CODE <= 0x10400) @@ -152,7 +148,7 @@ /* Repeatedly perform a read call until the buffer is filled or */ /* we encounter EOF. */ -ssize_t GC_repeat_read(int fd, char *buf, size_t count) +STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count) { ssize_t num_read = 0; ssize_t result; @@ -220,7 +216,7 @@ char * GC_get_maps(void) /* file atomically. This is arguably a misfeature of the */ /* /proc/.../maps interface. */ - /* Since we dont believe the file can grow */ + /* Since we don't believe the file can grow */ /* asynchronously, it should suffice to first determine */ /* the size (using lseek or read), and then to reread the */ /* file. If the size is inconsistent we have to retry. */ @@ -304,8 +300,8 @@ char * GC_get_maps(void) * buffer. */ char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, - char **prot, unsigned int *maj_dev, - char **mapping_name) + char **prot, unsigned int *maj_dev, + char **mapping_name) { char *start_start, *end_start, *maj_dev_start; char *p; @@ -417,8 +413,8 @@ GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp) #endif /* REDIRECT_MALLOC */ #ifdef IA64 -static ptr_t backing_store_base_from_proc(void) -{ + static ptr_t backing_store_base_from_proc(void) + { ptr_t my_start, my_end; if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) { if (GC_print_stats) { @@ -427,7 +423,7 @@ static ptr_t backing_store_base_from_proc(void) return 0; } return my_start; -} + } #endif #endif /* NEED_PROC_MAPS */ @@ -506,6 +502,7 @@ static void *tiny_sbrk(ptrdiff_t increment) #if defined(NETBSD) && defined(__ELF__) ptr_t GC_data_start = NULL; ptr_t GC_find_limit(ptr_t, GC_bool); + extern char **environ; void GC_init_netbsd_elf(void) @@ -525,7 +522,7 @@ static void *tiny_sbrk(ptrdiff_t increment) extern sigset_t __syscall(quad_t, ...); # endif - /* Dont use GC_find_limit() because siglongjmp() outside of the */ + /* Don't use GC_find_limit() because siglongjmp() outside of the */ /* signal handler by-passes our userland pthreads lib, leaving */ /* SIGSEGV and SIGPROF masked. Instead, use this custom one that */ /* works-around the issues. */ @@ -1209,7 +1206,7 @@ ptr_t GC_get_main_stack_base(void) #ifdef IA64 ptr_t GC_greatest_stack_base_below(ptr_t bound); - /* From pthread_support.c */ + /* From pthread_support.c */ #endif GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b) @@ -1267,7 +1264,7 @@ GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b) # include /* Find the stack using pthread_stackseg_np(). */ - int GC_get_stack_base(struct GC_stack_base *sb) + GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) { stack_t stack; pthread_stackseg_np(pthread_self(), &stack); @@ -1654,11 +1651,9 @@ void GC_register_data_segments(void) /* Is p the start of either the malloc heap, or of one of our */ /* heap sections? */ - GC_bool GC_is_heap_base (ptr_t p) + GC_bool GC_is_heap_base(ptr_t p) { - unsigned i; - # ifndef REDIRECT_MALLOC if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size; if (GC_is_malloc_heap_base(p)) return TRUE; @@ -1666,7 +1661,7 @@ void GC_register_data_segments(void) for (i = 0; i < GC_n_heap_bases; i++) { if (GC_heap_bases[i] == p) return TRUE; } - return FALSE ; + return FALSE; } # ifdef MSWIN32 @@ -1746,7 +1741,9 @@ ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr) } # endif -# if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR) +# if defined(FREEBSD) && !defined(PCR) && (defined(I386) || defined(X86_64) \ + || defined(powerpc) || defined(__powerpc__)) + /* Its unclear whether this should be identical to the above, or */ /* whether it should apply to non-X86 architectures. */ /* For now we don't assume that there is always an empty page after */ @@ -1775,7 +1772,7 @@ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr) return(result); } -# endif +# endif /* FREEBSD */ #ifdef AMIGA @@ -1991,10 +1988,9 @@ STATIC ptr_t GC_unix_sbrk_get_mem(word bytes) } #if defined(MMAP_SUPPORTED) - -/* By default, we try both sbrk and mmap, in that order. */ -ptr_t GC_unix_get_mem(word bytes) -{ + /* By default, we try both sbrk and mmap, in that order. */ + ptr_t GC_unix_get_mem(word bytes) + { static GC_bool sbrk_failed = FALSE; ptr_t result = 0; @@ -2008,15 +2004,12 @@ ptr_t GC_unix_get_mem(word bytes) result = GC_unix_sbrk_get_mem(bytes); } return result; -} - + } #else /* !MMAP_SUPPORTED */ - -ptr_t GC_unix_get_mem(word bytes) -{ + ptr_t GC_unix_get_mem(word bytes) + { return GC_unix_sbrk_get_mem(bytes); -} - + } #endif #endif /* Not USE_MMAP */ @@ -2130,9 +2123,9 @@ GC_API void GC_CALL GC_win32_free_heap(void) #endif -# ifdef MSWINCE -ptr_t GC_wince_get_mem(word bytes) -{ +#ifdef MSWINCE + ptr_t GC_wince_get_mem(word bytes) + { ptr_t result = 0; /* initialized to prevent warning. */ word i; @@ -2180,8 +2173,8 @@ ptr_t GC_wince_get_mem(word bytes) } return(result); -} -# endif + } +#endif #ifdef USE_MUNMAP @@ -2389,7 +2382,7 @@ PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data) extern struct PCR_MM_ProcsRep * GC_old_allocator; /* defined in pcr_interface.c. */ -void GC_default_push_other_roots(void) +STATIC void GC_default_push_other_roots(void) { /* Traverse data allocated by previous memory managers. */ if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false, @@ -2585,6 +2578,8 @@ STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2) get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h)); } +#if 0 + /* Used only if PROC_VDB. */ # ifdef MPROTECT_VDB STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h) # else @@ -2594,11 +2589,12 @@ STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2) return HDR(h) == 0 || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h)); } +#endif # ifndef MPROTECT_VDB /*ARGSUSED*/ void GC_remove_protection(struct hblk *h, word nblocks, - GC_bool is_ptrfree) {} + GC_bool is_ptrfree) {} # endif # endif /* GWW_VDB */ @@ -2639,12 +2635,14 @@ GC_bool GC_page_was_dirty(struct hblk *h) * versions are adequate. */ +#if 0 /* Could any valid GC heap pointer ever have been written to this page? */ /*ARGSUSED*/ GC_bool GC_page_was_ever_dirty(struct hblk *h) { return(TRUE); } +#endif /* A call that: */ /* I) hints that [h, h+nblocks) is about to be written. */ @@ -2654,9 +2652,8 @@ GC_bool GC_page_was_ever_dirty(struct hblk *h) /* pointer-free system call buffers in the heap are */ /* not protected. */ /*ARGSUSED*/ -void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) -{ -} +void GC_remove_protection(struct hblk *h, word nblocks, + GC_bool is_ptrfree) {} # endif /* DEFAULT_VDB */ @@ -2692,14 +2689,6 @@ GC_bool GC_page_was_dirty(struct hblk *h) return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index)); } -/* Could any valid GC heap pointer ever have been written to this page? */ -/*ARGSUSED*/ -GC_bool GC_page_was_ever_dirty(struct hblk *h) -{ - /* FIXME - implement me. */ - return(TRUE); -} - /* Mark the page containing p as dirty. Logically, this dirties the */ /* entire object. */ void GC_dirty(ptr_t p) @@ -2709,9 +2698,8 @@ void GC_dirty(ptr_t p) } /*ARGSUSED*/ -void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) -{ -} +void GC_remove_protection(struct hblk *h, word nblocks, + GC_bool is_ptrfree) {} # endif /* MANUAL_VDB */ @@ -2815,13 +2803,13 @@ void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) #endif #ifndef DARWIN -STATIC SIG_HNDLR_PTR GC_old_segv_handler = 0; + STATIC SIG_HNDLR_PTR GC_old_segv_handler = 0; /* Also old MSWIN32 ACCESS_VIOLATION filter */ -#if !defined(MSWIN32) && !defined(MSWINCE) -STATIC SIG_HNDLR_PTR GC_old_bus_handler = 0; -STATIC GC_bool GC_old_bus_handler_used_si = FALSE; -STATIC GC_bool GC_old_segv_handler_used_si = FALSE; -#endif +# if !defined(MSWIN32) && !defined(MSWINCE) + STATIC SIG_HNDLR_PTR GC_old_bus_handler = 0; + STATIC GC_bool GC_old_bus_handler_used_si = FALSE; + STATIC GC_bool GC_old_segv_handler_used_si = FALSE; +# endif #endif /* !DARWIN */ #if defined(THREADS) @@ -3072,8 +3060,8 @@ void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) } #if !defined(DARWIN) -void GC_dirty_init(void) -{ + void GC_dirty_init(void) + { # if !defined(MSWIN32) && !defined(MSWINCE) struct sigaction act, oldact; act.sa_flags = SA_RESTART | SA_SIGINFO; @@ -3155,7 +3143,7 @@ void GC_dirty_init(void) /* MPROTECT_VDB is unsupported for WinCE at present. */ /* FIXME: implement it (if possible). */ # endif -} + } #endif /* !DARWIN */ GC_API int GC_CALL GC_incremental_protection_needs(void) @@ -3389,8 +3377,6 @@ ssize_t read(int fd, void *buf, size_t nbyte) /* actually calls. */ #endif -#endif /* 0 */ - /*ARGSUSED*/ GC_bool GC_page_was_ever_dirty(struct hblk *h) { @@ -3401,6 +3387,8 @@ GC_bool GC_page_was_ever_dirty(struct hblk *h) return(TRUE); } +#endif /* 0 */ + # endif /* MPROTECT_VDB */ # ifdef PROC_VDB @@ -3462,9 +3450,8 @@ void GC_dirty_init(void) /* Ignore write hints. They don't help us here. */ /*ARGSUSED*/ -void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) -{ -} +void GC_remove_protection(struct hblk *h, word nblocks, + GC_bool is_ptrfree) {} # define READ(fd,buf,nbytes) read(fd, buf, nbytes) @@ -3541,14 +3528,12 @@ void GC_read_dirty(void) GC_bool GC_page_was_dirty(struct hblk *h) { register word index = PHT_HASH(h); - return get_pht_entry_from_index(GC_grungy_pages, index); } GC_bool GC_page_was_ever_dirty(struct hblk *h) { register word index = PHT_HASH(h); - return get_pht_entry_from_index(GC_written_pages, index); } @@ -3587,14 +3572,13 @@ void GC_read_dirty(void) { static int onhs = 0; int nhs = GC_n_heap_sects; - for( ; onhs < nhs; onhs++ ) { + for(; onhs < nhs; onhs++) { PCR_VD_WriteProtectEnable( GC_heap_sects[onhs].hs_start, GC_heap_sects[onhs].hs_bytes ); } } - if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits) != PCR_ERes_okay) { ABORT("dirty bit read failed"); @@ -3664,7 +3648,6 @@ exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t, thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*); - #define MAX_EXCEPTION_PORTS 16 static struct { @@ -3751,6 +3734,7 @@ void GC_mprotect_stop(void) { GC_mprotect_thread_notify(ID_STOP); } + void GC_mprotect_resume(void) { GC_mprotect_thread_notify(ID_RESUME); @@ -4257,7 +4241,7 @@ catch_exception_raise_state_identity(mach_port_name_t exception_port, GC_in_save_callers = FALSE; #endif -void GC_save_callers (struct callinfo info[NFRAMES]) +void GC_save_callers(struct callinfo info[NFRAMES]) { void * tmp_info[NFRAMES + 1]; int npcs, i; @@ -4298,7 +4282,7 @@ void GC_save_callers (struct callinfo info[NFRAMES]) # define BIAS 0 #endif -void GC_save_callers (struct callinfo info[NFRAMES]) +void GC_save_callers(struct callinfo info[NFRAMES]) { struct frame *frame; struct frame *fp; @@ -4308,7 +4292,7 @@ void GC_save_callers (struct callinfo info[NFRAMES]) asm("movl %%ebp,%0" : "=r"(frame)); fp = frame; # else - frame = (struct frame *) GC_save_regs_in_stack (); + frame = (struct frame *)GC_save_regs_in_stack(); fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS); #endif @@ -4334,7 +4318,7 @@ void GC_save_callers (struct callinfo info[NFRAMES]) #ifdef NEED_CALLINFO /* Print info to stderr. We do NOT hold the allocation lock */ -void GC_print_callers (struct callinfo info[NFRAMES]) +void GC_print_callers(struct callinfo info[NFRAMES]) { int i; static int reentry_count = 0; @@ -4351,7 +4335,7 @@ void GC_print_callers (struct callinfo info[NFRAMES]) # else GC_err_printf("\tCall chain at allocation:\n"); # endif - for (i = 0; i < NFRAMES && !stop ; i++) { + for (i = 0; i < NFRAMES && !stop; i++) { if (info[i].ci_pc == 0) break; # if NARGS > 0 { @@ -4409,7 +4393,7 @@ void GC_print_callers (struct callinfo info[NFRAMES]) ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ); if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') { - will_fail = TRUE; /* Dont try again. */ + will_fail = TRUE; /* Don't try again. */ goto out; } exe_name[ret_code] = '\0'; diff --git a/pthread_stop_world.c b/pthread_stop_world.c index f5f35f6..321726b 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -139,10 +139,10 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context); #if defined(IA64) || defined(HP_PA) || defined(M68K) #ifdef SA_SIGINFO -/*ARGSUSED*/ -STATIC void GC_suspend_handler(int sig, siginfo_t *info, void *context) + /*ARGSUSED*/ + STATIC void GC_suspend_handler(int sig, siginfo_t *info, void *context) #else -STATIC void GC_suspend_handler(int sig) + STATIC void GC_suspend_handler(int sig) #endif { int old_errno = errno; @@ -153,9 +153,9 @@ STATIC void GC_suspend_handler(int sig) /* We believe that in all other cases the full context is already */ /* in the signal handler frame. */ #ifdef SA_SIGINFO -STATIC void GC_suspend_handler(int sig, siginfo_t *info, void *context) + STATIC void GC_suspend_handler(int sig, siginfo_t *info, void *context) #else -STATIC void GC_suspend_handler(int sig) + STATIC void GC_suspend_handler(int sig) #endif { int old_errno = errno; @@ -272,8 +272,6 @@ STATIC void GC_restart_handler(int sig) #endif /* !GC_OPENBSD_THREADS */ -void GC_thr_init(void); - # ifdef IA64 # define IF_IA64(x) x # else @@ -589,16 +587,16 @@ void GC_stop_init(void) /* SIG_THR_RESTART is set in the resulting mask. */ /* It is unmasked by the handler when necessary. */ # ifdef SA_SIGINFO - act.sa_sigaction = GC_suspend_handler; + act.sa_sigaction = GC_suspend_handler; # else - act.sa_handler = GC_suspend_handler; + act.sa_handler = GC_suspend_handler; # endif if (sigaction(SIG_SUSPEND, &act, NULL) != 0) { ABORT("Cannot set SIG_SUSPEND handler"); } # ifdef SA_SIGINFO - act.sa_flags &= ~ SA_SIGINFO; + act.sa_flags &= ~ SA_SIGINFO; # endif act.sa_handler = GC_restart_handler; if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) { diff --git a/pthread_support.c b/pthread_support.c index a601ab9..d5c3953 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -208,14 +208,10 @@ GC_INNER unsigned long GC_lock_holder = NO_THREAD; # define INIT_REAL_SYMS() #endif -void GC_thr_init(void); - static GC_bool parallel_initialized = FALSE; GC_INNER GC_bool GC_need_to_lock = FALSE; -void GC_init_parallel(void); - STATIC long GC_nprocs = 1; /* Number of processors. We may not have */ /* access to all of them, but this is as good */ @@ -542,8 +538,8 @@ STATIC void GC_remove_all_threads_but_me(void) #endif /* HANDLE_FORK */ #ifdef USE_PROC_FOR_LIBRARIES -GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) -{ + GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) + { int i; GC_thread p; @@ -568,15 +564,15 @@ GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) } } return FALSE; -} + } #endif /* USE_PROC_FOR_LIBRARIES */ #ifdef IA64 -/* Find the largest stack_base smaller than bound. May be used */ -/* to find the boundary between a register stack and adjacent */ -/* immediately preceding memory stack. */ -ptr_t GC_greatest_stack_base_below(ptr_t bound) -{ + /* Find the largest stack_base smaller than bound. May be used */ + /* to find the boundary between a register stack and adjacent */ + /* immediately preceding memory stack. */ + ptr_t GC_greatest_stack_base_below(ptr_t bound) + { int i; GC_thread p; ptr_t result = 0; @@ -596,13 +592,13 @@ ptr_t GC_greatest_stack_base_below(ptr_t bound) } } return result; -} + } #endif /* IA64 */ #ifdef GC_LINUX_THREADS -/* Return the number of processors, or i<= 0 if it can't be determined. */ -STATIC int GC_get_nprocs(void) -{ + /* Return the number of processors, or i<= 0 if it can't be determined. */ + STATIC int GC_get_nprocs(void) + { /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ /* appears to be buggy in many cases. */ /* We look for lines "cpu" in /proc/stat. */ @@ -635,7 +631,7 @@ STATIC int GC_get_nprocs(void) } close(f); return result; -} + } #endif /* GC_LINUX_THREADS */ /* We hold the GC lock. Wait until an in-progress GC has finished. */ @@ -643,7 +639,6 @@ STATIC int GC_get_nprocs(void) /* If wait_for_all is true, then we exit with the GC lock held and no */ /* collection in progress; otherwise we just wait for the current GC */ /* to finish. */ -GC_bool GC_collection_in_progress(void); STATIC void GC_wait_for_gc_completion(GC_bool wait_for_all) { GC_ASSERT(I_HOLD_LOCK()); @@ -735,9 +730,9 @@ STATIC void GC_fork_child_proc(void) #endif /* HANDLE_FORK */ #if defined(GC_DGUX386_THREADS) -/* Return the number of processors, or i<= 0 if it can't be determined. */ -STATIC int GC_get_nprocs(void) -{ + /* Return the number of processors, or i<= 0 if it can't be determined. */ + STATIC int GC_get_nprocs(void) + { /* */ int numCpus; struct dg_sys_info_pm_info pm_sysinfo; @@ -756,24 +751,24 @@ STATIC int GC_get_nprocs(void) GC_printf("Number of active CPUs in this system: %d\n", numCpus); # endif return(numCpus); -} + } #endif /* GC_DGUX386_THREADS */ #if defined(GC_NETBSD_THREADS) -static int get_ncpu(void) -{ + static int get_ncpu(void) + { int mib[] = {CTL_HW,HW_NCPU}; int res; size_t len = sizeof(res); sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0); return res; -} + } #endif /* GC_NETBSD_THREADS */ -# if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR) -__thread int GC_dummy_thread_local; -# endif +#if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR) + __thread int GC_dummy_thread_local; +#endif /* We hold the allocation lock. */ void GC_thr_init(void) diff --git a/tests/test.c b/tests/test.c index 2f7022c..346436a 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1406,12 +1406,10 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) GC_noop(GC_expand_hp, GC_add_roots, GC_clear_roots, GC_register_disappearing_link, GC_register_finalizer_ignore_self, - GC_debug_register_displacement, - GC_print_obj, GC_debug_change_stubborn, + GC_debug_register_displacement, GC_debug_change_stubborn, GC_debug_end_stubborn_change, GC_debug_malloc_uncollectable, - GC_debug_free, GC_debug_realloc, GC_generic_malloc_words_small, - GC_init, GC_make_closure, GC_debug_invoke_finalizer, - GC_page_was_ever_dirty, GC_is_fresh, + GC_debug_free, GC_debug_realloc, + GC_generic_malloc_words_small, GC_init, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_max_heap_size, GC_get_bytes_since_gc, GC_get_total_bytes, GC_pre_incr, GC_post_incr); diff --git a/thread_local_alloc.c b/thread_local_alloc.c index fc68c83..21a1d30 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -20,7 +20,6 @@ #endif #include "private/thread_local_alloc.h" -#include "gc_inline.h" #include diff --git a/win32_threads.c b/win32_threads.c index dd8268b..e13b06a 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -155,8 +155,6 @@ GC_INNER GC_bool GC_need_to_lock = FALSE; static GC_bool parallel_initialized = FALSE; -void GC_init_parallel(void); - /* GC_use_DllMain() is currently incompatible with pthreads and WinCE. */ /* It might be possible to get DllMain-based thread registration to */ /* work with Cygwin, but if you try, you are on your own. */ @@ -274,24 +272,26 @@ STATIC volatile GC_bool GC_please_stop = FALSE; STATIC AO_t GC_attached_thread = FALSE; #endif -/* Return TRUE if an thread was attached since we last asked or */ -/* since GC_attached_thread was explicitly reset. */ -GC_bool GC_started_thread_while_stopped(void) -{ -#ifndef GC_NO_DLLMAIN - AO_t result; +#if !defined(__GNUC__) + /* Return TRUE if an thread was attached since we last asked or */ + /* since GC_attached_thread was explicitly reset. */ + GC_bool GC_started_thread_while_stopped(void) + { +# ifndef GC_NO_DLLMAIN + AO_t result; - if (GC_win32_dll_threads) { - AO_nop_full(); /* Prior heap reads need to complete earlier. */ - result = AO_load(&GC_attached_thread); - if (result) { - AO_store(&GC_attached_thread, FALSE); - } - return ((GC_bool)result); + if (GC_win32_dll_threads) { + AO_nop_full(); /* Prior heap reads need to complete earlier. */ + result = AO_load(&GC_attached_thread); + if (result) { + AO_store(&GC_attached_thread, FALSE); + } + return ((GC_bool)result); + } +# endif + return FALSE; } -#endif - return FALSE; -} +#endif /* !__GNUC__ */ /* Thread table used if GC_win32_dll_threads is set. */ /* This is a fixed size array. */ @@ -351,7 +351,10 @@ STATIC GC_thread GC_new_thread(DWORD id) return(result); } -LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info); +#ifdef MPROTECT_VDB + LONG WINAPI GC_write_fault_handler( + struct _EXCEPTION_POINTERS *exc_info); +#endif #if defined(GWW_VDB) && defined(MPROTECT_VDB) GC_bool GC_gww_dirty_init(void); @@ -917,10 +920,6 @@ void GC_push_thread_structures(void) # endif } -#if defined(MPROTECT_VDB) -# include "atomic_ops.h" -#endif - /* Suspend the given thread, if it's still active. */ STATIC void GC_suspend(GC_thread t) { @@ -1334,7 +1333,7 @@ void GC_push_all_stacks(void) /* is found, both *hi and *lo will be set to an address */ /* higher than limit. */ void GC_get_next_stack(char *start, char *limit, - char **lo, char **hi) + char **lo, char **hi) { int i; char * current_min = ADDR_LIMIT; /* Least in-range stack base */ -- 2.7.4