From 4c99405280ddd521a90c899c5fa4c07b30dc05a2 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 2 Apr 2011 08:15:07 +0000 Subject: 2011-04-02 Ivan Maidanski * tests/test.c (reverse_test_inner): Test interior pointer recognition only if ALL_INTERIOR_POINTERS. * tests/test.c (run_one_test): Replace GC_all_interior_pointers with GC_get_all_interior_pointers(); simplify the expression. * tests/test.c (check_heap_stats): Replace GC_bytes_allocd and GC_bytes_allocd_before_gc with GC_get_total_bytes(). * tests/test.c (main): Replace GC_gc_no with GC_get_gc_no(). --HG-- branch : bdwgc --- ChangeLog | 23 +++++++++++++++++------ tests/test.c | 14 +++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02b53a8f..39574847 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-04-02 Ivan Maidanski + + * tests/test.c (reverse_test_inner): Test interior pointer + recognition only if ALL_INTERIOR_POINTERS. + * tests/test.c (run_one_test): Replace GC_all_interior_pointers + with GC_get_all_interior_pointers(); simplify the expression. + * tests/test.c (check_heap_stats): Replace GC_bytes_allocd and + GC_bytes_allocd_before_gc with GC_get_total_bytes(). + * tests/test.c (main): Replace GC_gc_no with GC_get_gc_no(). + 2011-03-27 Ivan Maidanski * dbg_mlc.c (GC_debug_strdup, GC_debug_free): Output a portability @@ -49,12 +59,13 @@ 2011-03-22 Ivan Maidanski - * misc.c (GC_abort): Use _exit() (instead of DebugBreak) on Win32 when - doing code static analysis (to inform the tool that the function is - a no-return one). - * os_dep.c (GC_linux_stack_base): Remove a duplicate validation of the - length of "stat" file; use signed int type for "i", "buf_offset" and - "len" local variables (since read() may return -1). + * misc.c (GC_abort): Use _exit() (instead of DebugBreak) on Win32 + when doing code static analysis (to inform the tool that the + function is a no-return one). + * os_dep.c (GC_linux_stack_base): Remove a duplicate validation + of the length of "stat" file; use signed int type for "i", + "buf_offset" and "len" local variables (since read() may + return -1). 2011-03-20 Ivan Maidanski diff --git a/tests/test.c b/tests/test.c index d8cf4f68..c271073f 100644 --- a/tests/test.c +++ b/tests/test.c @@ -588,9 +588,11 @@ void *GC_CALLBACK reverse_test_inner(void *data) for (i = 0; i < 10; i++) { (void)ints(1, BIG); } - /* Superficially test interior pointer recognition on stack */ +# ifdef ALL_INTERIOR_POINTERS + /* Superficially test interior pointer recognition on stack */ c = (sexpr)((char *)c + sizeof(char *)); d = (sexpr)((char *)d + sizeof(char *)); +# endif GC_FREE((void *)e); @@ -1143,8 +1145,7 @@ void run_one_test(void) # if defined(RS6000) || defined(POWERPC) if (!TEST_FAIL_COUNT(1)) # else - if ((GC_all_interior_pointers && !TEST_FAIL_COUNT(1)) - || (!GC_all_interior_pointers && !TEST_FAIL_COUNT(2))) + if (!TEST_FAIL_COUNT(GC_get_all_interior_pointers() ? 1 : 2)) # endif { GC_printf("GC_is_valid_displacement produced wrong failure indication\n"); @@ -1326,11 +1327,10 @@ void check_heap_stats(void) } } (void)GC_printf("Total number of bytes allocated is %lu\n", - (unsigned long) - (GC_bytes_allocd + GC_bytes_allocd_before_gc)); + (unsigned long)GC_get_total_bytes()); (void)GC_printf("Final heap size is %lu bytes\n", (unsigned long)GC_get_heap_size()); - if (GC_bytes_allocd + GC_bytes_allocd_before_gc < n_tests * + if (GC_get_total_bytes() < n_tests * # ifdef VERY_SMALL_CONFIG 2700000 # else @@ -1703,7 +1703,7 @@ int main(void) check_heap_stats(); (void)fflush(stdout); pthread_attr_destroy(&attr); - GC_printf("Completed %u collections\n", (unsigned)GC_gc_no); + GC_printf("Completed %u collections\n", (unsigned)GC_get_gc_no()); # ifdef PTW32_STATIC_LIB pthread_win32_thread_detach_np (); pthread_win32_process_detach_np (); -- cgit v1.2.1 From edd7149834c52e5df0b756ed3fdc0a1aab33d7d9 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 2 Apr 2011 15:57:24 +0000 Subject: 2011-04-02 Ivan Maidanski * allchblk.c (GC_print_hblkfreelist): Adjust (make uniform across BDWGC) printed message (adjust letters case, terminating dot and new line symbols). * alloc.c (GC_check_fl_marks): Ditto. * backgraph.c (new_back_edges): Ditto. * checksums.c (GC_check_dirty): Ditto. * darwin_stop_world.c (GC_push_all_stacks, GC_suspend_thread_list): Ditto. * dbg_mlc.c (GC_print_type, GC_debug_free, GC_debug_realloc, store_old): Ditto. * dyn_load.c (GC_register_dynamic_libraries): Ditto. * mark.c (GC_initiate_gc, GC_mark_some, GC_mark_from, GC_push_all, GC_push_selected, GC_push_next_marked_dirty): Ditto. * mark_rts.c (GC_exclude_static_roots_inner): Ditto. * os_dep.c (GC_remap, GC_default_push_other_roots, GC_push_thread_structures, GC_dirty_init, GC_read_dirty, catch_exception_raise_state, catch_exception_raise_state_identity, GC_mprotect_thread_notify, GC_mprotect_thread, catch_exception_raise): Ditto. * pthread_stop_world.c (GC_print_sig_mask, GC_push_all_stacks, GC_stop_world, GC_stop_init): Ditto. * pthread_support.c (GC_thr_init, GC_register_my_thread_inner, GC_start_routine): Ditto. * win32_threads.c (GC_register_my_thread_inner, GC_push_all_stacks, GC_win32_start_inner, GC_pthread_join, GC_pthread_start_inner): Ditto. * alloc.c (GC_expand_hp_inner): Realign the code. * mark.c (GC_mark_from, GC_mark_local, GC_do_parallel_mark): Ditto. * misc.c (GC_init): Ditto. * os_dep.c (GC_dirty_init, GC_read_dirty): Ditto. * include/private/gc_pmark.h (PUSH_CONTENTS_HDR): Ditto. * tests/test.c (run_one_test): Ditto. * misc.c (GC_err_puts): Document. * misc.c (GC_err_write): Remove. * os_dep.c (dump_maps): Ditto. * include/private/gc_priv.h (GC_err_write): Ditto. * os_dep.c (GC_print_address_map): Call GC_err_puts() instead of dump_maps() and GC_err_write(). * os_dep.c (GC_read_dirty): Remove redundant brackets. --HG-- branch : bdwgc --- ChangeLog | 43 +++++++++++++ allchblk.c | 2 +- alloc.c | 9 ++- backgraph.c | 2 +- checksums.c | 2 +- darwin_stop_world.c | 4 +- dbg_mlc.c | 10 ++-- dyn_load.c | 2 +- include/private/gc_pmark.h | 3 +- include/private/gc_priv.h | 6 -- mark.c | 62 +++++++++---------- mark_rts.c | 2 +- misc.c | 14 +---- os_dep.c | 146 ++++++++++++++++++++++----------------------- pthread_stop_world.c | 9 ++- pthread_support.c | 8 +-- tests/test.c | 9 +-- win32_threads.c | 24 ++++---- 18 files changed, 186 insertions(+), 171 deletions(-) diff --git a/ChangeLog b/ChangeLog index 39574847..5609e196 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2011-04-02 Ivan Maidanski + + * allchblk.c (GC_print_hblkfreelist): Adjust (make uniform across + BDWGC) printed message (adjust letters case, terminating dot and + new line symbols). + * alloc.c (GC_check_fl_marks): Ditto. + * backgraph.c (new_back_edges): Ditto. + * checksums.c (GC_check_dirty): Ditto. + * darwin_stop_world.c (GC_push_all_stacks, + GC_suspend_thread_list): Ditto. + * dbg_mlc.c (GC_print_type, GC_debug_free, GC_debug_realloc, + store_old): Ditto. + * dyn_load.c (GC_register_dynamic_libraries): Ditto. + * mark.c (GC_initiate_gc, GC_mark_some, GC_mark_from, GC_push_all, + GC_push_selected, GC_push_next_marked_dirty): Ditto. + * mark_rts.c (GC_exclude_static_roots_inner): Ditto. + * os_dep.c (GC_remap, GC_default_push_other_roots, + GC_push_thread_structures, GC_dirty_init, GC_read_dirty, + catch_exception_raise_state, catch_exception_raise_state_identity, + GC_mprotect_thread_notify, GC_mprotect_thread, + catch_exception_raise): Ditto. + * pthread_stop_world.c (GC_print_sig_mask, GC_push_all_stacks, + GC_stop_world, GC_stop_init): Ditto. + * pthread_support.c (GC_thr_init, GC_register_my_thread_inner, + GC_start_routine): Ditto. + * win32_threads.c (GC_register_my_thread_inner, + GC_push_all_stacks, GC_win32_start_inner, GC_pthread_join, + GC_pthread_start_inner): Ditto. + * alloc.c (GC_expand_hp_inner): Realign the code. + * mark.c (GC_mark_from, GC_mark_local, GC_do_parallel_mark): + Ditto. + * misc.c (GC_init): Ditto. + * os_dep.c (GC_dirty_init, GC_read_dirty): Ditto. + * include/private/gc_pmark.h (PUSH_CONTENTS_HDR): Ditto. + * tests/test.c (run_one_test): Ditto. + * misc.c (GC_err_puts): Document. + * misc.c (GC_err_write): Remove. + * os_dep.c (dump_maps): Ditto. + * include/private/gc_priv.h (GC_err_write): Ditto. + * os_dep.c (GC_print_address_map): Call GC_err_puts() instead of + dump_maps() and GC_err_write(). + * os_dep.c (GC_read_dirty): Remove redundant brackets. + 2011-04-02 Ivan Maidanski * tests/test.c (reverse_test_inner): Test interior pointer diff --git a/allchblk.c b/allchblk.c index 440b0510..637d20d0 100644 --- a/allchblk.c +++ b/allchblk.c @@ -120,7 +120,7 @@ void GC_print_hblkfreelist(void) # ifdef USE_MUNMAP if (0 != h) GC_printf("Free list %u:\n", i); # else - if (0 != h) GC_printf("Free list %u (Total size %lu):\n", + if (0 != h) GC_printf("Free list %u (total size %lu):\n", i, (unsigned long)GC_free_bytes[i]); # endif while (h != 0) { diff --git a/alloc.c b/alloc.c index d18b7710..457a0178 100644 --- a/alloc.c +++ b/alloc.c @@ -731,7 +731,7 @@ GC_INNER void GC_set_fl_marks(ptr_t q) for (p = q; p != 0; p = obj_link(p)) { if (!GC_is_marked(p)) { GC_err_printf("Unmarked object %p on list %p\n", p, q); - ABORT("Unmarked local free list entry."); + ABORT("Unmarked local free list entry"); } } } @@ -1149,9 +1149,8 @@ GC_INNER GC_bool GC_expand_hp_inner(word n) return(FALSE); } if (GC_print_stats) { - GC_log_printf("Increasing heap size by %lu after %lu allocated bytes\n", - (unsigned long)bytes, - (unsigned long)GC_bytes_allocd); + GC_log_printf("Increasing heap size by %lu after %lu allocated bytes\n", + (unsigned long)bytes, (unsigned long)GC_bytes_allocd); } /* Adjust heap limits generously for blacklisting to work better. */ /* GC_add_to_heap performs minimal adjustment needed for */ @@ -1273,7 +1272,7 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, return(FALSE); } } else if (GC_fail_count && GC_print_stats) { - GC_printf("Memory available again ...\n"); + GC_printf("Memory available again...\n"); } RESTORE_CANCEL(cancel_state); return(TRUE); diff --git a/backgraph.c b/backgraph.c index c496e003..60d000cf 100644 --- a/backgraph.c +++ b/backgraph.c @@ -98,7 +98,7 @@ static back_edges * new_back_edges(void) return result; } if (GC_n_back_edge_structs >= MAX_BACK_EDGE_STRUCTS - 1) { - ABORT("needed too much space for back edges: adjust " + ABORT("Needed too much space for back edges: adjust " "MAX_BACK_EDGE_STRUCTS"); } return back_edge_space + (GC_n_back_edge_structs++); diff --git a/checksums.c b/checksums.c index e2e5a69f..e565ccd6 100644 --- a/checksums.c +++ b/checksums.c @@ -214,7 +214,7 @@ out: GC_printf("These may be benign (provoked by nonpointer changes)\n"); # ifdef THREADS GC_printf( - "Also expect 1 per thread currently allocating a stubborn obj.\n"); + "Also expect 1 per thread currently allocating a stubborn obj\n"); # endif } for (i = 0; i < GC_n_faulted; ++i) { diff --git a/darwin_stop_world.c b/darwin_stop_world.c index db462295..50e2a539 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -322,7 +322,7 @@ GC_INNER void GC_push_all_stacks(void) if (GC_print_stats == VERBOSE) GC_log_printf("Pushed %d thread stacks\n", nthreads); if (!found_me && !GC_in_thread_creation) - ABORT("Collecting from unknown thread."); + ABORT("Collecting from unknown thread"); GC_total_stacksize = total_size; } @@ -411,7 +411,7 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, if (!found) { /* add it to the GC_mach_threads list */ if (GC_mach_threads_count == GC_MAX_MACH_THREADS) - ABORT("too many threads"); + ABORT("Too many threads"); GC_mach_threads[GC_mach_threads_count].thread = thread; /* default is not suspended */ GC_mach_threads[GC_mach_threads_count].already_suspended = FALSE; diff --git a/dbg_mlc.c b/dbg_mlc.c index d4db3b3b..f8727f6b 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -380,7 +380,7 @@ STATIC void GC_print_type(ptr_t p) GC_err_puts("STUBBORN"); break; default: - GC_err_printf("kind %d, descr 0x%lx", kind, + GC_err_printf("kind=%d descr=0x%lx", kind, (unsigned long)(hhdr -> hb_descr)); } } @@ -778,7 +778,7 @@ GC_API void GC_CALL GC_debug_free(void * p) base = GC_base(p); if (base == 0) { GC_err_printf("Attempt to free invalid pointer %p\n", p); - ABORT("free(invalid pointer)"); + ABORT("Invalid pointer passed to free()"); } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { GC_err_printf( @@ -857,7 +857,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) base = GC_base(p); if (base == 0) { GC_err_printf("Attempt to reallocate invalid pointer %p\n", p); - ABORT("realloc(invalid pointer)"); + ABORT("Invalid pointer passed to realloc()"); } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { GC_err_printf( @@ -888,7 +888,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) default: result = NULL; /* initialized to prevent warning. */ GC_err_printf("GC_debug_realloc: encountered bad kind\n"); - ABORT("bad kind"); + ABORT("Bad kind"); } # ifdef SHORT_DBG_HDRS old_sz = GC_size(base) - sizeof(oh); @@ -1027,7 +1027,7 @@ static void store_old(void *obj, GC_finalization_proc my_old_fn, return; } if (my_old_fn != GC_debug_invoke_finalizer) { - GC_err_printf("Debuggable object at %p had non-debug finalizer.\n", + GC_err_printf("Debuggable object at %p had a non-debug finalizer\n", obj); /* This should probably be fatal. */ } else { diff --git a/dyn_load.c b/dyn_load.c index 49448a1d..698e8aa4 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -383,7 +383,7 @@ STATIC word GC_register_map_entries(char *maps) GC_INNER void GC_register_dynamic_libraries(void) { if (!GC_register_map_entries(GC_get_maps())) - ABORT("Failed to read /proc for library registration."); + ABORT("Failed to read /proc for library registration"); } /* We now take care of the main data segment ourselves: */ diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index c0232cc4..a24dda83 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -358,8 +358,7 @@ exit_label: ; \ (unsigned)GC_gc_no)); \ TRACE_TARGET(base, \ GC_log_printf("GC:%u: marking %p from %p instead\n", \ - (unsigned)GC_gc_no, \ - base, source)); \ + (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); \ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 816bb0f0..b8f48792 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1951,12 +1951,6 @@ void GC_err_puts(const char *s); /* Write s to stderr, don't buffer, don't add */ /* newlines, don't ... */ -#if defined(LINUX) && !defined(SMALL_CONFIG) - GC_INNER void GC_err_write(const char *buf, size_t len); - /* Write buf to stderr, don't buffer, don't add */ - /* newlines, don't ... */ -#endif - GC_EXTERN unsigned GC_fail_count; /* How many consecutive GC/expansion failures? */ /* Reset by GC_allochblk(); defined in alloc.c. */ diff --git a/mark.c b/mark.c index e69d7dc2..deb3cdf7 100644 --- a/mark.c +++ b/mark.c @@ -272,7 +272,7 @@ GC_INNER void GC_initiate_gc(void) if (GC_mark_state == MS_NONE) { GC_mark_state = MS_PUSH_RESCUERS; } else if (GC_mark_state != MS_INVALID) { - ABORT("unexpected state"); + ABORT("Unexpected state"); } /* else this is really a full collection, and mark */ /* bits are invalid. */ scan_ptr = 0; @@ -576,8 +576,8 @@ static void alloc_mark_stack(size_t); handle_ex: /* Exception handler starts here for all cases. */ if (GC_print_stats) { - GC_log_printf("Caught ACCESS_VIOLATION in marker. " - "Memory mapping disappeared.\n"); + GC_log_printf( + "Caught ACCESS_VIOLATION in marker; memory mapping disappeared\n"); } /* We have bad roots on the stack. Discard mark stack. */ @@ -670,9 +670,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr >= current_p && GC_trace_addr < current_p + descr) { - GC_log_printf("GC:%u Large section; start %p len %lu\n", - (unsigned)GC_gc_no, current_p, - (unsigned long) descr); + GC_log_printf("GC:%u Large section; start %p len %lu\n", + (unsigned)GC_gc_no, current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ # ifdef PARALLEL_MARK @@ -688,9 +687,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr >= current_p && GC_trace_addr < current_p + descr) { - GC_log_printf("GC:%u splitting (parallel) %p at %p\n", - (unsigned)GC_gc_no, current_p, - current_p + new_size); + GC_log_printf("GC:%u Splitting (parallel) %p at %p\n", + (unsigned)GC_gc_no, current_p, current_p + new_size); } # endif /* ENABLE_TRACE */ current_p += new_size; @@ -705,8 +703,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr >= current_p && GC_trace_addr < current_p + descr) { - GC_log_printf("GC:%u splitting %p at %p\n", - (unsigned)GC_gc_no, current_p, limit); + GC_log_printf("GC:%u Splitting %p at %p\n", + (unsigned)GC_gc_no, current_p, limit); } # endif /* ENABLE_TRACE */ /* Make sure that pointers overlapping the two ranges are */ @@ -718,9 +716,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr >= current_p && GC_trace_addr < current_p + WORDS_TO_BYTES(WORDSZ-2)) { - GC_log_printf("GC:%u Tracing from %p bitmap descr %lu\n", - (unsigned)GC_gc_no, current_p, - (unsigned long) descr); + GC_log_printf("GC:%u Tracing from %p bitmap descr %lu\n", + (unsigned)GC_gc_no, current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ descr &= ~GC_DS_TAGS; @@ -734,8 +731,7 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { GC_log_printf("GC:%u Considering(3) %p -> %p\n", - (unsigned)GC_gc_no, current_p, - (ptr_t) current); + (unsigned)GC_gc_no, current_p, (ptr_t)current); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)current, mark_stack_top, @@ -752,9 +748,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, if (GC_trace_addr >= current_p && GC_base(current_p) != 0 && GC_base(current_p) == GC_base(GC_trace_addr)) { - GC_log_printf("GC:%u Tracing from %p proc descr %lu\n", - (unsigned)GC_gc_no, current_p, - (unsigned long) descr); + GC_log_printf("GC:%u Tracing from %p proc descr %lu\n", + (unsigned)GC_gc_no, current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ credit -= GC_PROC_BYTES; @@ -805,8 +800,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr >= current_p && GC_trace_addr < limit) { - GC_log_printf("GC:%u Tracing from %p len %lu\n", - (int)GC_gc_no, current_p, (unsigned long) descr); + GC_log_printf("GC:%u Tracing from %p len %lu\n", + (int)GC_gc_no, current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ /* The simple case in which we're scanning a range. */ @@ -862,8 +857,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, PREFETCH((ptr_t)current); # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { - GC_log_printf("GC:%u Considering(1) %p -> %p\n", - (unsigned)GC_gc_no, current_p, (ptr_t) current); + GC_log_printf("GC:%u Considering(1) %p -> %p\n", + (unsigned)GC_gc_no, current_p, (ptr_t)current); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)current, mark_stack_top, @@ -878,8 +873,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, /* validity test. */ # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { - GC_log_printf("GC:%u Considering(2) %p -> %p\n", - (unsigned)GC_gc_no, current_p, (ptr_t) deferred); + GC_log_printf("GC:%u Considering(2) %p -> %p\n", + (unsigned)GC_gc_no, current_p, (ptr_t)deferred); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)deferred, mark_stack_top, @@ -1106,8 +1101,8 @@ STATIC void GC_mark_local(mse *local_mark_stack, int id) GC_helper_count--; if (0 == GC_helper_count) need_to_notify = TRUE; if (GC_print_stats == VERBOSE) - GC_log_printf( - "Finished mark helper %lu\n", (unsigned long)id); + GC_log_printf("Finished mark helper %lu\n", + (unsigned long)id); GC_release_mark_lock(); if (need_to_notify) GC_notify_all_marker(); return; @@ -1150,7 +1145,7 @@ STATIC void GC_do_parallel_mark(void) ABORT("Tried to start parallel mark in bad state"); if (GC_print_stats == VERBOSE) GC_log_printf("Starting marking for mark phase number %lu\n", - (unsigned long)GC_mark_no); + (unsigned long)GC_mark_no); GC_first_nonempty = (AO_t)GC_mark_stack; GC_active_count = 0; GC_helper_count = 1; @@ -1165,9 +1160,8 @@ STATIC void GC_do_parallel_mark(void) while (GC_helper_count > 0) GC_wait_marker(); /* GC_helper_count cannot be incremented while GC_help_wanted == FALSE */ if (GC_print_stats == VERBOSE) - GC_log_printf( - "Finished marking for mark phase number %lu\n", - (unsigned long)GC_mark_no); + GC_log_printf("Finished marking for mark phase number %lu\n", + (unsigned long)GC_mark_no); GC_mark_no++; GC_release_mark_lock(); GC_notify_all_marker(); @@ -1280,7 +1274,7 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) if (top == 0 || bottom == top) return; GC_mark_stack_top++; if (GC_mark_stack_top >= GC_mark_stack_limit) { - ABORT("unexpected mark stack overflow"); + ABORT("Unexpected mark stack overflow"); } length = top - bottom; # if GC_DS_TAGS > ALIGNMENT - 1 @@ -1342,7 +1336,7 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) } } if (GC_mark_stack_top >= GC_mark_stack_limit) { - ABORT("unexpected mark stack overflow"); + ABORT("Unexpected mark stack overflow"); } } @@ -1820,7 +1814,7 @@ STATIC struct hblk * GC_push_next_marked(struct hblk *h) { hdr * hhdr = HDR(h); - if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); } + if (!GC_dirty_maintained) ABORT("Dirty bits not set up"); for (;;) { if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) { diff --git a/mark_rts.c b/mark_rts.c index d808e8e5..3ae8e614 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -426,7 +426,7 @@ GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish) if (0 != next) { if ((word)(next -> e_start) < (word) finish) { /* incomplete error check. */ - ABORT("exclusion ranges overlap"); + ABORT("Exclusion ranges overlap"); } if ((word)(next -> e_start) == (word) finish) { /* extend old range backwards */ diff --git a/misc.c b/misc.c index 6533843b..b9a01e5a 100644 --- a/misc.c +++ b/misc.c @@ -924,8 +924,7 @@ GC_API void GC_CALL GC_init(void) if (sz_str != NULL) { initial_heap_sz = (word)STRTOULL(sz_str, NULL, 10); if (initial_heap_sz <= MINHINCR * HBLKSIZE) { - WARN("Bad initial heap size %s - ignoring it.\n", - sz_str); + WARN("Bad initial heap size %s - ignoring it.\n", sz_str); } initial_heap_sz = divHBLKSZ(initial_heap_sz); } @@ -935,8 +934,7 @@ GC_API void GC_CALL GC_init(void) if (sz_str != NULL) { word max_heap_sz = (word)STRTOULL(sz_str, NULL, 10); if (max_heap_sz < initial_heap_sz * HBLKSIZE) { - WARN("Bad maximum heap size %s - ignoring it.\n", - sz_str); + WARN("Bad maximum heap size %s - ignoring it.\n", sz_str); } if (0 == GC_max_retries) GC_max_retries = 2; GC_set_max_heap_size(max_heap_sz); @@ -1301,18 +1299,12 @@ void GC_log_printf(const char *format, ...) ABORT("write to log failed"); } +/* This is equivalent to GC_err_printf("%s",s). */ void GC_err_puts(const char *s) { if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed"); } -#if defined(LINUX) && !defined(SMALL_CONFIG) - GC_INNER 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) { GC_err_printf(msg, arg); diff --git a/os_dep.c b/os_dep.c index bc53d7ce..398d7d4b 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2469,7 +2469,7 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) if (GC_print_stats) GC_printf("Mprotect failed at %p (length %lu) with errno %d\n", start_addr, (unsigned long)len, errno); - ABORT("Mprotect remapping failed"); + ABORT("mprotect remapping failed"); } GC_unmapped_bytes -= len; # endif @@ -2565,8 +2565,8 @@ STATIC void GC_default_push_other_roots(void) /* Traverse all thread stacks. */ if (PCR_ERes_IsErr( PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0)) - || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) { - ABORT("Thread stack marking failed\n"); + || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) { + ABORT("Thread stack marking failed"); } } @@ -2587,12 +2587,12 @@ STATIC void GC_default_push_other_roots(void) # ifdef SN_TARGET_PS3 STATIC void GC_default_push_other_roots(void) { - ABORT("GC_default_push_other_roots is not implemented\n"); + ABORT("GC_default_push_other_roots is not implemented"); } void GC_push_thread_structures(void) { - ABORT("GC_push_thread_structures is not implemented\n"); + ABORT("GC_push_thread_structures is not implemented"); } # endif /* SN_TARGET_PS3 */ @@ -2924,14 +2924,14 @@ STATIC void GC_default_push_other_roots(void) FALSE, VM_PROT_READ \ | (pages_executable ? VM_PROT_EXECUTE : 0)) \ != KERN_SUCCESS) { \ - ABORT("vm_protect (PROTECT) failed"); \ + ABORT("vm_protect(PROTECT) failed"); \ } # define UNPROTECT(addr,len) \ if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ FALSE, (VM_PROT_READ | VM_PROT_WRITE) \ | (pages_executable ? VM_PROT_EXECUTE : 0)) \ != KERN_SUCCESS) { \ - ABORT("vm_protect (UNPROTECT) failed"); \ + ABORT("vm_protect(UNPROTECT) failed"); \ } # elif !defined(MSWIN32) && !defined(MSWINCE) @@ -3631,7 +3631,8 @@ GC_INNER void GC_dirty_init(void) if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { register int i; - for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1); + for (i = 0; i < PHT_SIZE; i++) + GC_written_pages[i] = (word)(-1); if (GC_print_stats == VERBOSE) GC_log_printf( "Allocated bytes:%lu:all pages may have been written\n", @@ -3673,58 +3674,60 @@ GC_INNER void GC_read_dirty(void) bufp = GC_proc_buf; if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { + /* Retry with larger buffer. */ + word new_size = 2 * GC_proc_buf_size; + char *new_buf; + if (GC_print_stats) GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n", (unsigned long)GC_proc_buf_size); - { - /* Retry with larger buffer. */ - word new_size = 2 * GC_proc_buf_size; - char * new_buf = GC_scratch_alloc(new_size); - if (new_buf != 0) { - GC_proc_buf = bufp = new_buf; - GC_proc_buf_size = new_size; - } - if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { - WARN("Insufficient space for /proc read\n", 0); - /* Punt: */ - memset(GC_grungy_pages, 0xff, sizeof (page_hash_table)); - memset(GC_written_pages, 0xff, sizeof(page_hash_table)); - return; - } + new_buf = GC_scratch_alloc(new_size); + if (new_buf != 0) { + GC_proc_buf = bufp = new_buf; + GC_proc_buf_size = new_size; + } + if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { + WARN("Insufficient space for /proc read\n", 0); + /* Punt: */ + memset(GC_grungy_pages, 0xff, sizeof (page_hash_table)); + memset(GC_written_pages, 0xff, sizeof(page_hash_table)); + return; } } - /* Copy dirty bits into GC_grungy_pages */ - nmaps = ((struct prpageheader *)bufp) -> pr_nmap; - /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n", - nmaps, PG_REFERENCED, PG_MODIFIED); */ - bufp = bufp + sizeof(struct prpageheader); - for (i = 0; i < nmaps; i++) { - map = (struct prasmap *)bufp; - vaddr = (ptr_t)(map -> pr_vaddr); - ps = map -> pr_pagesize; - np = map -> pr_npage; - /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */ - limit = vaddr + ps * np; - bufp += sizeof (struct prasmap); - for (current_addr = vaddr; - current_addr < limit; current_addr += ps) { - if ((*bufp++) & PG_MODIFIED) { - register struct hblk * h = (struct hblk *) current_addr; - - while ((ptr_t)h < current_addr + ps) { - register word index = PHT_HASH(h); - - set_pht_entry_from_index(GC_grungy_pages, index); - h++; - } + + /* Copy dirty bits into GC_grungy_pages */ + nmaps = ((struct prpageheader *)bufp) -> pr_nmap; + /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n", + nmaps, PG_REFERENCED, PG_MODIFIED); */ + bufp = bufp + sizeof(struct prpageheader); + for (i = 0; i < nmaps; i++) { + map = (struct prasmap *)bufp; + vaddr = (ptr_t)(map -> pr_vaddr); + ps = map -> pr_pagesize; + np = map -> pr_npage; + /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */ + limit = vaddr + ps * np; + bufp += sizeof (struct prasmap); + for (current_addr = vaddr; + current_addr < limit; current_addr += ps) { + if ((*bufp++) & PG_MODIFIED) { + register struct hblk * h = (struct hblk *) current_addr; + + while ((ptr_t)h < current_addr + ps) { + register word index = PHT_HASH(h); + + set_pht_entry_from_index(GC_grungy_pages, index); + h++; } } - bufp += sizeof(long) - 1; - bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1)); } + bufp += sizeof(long) - 1; + bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1)); + } + /* Update GC_written_pages. */ - GC_or_pages(GC_written_pages, GC_grungy_pages); + GC_or_pages(GC_written_pages, GC_grungy_pages); } #undef READ @@ -3766,7 +3769,7 @@ GC_INNER void GC_dirty_init(void) } if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE) != PCR_ERes_okay) { - ABORT("dirty bit initialization failed"); + ABORT("Dirty bit initialization failed"); } } @@ -3785,7 +3788,7 @@ GC_INNER void GC_read_dirty(void) if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits) != PCR_ERes_okay) { - ABORT("dirty bit read failed"); + ABORT("Dirty bit read failed"); } } @@ -3864,7 +3867,7 @@ catch_exception_raise_state(mach_port_name_t exception_port, int exception, thread_state_t old_state, int old_stateCnt, thread_state_t new_state, int new_stateCnt) { - ABORT("catch_exception_raise_state"); + ABORT("Unexpected catch_exception_raise_state invocation"); return(KERN_INVALID_ARGUMENT); } @@ -3876,7 +3879,7 @@ catch_exception_raise_state_identity(mach_port_name_t exception_port, thread_state_t old_state, int old_stateCnt, thread_state_t new_state, int new_stateCnt) { - ABORT("catch_exception_raise_state_identity"); + ABORT("Unexpected catch_exception_raise_state_identity invocation"); return(KERN_INVALID_ARGUMENT); } @@ -3950,7 +3953,7 @@ typedef enum { if (r != MACH_MSG_SUCCESS) ABORT("mach_msg failed in GC_mprotect_thread_notify"); if (buf.msg.head.msgh_id != ID_ACK) - ABORT("invalid ack in GC_mprotect_thread_notify"); + ABORT("Invalid ack in GC_mprotect_thread_notify"); } /* Should only be called by the mprotect thread */ @@ -4028,7 +4031,7 @@ STATIC void *GC_mprotect_thread(void *arg) continue; } if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME)) - ABORT("out of order mprotect thread request"); + ABORT("Out of order mprotect thread request"); } # endif /* THREADS */ @@ -4113,8 +4116,8 @@ GC_INNER void GC_dirty_init(void) exception_mask_t mask; if (GC_print_stats == VERBOSE) - GC_log_printf("Initializing mach/darwin mprotect virtual dirty bit " - "implementation\n"); + GC_log_printf( + "Initializing mach/darwin mprotect virtual dirty bit implementation\n"); # ifdef BROKEN_EXCEPTION_HANDLING WARN("Enabling workarounds for various darwin " "exception handling bugs.\n", 0); @@ -4174,7 +4177,7 @@ GC_INNER void GC_dirty_init(void) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART|SA_SIGINFO; if (sigaction(SIGBUS, &sa, &oldsa) < 0) - ABORT("sigaction"); + ABORT("sigaction failed"); if ((SIG_HNDLR_PTR)oldsa.sa_handler != SIG_DFL) { if (GC_print_stats == VERBOSE) GC_err_printf("Replaced other SIGBUS handler\n"); @@ -4335,8 +4338,8 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, return KERN_SUCCESS; } - GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n" - "Aborting...\n", addr); + GC_err_printf( + "Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n", addr); /* Can't pass it along to the signal handler because that is ignoring SIGBUS signals. We also shouldn't call ABORT here as signals don't always work too well from the exception handler. */ @@ -4724,21 +4727,12 @@ GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]) #endif /* NEED_CALLINFO */ #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) - -/* Dump /proc/self/maps to GC_stderr, to enable looking up names for - addresses in FIND_LEAK output. */ - -static word dump_maps(char *maps) -{ - GC_err_write(maps, strlen(maps)); - return 1; -} - -void GC_print_address_map(void) -{ + /* Dump /proc/self/maps to GC_stderr, to enable looking up names for */ + /* addresses in FIND_LEAK output. */ + void GC_print_address_map(void) + { GC_err_printf("---------- Begin address map ----------\n"); - dump_maps(GC_get_maps()); + GC_err_puts(GC_get_maps()); GC_err_printf("---------- End address map ----------\n"); -} - + } #endif /* LINUX && ELF */ diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 0ef0d221..0687bbc8 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -65,7 +65,7 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; int i; if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) - ABORT("pthread_sigmask"); + ABORT("pthread_sigmask failed"); GC_printf("Blocked: "); for (i = 1; i < NSIG; i++) { if (sigismember(&blocked, i)) { GC_printf("%d ", i); } @@ -361,7 +361,7 @@ GC_INNER void GC_push_all_stacks(void) GC_log_printf("Pushed %d thread stacks\n", (int)nthreads); } if (!found_me && !GC_in_thread_creation) - ABORT("Collecting from unknown thread."); + ABORT("Collecting from unknown thread"); GC_total_stacksize = total_size; } @@ -543,8 +543,7 @@ GC_INNER void GC_stop_world(void) int newly_sent = GC_suspend_all(); if (GC_print_stats) { - GC_log_printf("Resent %d signals after timeout\n", - newly_sent); + GC_log_printf("Resent %d signals after timeout\n", newly_sent); } sem_getvalue(&GC_suspend_ack_sem, &ack_count); if (newly_sent < n_live_threads - ack_count) { @@ -840,7 +839,7 @@ GC_INNER void GC_stop_init(void) GC_retry_signals = FALSE; } if (GC_print_stats && GC_retry_signals) { - GC_log_printf("Will retry suspend signal if necessary.\n"); + GC_log_printf("Will retry suspend signal if necessary\n"); } # endif /* !GC_OPENBSD_THREADS && !NACL */ } diff --git a/pthread_support.c b/pthread_support.c index 68384bc6..c78faeaa 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -423,7 +423,7 @@ static void start_mark_threads(void) ABORT("pthread_attr_getstacksize failed"); if (old_size < MIN_STACK_SIZE) { if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0) - ABORT("pthread_attr_setstacksize failed"); + ABORT("pthread_attr_setstacksize failed"); } } # endif /* HPUX || GC_DGUX386_THREADS */ @@ -921,7 +921,7 @@ GC_INNER void GC_thr_init(void) { GC_thread t = GC_new_thread(pthread_self()); if (t == NULL) - ABORT("Failed to allocate memory for the initial thread."); + ABORT("Failed to allocate memory for the initial thread"); # ifdef GC_DARWIN_THREADS t -> stop_info.mach_thread = mach_thread_self(); # else @@ -1334,7 +1334,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, me = GC_new_thread(my_pthread); GC_in_thread_creation = FALSE; if (me == 0) - ABORT("Failed to allocate memory for thread registering."); + ABORT("Failed to allocate memory for thread registering"); # ifdef GC_DARWIN_THREADS me -> stop_info.mach_thread = mach_thread_self(); # else @@ -1442,7 +1442,7 @@ STATIC void * GC_start_routine(void * arg) GC_disable(); # endif if (GC_get_stack_base(&sb) != GC_SUCCESS) - ABORT("Failed to get thread stack base."); + ABORT("Failed to get thread stack base"); # ifdef REDIRECT_MALLOC GC_enable(); # endif diff --git a/tests/test.c b/tests/test.c index c271073f..66ae86e1 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1217,10 +1217,11 @@ void run_one_test(void) /* Run reverse_test a second time, so we hopefully notice corruption. */ reverse_test(); if (GC_print_stats) { - GET_TIME(reverse_time); - time_diff = MS_TIME_DIFF(reverse_time, start_time); - GC_log_printf("-------------Finished second reverse_test at time %u (%p)\n", - (unsigned) time_diff, &start_time); + GET_TIME(reverse_time); + time_diff = MS_TIME_DIFF(reverse_time, start_time); + GC_log_printf( + "-------------Finished second reverse_test at time %u (%p)\n", + (unsigned)time_diff, &start_time); } /* GC_allocate_ml and GC_need_to_lock are no longer exported, and */ /* AO_fetch_and_add1() may be unavailable to update a counter. */ diff --git a/win32_threads.c b/win32_threads.c index 1e07a389..796b9096 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -431,7 +431,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, /* FIXME: We should eventually declare Win95 dead and use AO_ */ /* primitives here. */ if (i == MAX_THREADS - 1) - ABORT("too many threads"); + ABORT("Too many threads"); } /* Update GC_max_thread_index if necessary. The following is */ /* safe, and unlike CompareExchange-based solutions seems to work */ @@ -455,7 +455,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, me = GC_new_thread(thread_id); GC_in_thread_creation = FALSE; if (me == 0) - ABORT("Failed to allocate memory for thread registering."); + ABORT("Failed to allocate memory for thread registering"); } # ifdef GC_PTHREADS /* me can be NULL -> segfault */ @@ -1358,7 +1358,7 @@ GC_INNER void GC_push_all_stacks(void) } # endif if (!found_me && !GC_in_thread_creation) - ABORT("Collecting from unknown thread."); + ABORT("Collecting from unknown thread"); GC_total_stacksize = total_size; } @@ -2020,7 +2020,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, } # if DEBUG_WIN32_THREADS - GC_printf("thread 0x%x returned from start routine.\n", + GC_printf("thread 0x%x returned from start routine\n", (unsigned)GetCurrentThreadId()); # endif return ret; @@ -2342,12 +2342,12 @@ GC_INNER void GC_thr_init(void) GC_thread joinee; # if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n", + GC_printf("thread 0x%x(0x%x) is joining thread 0x%x\n", (int)pthread_self(), (int)GetCurrentThreadId(), (int)pthread_id); # endif # if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n", + GC_printf("thread 0x%x(0x%x) is joining thread 0x%x\n", (int)(pthread_self()).p, (int)GetCurrentThreadId(), pthread_id.p); # endif @@ -2378,12 +2378,12 @@ GC_INNER void GC_thr_init(void) } /* otherwise DllMain handles it. */ # if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n", + GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x\n", (int)pthread_self(), (int)GetCurrentThreadId(), (int)pthread_id); # endif # if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n", + GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x\n", (int)(pthread_self()).p, (int)GetCurrentThreadId(), pthread_id.p); # endif @@ -2481,11 +2481,11 @@ GC_INNER void GC_thr_init(void) pthread_cleanup_pop(1); # if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) returned from start routine.\n", + GC_printf("thread 0x%x(0x%x) returned from start routine\n", (int)pthread_self(),(int)GetCurrentThreadId()); # endif # if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) returned from start routine.\n", + GC_printf("thread 0x%x(0x%x) returned from start routine\n", (int)(pthread_self()).p, (int)GetCurrentThreadId()); # endif return(result); @@ -2503,11 +2503,11 @@ GC_INNER void GC_thr_init(void) GC_ASSERT(!GC_win32_dll_threads); # if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) called pthread_exit().\n", + GC_printf("thread 0x%x(0x%x) called pthread_exit()\n", (int)pthread_self(),(int)GetCurrentThreadId()); # endif # if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) called pthread_exit().\n", + GC_printf("thread 0x%x(0x%x) called pthread_exit()\n", (int)(pthread_self()).p,(int)GetCurrentThreadId()); # endif -- cgit v1.2.1 From ff85afcc3908a220edf9b369b3abe64bda9aa623 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 3 Apr 2011 13:43:18 +0000 Subject: 2011-04-03 Ivan Maidanski * tests/test.c (cons, small_cons, gcj_cons, check_ints, check_uncollectable_ints, print_int_list, check_marks_int_list, fork_a_thread, finalizer, mktree, chktree, alloc8bytes, alloc_small, tree_test, typed_test, check_heap_stats, WinMain, test, main): Remove unnecessary casts of GC_printf calls to void. --HG-- branch : bdwgc --- ChangeLog | 8 +++ tests/test.c | 177 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 96 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5609e196..4c562a3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-04-03 Ivan Maidanski + + * tests/test.c (cons, small_cons, gcj_cons, check_ints, + check_uncollectable_ints, print_int_list, check_marks_int_list, + fork_a_thread, finalizer, mktree, chktree, alloc8bytes, + alloc_small, tree_test, typed_test, check_heap_stats, WinMain, + test, main): Remove unnecessary casts of GC_printf calls to void. + 2011-04-02 Ivan Maidanski * allchblk.c (GC_print_hblkfreelist): Adjust (make uniform across diff --git a/tests/test.c b/tests/test.c index 66ae86e1..ee0cd97c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -113,7 +113,7 @@ int realloc_count = 0; } if(ret==NULL){ GC_printf("Out of memory, (typed allocations are not directly " - "supported with the GC_AMIGA_FASTALLOC option.)\n"); + "supported with the GC_AMIGA_FASTALLOC option.)\n"); FAIL; } } @@ -128,7 +128,7 @@ int realloc_count = 0; } if(ret==NULL){ GC_printf("Out of memory, (typed allocations are not directly " - "supported with the GC_AMIGA_FASTALLOC option.)\n"); + "supported with the GC_AMIGA_FASTALLOC option.)\n"); FAIL; } } @@ -187,13 +187,13 @@ sexpr cons (sexpr x, sexpr y) stubborn_count++; r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra); if (r == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } for (p = (int *)r; ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) { if (*p) { - (void)GC_printf("Found nonzero at %p - allocator is broken\n", p); + GC_printf("Found nonzero at %p - allocator is broken\n", p); FAIL; } *p = (int)((13 << 12) + ((p - (int *)r) & 0xfff)); @@ -263,7 +263,7 @@ sexpr small_cons (sexpr x, sexpr y) collectable_count++; r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); if (r == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } r -> sexpr_car = x; @@ -278,7 +278,7 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) uncollectable_count++; r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); if (r == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } r -> sexpr_car = x; @@ -298,7 +298,7 @@ sexpr gcj_cons(sexpr x, sexpr y) + sizeof(struct fake_vtable*), &gcj_class_struct2); if (r == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } result = (sexpr)(r + 1); @@ -376,13 +376,13 @@ sexpr uncollectable_ints(int low, int up) void check_ints(sexpr list, int low, int up) { if (SEXPR_TO_INT(car(car(list))) != low) { - (void)GC_printf( + GC_printf( "List reversal produced incorrect list - collector is broken\n"); FAIL; } if (low == up) { if (cdr(list) != nil) { - (void)GC_printf("List too long - collector is broken\n"); + GC_printf("List too long - collector is broken\n"); FAIL; } } else { @@ -395,15 +395,14 @@ void check_ints(sexpr list, int low, int up) void check_uncollectable_ints(sexpr list, int low, int up) { if (SEXPR_TO_INT(car(car(list))) != low) { - (void)GC_printf( - "Uncollectable list corrupted - collector is broken\n"); + GC_printf("Uncollectable list corrupted - collector is broken\n"); FAIL; } if (low == up) { - if (UNCOLLECTABLE_CDR(list) != nil) { - (void)GC_printf("Uncollectable list too long - collector is broken\n"); - FAIL; - } + if (UNCOLLECTABLE_CDR(list) != nil) { + GC_printf("Uncollectable list too long - collector is broken\n"); + FAIL; + } } else { check_uncollectable_ints(UNCOLLECTABLE_CDR(list), low+1, up); } @@ -413,14 +412,14 @@ void check_uncollectable_ints(sexpr list, int low, int up) void print_int_list(sexpr x) { if (is_nil(x)) { - (void)GC_printf("NIL\n"); + GC_printf("NIL\n"); } else { - (void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x)))); + GC_printf("(%d)", SEXPR_TO_INT(car(car(x)))); if (!is_nil(cdr(x))) { - (void)GC_printf(", "); - (void)print_int_list(cdr(x)); + GC_printf(", "); + print_int_list(cdr(x)); } else { - (void)GC_printf("\n"); + GC_printf("\n"); } } } @@ -433,15 +432,16 @@ void check_marks_int_list(sexpr x) else GC_printf("[mkd:%p]", x); if (is_nil(x)) { - (void)GC_printf("NIL\n"); + GC_printf("NIL\n"); } else { - if (!GC_is_marked((ptr_t)car(x))) GC_printf("[unm car:%p]", car(x)); - (void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x)))); + if (!GC_is_marked((ptr_t)car(x))) + GC_printf("[unm car:%p]", car(x)); + GC_printf("(%d)", SEXPR_TO_INT(car(car(x)))); if (!is_nil(cdr(x))) { - (void)GC_printf(", "); - (void)check_marks_int_list(cdr(x)); + GC_printf(", "); + check_marks_int_list(cdr(x)); } else { - (void)GC_printf("\n"); + GC_printf("\n"); } } } @@ -477,11 +477,11 @@ void check_marks_int_list(sexpr x) pthread_t t; int code; if ((code = pthread_create(&t, 0, tiny_reverse_test, 0)) != 0) { - (void)GC_printf("Small thread creation failed %d\n", code); + GC_printf("Small thread creation failed %d\n", code); FAIL; } if ((code = pthread_join(t, 0)) != 0) { - (void)GC_printf("Small thread join failed %d\n", code); + GC_printf("Small thread join failed %d\n", code); FAIL; } } @@ -493,13 +493,13 @@ void check_marks_int_list(sexpr x) HANDLE h; h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id); if (h == (HANDLE)NULL) { - (void)GC_printf("Small thread creation failed %d\n", - (int)GetLastError()); + GC_printf("Small thread creation failed %d\n", + (int)GetLastError()); FAIL; } if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) { - (void)GC_printf("Small thread wait failed %d\n", - (int)GetLastError()); + GC_printf("Small thread wait failed %d\n", + (int)GetLastError()); FAIL; } } @@ -677,7 +677,7 @@ void GC_CALLBACK finalizer(void * obj, void * client_data) EnterCriticalSection(&incr_cs); # endif if ((int)(GC_word)client_data != t -> level) { - (void)GC_printf("Wrong finalization data - collector is broken\n"); + GC_printf("Wrong finalization data - collector is broken\n"); FAIL; } finalized_count++; @@ -716,13 +716,13 @@ tn * mktree(int n) live_indicators = (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word)); if (!live_indicators) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } # endif if (n == 0) return(0); if (result == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); exit(1); } result -> level = n; @@ -793,12 +793,12 @@ tn * mktree(int n) void chktree(tn *t, int n) { if (n == 0 && t != 0) { - (void)GC_printf("Clobbered a leaf - collector is broken\n"); + GC_printf("Clobbered a leaf - collector is broken\n"); FAIL; } if (n == 0) return; if (t -> level != n) { - (void)GC_printf("Lost a node at level %d - collector is broken\n", n); + GC_printf("Lost a node at level %d - collector is broken\n", n); FAIL; } if (counter++ % 373 == 0) { @@ -831,7 +831,7 @@ void * alloc8bytes(void) uncollectable_count++; my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *); if (pthread_setspecific(fl_key, my_free_list_ptr) != 0) { - (void)GC_printf("pthread_setspecific failed\n"); + GC_printf("pthread_setspecific failed\n"); FAIL; } } @@ -839,7 +839,7 @@ void * alloc8bytes(void) if (my_free_list == 0) { my_free_list = GC_malloc_many(8); if (my_free_list == 0) { - (void)GC_printf("alloc8bytes out of memory\n"); + GC_printf("alloc8bytes out of memory\n"); FAIL; } } @@ -861,7 +861,7 @@ void alloc_small(int n) for (i = 0; i < n; i += 8) { atomic_count++; if (alloc8bytes() == 0) { - (void)GC_printf("Out of memory\n"); + GC_printf("Out of memory\n"); FAIL; } } @@ -891,7 +891,7 @@ void tree_test(void) # endif chktree(root, TREE_HEIGHT); if (finalized_count && ! dropped_something) { - (void)GC_printf("Premature finalization - collector is broken\n"); + GC_printf("Premature finalization - collector is broken\n"); FAIL; } dropped_something = 1; @@ -987,8 +987,7 @@ void typed_test(void) } for (i = 0; i < 20000; i++) { if (new[0] != 17) { - (void)GC_printf("typed alloc failed at %lu\n", - (unsigned long)i); + GC_printf("typed alloc failed at %lu\n", (unsigned long)i); FAIL; } new[0] = 0; @@ -1057,22 +1056,22 @@ void run_one_test(void) # ifdef FIND_LEAK GC_printf( - "This test program is not designed for leak detection mode\n"); - GC_printf("Expect lots of problems.\n"); + "This test program is not designed for leak detection mode\n"); + GC_printf("Expect lots of problems\n"); # endif GC_FREE(0); # ifndef DBG_HDRS_ALL collectable_count += 3; if ((GC_size(GC_malloc(7)) != 8 && GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)) - || GC_size(GC_malloc(15)) != 16) { - GC_printf("GC_size produced unexpected results\n"); - FAIL; + || GC_size(GC_malloc(15)) != 16) { + GC_printf("GC_size produced unexpected results\n"); + FAIL; } collectable_count += 1; if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) { GC_printf("GC_malloc(0) failed: GC_size returns %ld\n", - (unsigned long)GC_size(GC_malloc(0))); + (unsigned long)GC_size(GC_malloc(0))); FAIL; } collectable_count += 1; @@ -1128,8 +1127,7 @@ void run_one_test(void) if (GC_is_valid_displacement(y) != y || GC_is_valid_displacement(x) != x || GC_is_valid_displacement(x + 3) != x + 3) { - GC_printf( - "GC_is_valid_displacement produced incorrect result\n"); + GC_printf("GC_is_valid_displacement produced incorrect result\n"); FAIL; } { @@ -1148,7 +1146,8 @@ void run_one_test(void) if (!TEST_FAIL_COUNT(GC_get_all_interior_pointers() ? 1 : 2)) # endif { - GC_printf("GC_is_valid_displacement produced wrong failure indication\n"); + GC_printf( + "GC_is_valid_displacement produced wrong failure indication\n"); FAIL; } # endif @@ -1212,7 +1211,7 @@ void run_one_test(void) GET_TIME(tree_time); time_diff = MS_TIME_DIFF(tree_time, start_time); GC_log_printf("-------------Finished tree_test at time %u (%p)\n", - (unsigned) time_diff, &start_time); + (unsigned) time_diff, &start_time); } /* Run reverse_test a second time, so we hopefully notice corruption. */ reverse_test(); @@ -1290,26 +1289,26 @@ void check_heap_stats(void) GC_log_printf("Primordial thread stack bottom: %p\n", GC_stackbottom); } - (void)GC_printf("Completed %u tests\n", n_tests); - (void)GC_printf("Allocated %d collectable objects\n", collectable_count); - (void)GC_printf("Allocated %d uncollectable objects\n", - uncollectable_count); - (void)GC_printf("Allocated %d atomic objects\n", atomic_count); - (void)GC_printf("Allocated %d stubborn objects\n", stubborn_count); - (void)GC_printf("Finalized %d/%d objects - ", - finalized_count, finalizable_count); + GC_printf("Completed %u tests\n", n_tests); + GC_printf("Allocated %d collectable objects\n", collectable_count); + GC_printf("Allocated %d uncollectable objects\n", + uncollectable_count); + GC_printf("Allocated %d atomic objects\n", atomic_count); + GC_printf("Allocated %d stubborn objects\n", stubborn_count); + GC_printf("Finalized %d/%d objects - ", + finalized_count, finalizable_count); # ifdef FINALIZE_ON_DEMAND if (finalized_count != late_finalize_count) { - (void)GC_printf("Demand finalization error\n"); + GC_printf("Demand finalization error\n"); FAIL; } # endif if (finalized_count > finalizable_count || finalized_count < finalizable_count/2) { - (void)GC_printf("finalization is probably broken\n"); + GC_printf("finalization is probably broken\n"); FAIL; } else { - (void)GC_printf("finalization is probably ok\n"); + GC_printf("finalization is probably ok\n"); } still_live = 0; for (i = 0; i < MAX_FINALIZED; i++) { @@ -1320,17 +1319,17 @@ void check_heap_stats(void) i = finalizable_count - finalized_count - still_live; if (0 != i) { GC_printf("%d disappearing links remain and %d more objects " - "were not finalized\n", still_live, i); + "were not finalized\n", still_live, i); if (i > 10) { GC_printf("\tVery suspicious!\n"); } else { - GC_printf("\tSlightly suspicious, but probably OK.\n"); + GC_printf("\tSlightly suspicious, but probably OK\n"); } } - (void)GC_printf("Total number of bytes allocated is %lu\n", - (unsigned long)GC_get_total_bytes()); - (void)GC_printf("Final heap size is %lu bytes\n", - (unsigned long)GC_get_heap_size()); + GC_printf("Total number of bytes allocated is %lu\n", + (unsigned long)GC_get_total_bytes()); + GC_printf("Final heap size is %lu bytes\n", + (unsigned long)GC_get_heap_size()); if (GC_get_total_bytes() < n_tests * # ifdef VERY_SMALL_CONFIG 2700000 @@ -1338,17 +1337,17 @@ void check_heap_stats(void) 33500000 # endif ) { - (void)GC_printf("Incorrect execution - missed some allocations\n"); - FAIL; + GC_printf("Incorrect execution - missed some allocations\n"); + FAIL; } if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz*n_tests) { - (void)GC_printf("Unexpected heap growth - collector may be broken\n"); + GC_printf("Unexpected heap growth - collector may be broken\n"); FAIL; } # ifdef THREADS GC_unregister_my_thread(); /* just to check it works (for main) */ # endif - (void)GC_printf("Collector appears to work\n"); + GC_printf("Collector appears to work\n"); } #if defined(MACOS) @@ -1396,7 +1395,7 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) /* Make sure we have lots and lots of stack space. */ SetMinimumStack(cMinStackSpace); /* Cheat and let stdio initialize toolbox for us. */ - printf("Testing GC Macintosh port.\n"); + printf("Testing GC Macintosh port\n"); # endif GC_COND_INIT(); GC_set_warn_proc(warn_proc); @@ -1552,12 +1551,12 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, # ifdef MSWINCE win_created_h = CreateEvent(NULL, FALSE, FALSE, NULL); if (win_created_h == (HANDLE)NULL) { - (void)GC_printf("Event creation failed %d\n", (int)GetLastError()); + GC_printf("Event creation failed %d\n", (int)GetLastError()); FAIL; } win_thr_h = GC_CreateThread(NULL, 0, thr_window, 0, 0, &thread_id); if (win_thr_h == (HANDLE)NULL) { - (void)GC_printf("Thread creation failed %d\n", (int)GetLastError()); + GC_printf("Thread creation failed %d\n", (int)GetLastError()); FAIL; } if (WaitForSingleObject(win_created_h, INFINITE) != WAIT_OBJECT_0) @@ -1568,7 +1567,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, for (i = 0; i < NTHREADS; i++) { h[i] = GC_CreateThread(NULL, 0, thr_run_one_test, 0, 0, &thread_id); if (h[i] == (HANDLE)NULL) { - (void)GC_printf("Thread creation failed %d\n", (int)GetLastError()); + GC_printf("Thread creation failed %d\n", (int)GetLastError()); FAIL; } } @@ -1577,7 +1576,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, # if NTHREADS > 0 for (i = 0; i < NTHREADS; i++) { if (WaitForSingleObject(h[i], INFINITE) != WAIT_OBJECT_0) { - (void)GC_printf("Thread wait failed %d\n", (int)GetLastError()); + GC_printf("Thread wait failed %d\n", (int)GetLastError()); FAIL; } } @@ -1609,11 +1608,11 @@ int test(void) run_one_test(); if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever) != PCR_ERes_okay || code != 0) { - (void)GC_printf("Thread 1 failed\n"); + GC_printf("Thread 1 failed\n"); } if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever) != PCR_ERes_okay || code != 0) { - (void)GC_printf("Thread 2 failed\n"); + GC_printf("Thread 2 failed\n"); } check_heap_stats(); return(0); @@ -1646,7 +1645,7 @@ int main(void) /* Default stack size is too small, especially with the 64 bit ABI */ /* Increase it. */ if (pthread_default_stacksize_np(1024*1024, 0) != 0) { - (void)GC_printf("pthread_default_stacksize_np failed.\n"); + GC_printf("pthread_default_stacksize_np failed\n"); } # endif /* GC_HPUX_THREADS */ # ifdef PTW32_STATIC_LIB @@ -1672,32 +1671,32 @@ int main(void) && !defined(MAKE_BACK_GRAPH) && !defined(USE_PROC_FOR_LIBRARIES) \ && !defined(NO_INCREMENTAL) GC_enable_incremental(); - (void) GC_printf("Switched to incremental mode\n"); + GC_printf("Switched to incremental mode\n"); # if defined(MPROTECT_VDB) - (void)GC_printf("Emulating dirty bits with mprotect/signals\n"); + GC_printf("Emulating dirty bits with mprotect/signals\n"); # else # ifdef PROC_VDB - (void)GC_printf("Reading dirty bits from /proc\n"); + GC_printf("Reading dirty bits from /proc\n"); # else - (void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n"); + GC_printf("Using DEFAULT_VDB dirty bit implementation\n"); # endif # endif # endif GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { - (void)GC_printf("Key creation failed %d\n", code); + GC_printf("Key creation failed %d\n", code); FAIL; } for (i = 0; i < NTHREADS; ++i) { if ((code = pthread_create(th+i, &attr, thr_run_one_test, 0)) != 0) { - (void)GC_printf("Thread %d creation failed %d\n", i, code); + GC_printf("Thread %d creation failed %d\n", i, code); FAIL; } } run_one_test(); for (i = 0; i < NTHREADS; ++i) { if ((code = pthread_join(th[i], 0)) != 0) { - (void)GC_printf("Thread %d failed %d\n", i, code); + GC_printf("Thread %d failed %d\n", i, code); FAIL; } } -- cgit v1.2.1 From a8f9c44628e79682503300bec4a464cbbed75977 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 3 Apr 2011 14:32:12 +0000 Subject: 2011-04-03 Ivan Maidanski * win32_threads.c (DEBUG_CYGWIN_THREADS, DEBUG_WIN32_PTHREADS, DEBUG_WIN32_THREADS): Remove. * win32_threads.c (GC_register_my_thread_inner, GC_win32_start_inner): Use GC_log_printf instead of GC_printf inside "if (GC_print_stats)" branch. * win32_threads.c (GC_PTHREAD_PTRVAL): New macro (defined only if GC_PTHREADS). * win32_threads.c (GC_delete_gc_thread, NUMERIC_THREAD_ID, GC_pthread_join, GC_pthread_create): Use GC_PTHREAD_PTRVAL macro. * win32_threads.c (GC_push_stack_for, GC_mark_thread, GC_CreateThread, GC_beginthreadex, GC_pthread_join, GC_pthread_create, GC_pthread_start_inner, GC_thread_exit_proc, GC_mark_thread_local_free_lists): Use GC_log_printf instead of GC_printf for DEBUG_THREADS output. * win32_threads.c (GC_win32_start_inner, GC_CreateThread, GC_beginthreadex, GC_pthread_join, GC_pthread_create, GC_pthread_start_inner, GC_thread_exit_proc): Cast GetCurrentThreadId result to long; don't cast value of pthread_t type to int; adjust printf format specifiers. * doc/README.win32 (DEBUG_WIN32_PTHREADS): Remove obsolete information. --HG-- branch : bdwgc --- ChangeLog | 25 ++++++++++ doc/README.win32 | 4 +- win32_threads.c | 147 ++++++++++++++++++++----------------------------------- 3 files changed, 80 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c562a3f..f033f2e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2011-04-03 Ivan Maidanski + + * win32_threads.c (DEBUG_CYGWIN_THREADS, DEBUG_WIN32_PTHREADS, + DEBUG_WIN32_THREADS): Remove. + * win32_threads.c (GC_register_my_thread_inner, + GC_win32_start_inner): Use GC_log_printf instead of GC_printf + inside "if (GC_print_stats)" branch. + * win32_threads.c (GC_PTHREAD_PTRVAL): New macro (defined only if + GC_PTHREADS). + * win32_threads.c (GC_delete_gc_thread, NUMERIC_THREAD_ID, + GC_pthread_join, GC_pthread_create): Use GC_PTHREAD_PTRVAL + macro. + * win32_threads.c (GC_push_stack_for, GC_mark_thread, + GC_CreateThread, GC_beginthreadex, GC_pthread_join, + GC_pthread_create, GC_pthread_start_inner, GC_thread_exit_proc, + GC_mark_thread_local_free_lists): Use GC_log_printf instead of + GC_printf for DEBUG_THREADS output. + * win32_threads.c (GC_win32_start_inner, GC_CreateThread, + GC_beginthreadex, GC_pthread_join, GC_pthread_create, + GC_pthread_start_inner, GC_thread_exit_proc): Cast + GetCurrentThreadId result to long; don't cast value of pthread_t + type to int; adjust printf format specifiers. + * doc/README.win32 (DEBUG_WIN32_PTHREADS): Remove obsolete + information. + 2011-04-03 Ivan Maidanski * tests/test.c (cons, small_cons, gcj_cons, check_ints, diff --git a/doc/README.win32 b/doc/README.win32 index 2e43b63e..44656fae 100644 --- a/doc/README.win32 +++ b/doc/README.win32 @@ -225,6 +225,4 @@ correctly track threads. To build the collector for Mingw32 Pthreads, use Makefile.direct and explicitly set GC_WIN32_PTHREADS. Use -DPTW32_STATIC_LIB for the static -threads library. Note that the DEBUG_WIN32_PTHREADS support in -win32_threads.c is currently broken and looking for someone to debug it. -(This information and the port came from Romano Paolo Tenca). +threads library. diff --git a/win32_threads.c b/win32_threads.c index 796b9096..026f1629 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -49,19 +49,6 @@ # ifndef GC_NO_PTHREAD_SIGMASK # undef pthread_sigmask -# endif - -# ifdef DEBUG_THREADS -# ifdef CYGWIN32 -# define DEBUG_CYGWIN_THREADS 1 -# define DEBUG_WIN32_PTHREADS 0 -# else -# define DEBUG_WIN32_PTHREADS 1 -# define DEBUG_CYGWIN_THREADS 0 -# endif -# else -# define DEBUG_CYGWIN_THREADS 0 -# define DEBUG_WIN32_PTHREADS 0 # endif STATIC void * GC_pthread_start(void * arg); @@ -76,12 +63,6 @@ # undef _beginthreadex # undef _endthreadex -# ifdef DEBUG_THREADS -# define DEBUG_WIN32_THREADS 1 -# else -# define DEBUG_WIN32_THREADS 0 -# endif - # ifdef MSWINCE /* Force DONT_USE_SIGNALANDWAIT implementation of PARALLEL_MARK */ /* for WinCE (since Win32 SignalObjectAndWait() is missing). */ @@ -469,8 +450,8 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, 0 /* dwDesiredAccess */, FALSE /* bInheritHandle */, DUPLICATE_SAME_ACCESS)) { if (GC_print_stats) - GC_printf("DuplicateHandle failed with error code: %d\n", - (int)GetLastError()); + GC_log_printf("DuplicateHandle failed with error code: %d\n", + (int)GetLastError()); ABORT("DuplicateHandle failed"); } # endif @@ -615,6 +596,12 @@ GC_INNER unsigned char *GC_check_finalizer_nested(void) # define UNPROTECT_THREAD(t) #endif +#ifdef CYGWIN32 +# define GC_PTHREAD_PTRVAL(pthread_id) pthread_id +#elif defined(GC_WIN32_PTHREADS) +# define GC_PTHREAD_PTRVAL(pthread_id) pthread_id.p +#endif + /* If a thread has been joined, but we have not yet */ /* been notified, then there may be more than one thread */ /* in the table with the same win32 id. */ @@ -638,12 +625,9 @@ STATIC void GC_delete_gc_thread(GC_vthread gc_id) /* see GC_stop_world() for the information. */ gc_id -> stack_base = 0; gc_id -> id = 0; -# ifdef CYGWIN32 - gc_id -> pthread_id = 0; -# endif /* CYGWIN32 */ -# ifdef GC_WIN32_PTHREADS - gc_id -> pthread_id.p = NULL; -# endif /* GC_WIN32_PTHREADS */ +# ifdef GC_PTHREADS + GC_PTHREAD_PTRVAL(gc_id->pthread_id) = 0; +# endif AO_store_release(&gc_id->tm.in_use, FALSE); } else # endif @@ -1288,8 +1272,8 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) if (sp >= stack_min && sp < thread->stack_base) { # ifdef DEBUG_THREADS - GC_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n", - (int)thread -> id, sp, thread -> stack_base, (int)me); + GC_log_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n", + (int)thread -> id, sp, thread -> stack_base, (int)me); # endif GC_push_all_stack_sections(sp, thread->stack_base, traced_stack_sect); } else { @@ -1301,9 +1285,8 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) WARN("Thread stack pointer %p out of range, pushing everything\n", sp); # ifdef DEBUG_THREADS - GC_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n", - (int)thread -> id, stack_min, - thread -> stack_base, (int)me); + GC_log_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n", + (int)thread->id, stack_min, thread->stack_base, (int)me); # endif /* Push everything - ignore "traced stack section" data. */ GC_push_all_stack(stack_min, thread->stack_base); @@ -1517,8 +1500,8 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, my_mark_no = GC_mark_no; } # ifdef DEBUG_THREADS - GC_printf("Starting mark helper for mark number %lu\n", - (unsigned long)my_mark_no); + GC_log_printf("Starting mark helper for mark number %lu\n", + (unsigned long)my_mark_no); # endif GC_help_marker(my_mark_no); } @@ -1534,7 +1517,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, # include # ifndef NUMERIC_THREAD_ID -# define NUMERIC_THREAD_ID(id) (unsigned long)(id.p) +# define NUMERIC_THREAD_ID(id) (unsigned long)GC_PTHREAD_PTRVAL(id) # endif /* start_mark_threads() is the same as in pthread_support.c except for: */ @@ -1997,8 +1980,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_register_my_thread(sb); /* This waits for an in-progress GC. */ -# if DEBUG_WIN32_THREADS - GC_printf("thread 0x%x starting...\n", (unsigned)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("thread 0x%lx starting...\n", + (long)GetCurrentThreadId()); # endif GC_free(arg); @@ -2019,9 +2003,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_unregister_my_thread(); } -# if DEBUG_WIN32_THREADS - GC_printf("thread 0x%x returned from start routine\n", - (unsigned)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("thread 0x%lx returned from start routine\n", + (long)GetCurrentThreadId()); # endif return ret; } @@ -2045,9 +2029,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* make sure GC is initialized (i.e. main thread is */ /* attached, tls initialized). */ -# if DEBUG_WIN32_THREADS - GC_printf("About to create a thread from 0x%x\n", - (unsigned)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("About to create a thread from 0x%lx\n", + (long)GetCurrentThreadId()); # endif if (GC_win32_dll_threads) { return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, @@ -2092,9 +2076,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, if (!parallel_initialized) GC_init_parallel(); /* make sure GC is initialized (i.e. main thread is */ /* attached, tls initialized). */ -# if DEBUG_WIN32_THREADS - GC_printf("About to create a thread from 0x%x\n", - (unsigned)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("About to create a thread from 0x%lx\n", + (long)GetCurrentThreadId()); # endif if (GC_win32_dll_threads) { @@ -2341,15 +2325,10 @@ GC_INNER void GC_thr_init(void) int result; GC_thread joinee; -# if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) is joining thread 0x%x\n", - (int)pthread_self(), (int)GetCurrentThreadId(), - (int)pthread_id); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) is joining thread 0x%x\n", - (int)(pthread_self()).p, (int)GetCurrentThreadId(), - pthread_id.p); +# ifdef DEBUG_THREADS + GC_log_printf("thread %p(0x%lx) is joining thread %p\n", + GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId(), GC_PTHREAD_PTRVAL(pthread_id)); # endif if (!parallel_initialized) GC_init_parallel(); @@ -2377,15 +2356,10 @@ GC_INNER void GC_thr_init(void) UNLOCK(); } /* otherwise DllMain handles it. */ -# if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x\n", - (int)pthread_self(), (int)GetCurrentThreadId(), - (int)pthread_id); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x\n", - (int)(pthread_self()).p, (int)GetCurrentThreadId(), - pthread_id.p); +# ifdef DEBUG_THREADS + GC_log_printf("thread %p(0x%lx) completed join with thread %p\n", + GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId(), GC_PTHREAD_PTRVAL(pthread_id)); # endif return result; } @@ -2417,13 +2391,10 @@ GC_INNER void GC_thr_init(void) si->detached = TRUE; } -# if DEBUG_CYGWIN_THREADS - GC_printf("About to create a thread from 0x%x(0x%x)\n", - (int)pthread_self(), (int)GetCurrentThreadId); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("About to create a thread from 0x%x(0x%x)\n", - (int)(pthread_self()).p, (int)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("About to create a thread from %p(0x%lx)\n", + GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId()); # endif GC_need_to_lock = TRUE; result = pthread_create(new_thread, attr, GC_pthread_start, si); @@ -2447,13 +2418,9 @@ GC_INNER void GC_thr_init(void) GC_thread me; DCL_LOCK_STATE; -# if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) starting...\n",(int)pthread_id, - (int)thread_id); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) starting...\n",(int) pthread_id.p, - (int)thread_id); +# ifdef DEBUG_THREADS + GC_log_printf("thread %p(0x%x) starting...\n", + GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); # endif GC_ASSERT(!GC_win32_dll_threads); @@ -2480,13 +2447,10 @@ GC_INNER void GC_thr_init(void) me -> status = result; pthread_cleanup_pop(1); -# if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) returned from start routine\n", - (int)pthread_self(),(int)GetCurrentThreadId()); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) returned from start routine\n", - (int)(pthread_self()).p, (int)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("thread %p(0x%lx) returned from start routine\n", + GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId()); # endif return(result); } @@ -2502,13 +2466,10 @@ GC_INNER void GC_thr_init(void) DCL_LOCK_STATE; GC_ASSERT(!GC_win32_dll_threads); -# if DEBUG_CYGWIN_THREADS - GC_printf("thread 0x%x(0x%x) called pthread_exit()\n", - (int)pthread_self(),(int)GetCurrentThreadId()); -# endif -# if DEBUG_WIN32_PTHREADS - GC_printf("thread 0x%x(0x%x) called pthread_exit()\n", - (int)(pthread_self()).p,(int)GetCurrentThreadId()); +# ifdef DEBUG_THREADS + GC_log_printf("thread %p(0x%lx) called pthread_exit()\n", + GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId()); # endif LOCK(); @@ -2700,7 +2661,7 @@ GC_INNER void GC_init_parallel(void) for (p = GC_threads[i]; 0 != p; p = p -> tm.next) { if (!KNOWN_FINISHED(p)) { # ifdef DEBUG_THREADS - GC_printf("Marking thread locals for 0x%x\n", (int)p -> id); + GC_log_printf("Marking thread locals for 0x%x\n", (int)p -> id); # endif GC_mark_thread_local_fls_for(&(p->tlfs)); } -- cgit v1.2.1 From cbe18ce67d048bf7ecdd0df669a9f8160a63bbcf Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 3 Apr 2011 15:29:32 +0000 Subject: 2011-04-03 Ivan Maidanski * allchblk.c (GC_freehblk): Use GC_log_printf instead of GC_printf inside "if (GC_print_stats)" branch. * alloc.c (GC_collect_or_expand): Ditto. * dyn_load.c (GC_register_dynamic_libraries): Ditto. * headers.c (GC_scratch_alloc): Ditto. * os_dep.c (GC_get_maps, GC_remap, PROTECT, GC_write_fault_handler, GC_dirty_init, GC_mprotect_thread): Ditto. * alloc.c (min_bytes_allocd): Use GC_log_printf instead of GC_printf for DEBUG_THREADS output. * darwin_stop_world.c (GC_stack_range_for, GC_suspend_thread_list, GC_stop_world, GC_thread_resume, GC_start_world): Ditto. * pthread_start.c (GC_inner_start_routine): Ditto. * pthread_stop_world.c (GC_suspend_handler, GC_restart_handler, GC_push_all_stacks, GC_suspend_all, GC_stop_world, GC_start_world): Ditto. * pthread_support.c (GC_mark_thread, GC_get_nprocs, GC_start_rtn_prepare_thread, pthread_create): Ditto. * alloc.c (GC_adj_bytes_allocd, GC_maybe_gc, GC_stopped_mark, GC_finish_collection): Reformat code. * pthread_stop_world.c (GC_print_sig_mask): Ditto. * pthread_support.c (GC_thr_init): Ditto. * checksums.c (GC_update_check_page): Use GC_printf() instead of GC_err_printf() for error printing. * checksums.c (GC_check_blocks, GC_check_dirty): Use GC_log_printf instead of GC_printf for logging purposes. * dyn_load.c (sys_errlist, sys_nerr, errno): Move declaration of external variable outside from GC_register_dynamic_libraries. * dyn_load.c (GC_register_dynamic_libraries): Don't use sys_errlist value if errno equals to sys_nerr. * dyn_load.c (GC_register_dynamic_libraries): Use GC_log_printf instead of GC_printf for DL_VERBOSE output. * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove, GC_init_dyld): Use GC_log_printf instead of GC_printf for DARWIN_DEBUG output. * os_dep.c (catch_exception_raise): Use GC_log_printf instead of GC_printf for DEBUG_EXCEPTION_HANDLING output. * reclaim.c (GC_print_free_list): Move "n" increment out of GC_printf() call. --HG-- branch : bdwgc --- ChangeLog | 41 ++++++++++++++++++++ allchblk.c | 2 +- alloc.c | 93 +++++++++++++++++++++++---------------------- checksums.c | 30 ++++++++------- darwin_stop_world.c | 34 ++++++++--------- dyn_load.c | 95 +++++++++++++++++++++++----------------------- headers.c | 2 +- os_dep.c | 104 +++++++++++++++++++++++++-------------------------- pthread_start.c | 2 +- pthread_stop_world.c | 54 +++++++++++++------------- pthread_support.c | 25 +++++++------ reclaim.c | 16 ++++---- 12 files changed, 272 insertions(+), 226 deletions(-) diff --git a/ChangeLog b/ChangeLog index f033f2e6..e94be3a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +2011-04-03 Ivan Maidanski + + * allchblk.c (GC_freehblk): Use GC_log_printf instead of GC_printf + inside "if (GC_print_stats)" branch. + * alloc.c (GC_collect_or_expand): Ditto. + * dyn_load.c (GC_register_dynamic_libraries): Ditto. + * headers.c (GC_scratch_alloc): Ditto. + * os_dep.c (GC_get_maps, GC_remap, PROTECT, + GC_write_fault_handler, GC_dirty_init, GC_mprotect_thread): Ditto. + * alloc.c (min_bytes_allocd): Use GC_log_printf instead of + GC_printf for DEBUG_THREADS output. + * darwin_stop_world.c (GC_stack_range_for, GC_suspend_thread_list, + GC_stop_world, GC_thread_resume, GC_start_world): Ditto. + * pthread_start.c (GC_inner_start_routine): Ditto. + * pthread_stop_world.c (GC_suspend_handler, GC_restart_handler, + GC_push_all_stacks, GC_suspend_all, GC_stop_world, + GC_start_world): Ditto. + * pthread_support.c (GC_mark_thread, GC_get_nprocs, + GC_start_rtn_prepare_thread, pthread_create): Ditto. + * alloc.c (GC_adj_bytes_allocd, GC_maybe_gc, GC_stopped_mark, + GC_finish_collection): Reformat code. + * pthread_stop_world.c (GC_print_sig_mask): Ditto. + * pthread_support.c (GC_thr_init): Ditto. + * checksums.c (GC_update_check_page): Use GC_printf() instead of + GC_err_printf() for error printing. + * checksums.c (GC_check_blocks, GC_check_dirty): Use GC_log_printf + instead of GC_printf for logging purposes. + * dyn_load.c (sys_errlist, sys_nerr, errno): Move declaration of + external variable outside from GC_register_dynamic_libraries. + * dyn_load.c (GC_register_dynamic_libraries): Don't use + sys_errlist value if errno equals to sys_nerr. + * dyn_load.c (GC_register_dynamic_libraries): Use GC_log_printf + instead of GC_printf for DL_VERBOSE output. + * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove, + GC_init_dyld): Use GC_log_printf instead of GC_printf for + DARWIN_DEBUG output. + * os_dep.c (catch_exception_raise): Use GC_log_printf + instead of GC_printf for DEBUG_EXCEPTION_HANDLING output. + * reclaim.c (GC_print_free_list): Move "n" increment out of + GC_printf() call. + 2011-04-03 Ivan Maidanski * win32_threads.c (DEBUG_CYGWIN_THREADS, DEBUG_WIN32_PTHREADS, diff --git a/allchblk.c b/allchblk.c index 637d20d0..efcc00ab 100644 --- a/allchblk.c +++ b/allchblk.c @@ -848,7 +848,7 @@ GC_INNER void GC_freehblk(struct hblk *hbp) /* Check for duplicate deallocation in the easy case */ if (HBLK_IS_FREE(hhdr)) { if (GC_print_stats) - GC_printf("Duplicate large block deallocation of %p\n", hbp); + GC_log_printf("Duplicate large block deallocation of %p\n", hbp); ABORT("Duplicate large block deallocation"); } diff --git a/alloc.c b/alloc.c index 457a0178..dffbc014 100644 --- a/alloc.c +++ b/alloc.c @@ -180,7 +180,7 @@ GC_API GC_stop_func GC_CALL GC_get_stop_func(void) time_diff = MS_TIME_DIFF(current_time,GC_start_time); if (time_diff >= GC_time_limit) { if (GC_print_stats) { - GC_log_printf( + GC_log_printf( "Abandoning stopped marking after %lu msecs (attempt %d)\n", time_diff, GC_n_attempts); } @@ -217,7 +217,8 @@ static word min_bytes_allocd(void) stack_size = GC_total_stacksize; /* For now, we just use the value computed during the latest GC. */ # ifdef DEBUG_THREADS - GC_printf("Total stacks size: %lu\n", (unsigned long)stack_size); + GC_log_printf("Total stacks size: %lu\n", + (unsigned long)stack_size); # endif } # endif @@ -238,9 +239,8 @@ static word min_bytes_allocd(void) STATIC word GC_adj_bytes_allocd(void) { signed_word result; - signed_word expl_managed = - (signed_word)GC_non_gc_bytes - - (signed_word)GC_non_gc_bytes_at_gc; + signed_word expl_managed = (signed_word)GC_non_gc_bytes + - (signed_word)GC_non_gc_bytes_at_gc; /* Don't count what was explicitly freed, or newly allocated for */ /* explicit management. Note that deallocating an explicitly */ @@ -364,10 +364,9 @@ STATIC void GC_maybe_gc(void) # endif if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) { if (GC_print_stats) { - GC_log_printf( + GC_log_printf( "***>Full mark for collection %lu after %ld allocd bytes\n", - (unsigned long)GC_gc_no+1, - (long)GC_bytes_allocd); + (unsigned long)GC_gc_no + 1, (long)GC_bytes_allocd); } GC_promote_black_lists(); (void)GC_reclaim_all((GC_stop_func)0, TRUE); @@ -471,7 +470,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) if (GC_print_stats) { GET_TIME(current_time); GC_log_printf("Complete collection took %lu msecs\n", - MS_TIME_DIFF(current_time,start_time)); + MS_TIME_DIFF(current_time,start_time)); } # endif return(TRUE); @@ -624,20 +623,20 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) GC_clear_a_few_frames(); GC_noop(0,0,0,0,0,0); GC_initiate_gc(); - for(i = 0;;i++) { - if ((*stop_func)()) { - if (GC_print_stats) { - GC_log_printf("Abandoned stopped marking after " - "%u iterations\n", i); - } - GC_deficit = i; /* Give the mutator a chance. */ -# ifdef THREAD_LOCAL_ALLOC - GC_world_stopped = FALSE; -# endif - START_WORLD(); - return(FALSE); + for (i = 0;;i++) { + if ((*stop_func)()) { + if (GC_print_stats) { + GC_log_printf("Abandoned stopped marking after %u iterations\n", + i); } - if (GC_mark_some((ptr_t)(&dummy))) break; + GC_deficit = i; /* Give the mutator a chance. */ +# ifdef THREAD_LOCAL_ALLOC + GC_world_stopped = FALSE; +# endif + START_WORLD(); + return(FALSE); + } + if (GC_mark_some((ptr_t)(&dummy))) break; } GC_gc_no++; @@ -876,7 +875,7 @@ STATIC void GC_finish_collection(void) if (GC_print_stats == VERBOSE) GC_log_printf("Bytes recovered before sweep - f.l. count = %ld\n", - (long)GC_bytes_found); + (long)GC_bytes_found); /* Reconstruct free lists to contain everything not marked */ GC_start_reclaim(FALSE); @@ -895,16 +894,16 @@ STATIC void GC_finish_collection(void) } if (GC_print_stats == VERBOSE) { -# ifdef USE_MUNMAP - GC_log_printf("Immediately reclaimed %ld bytes in heap" - " of size %lu bytes (%lu unmapped)\n", - (long)GC_bytes_found, (unsigned long)GC_heapsize, - (unsigned long)GC_unmapped_bytes); -# else - GC_log_printf("Immediately reclaimed %ld bytes in heap" - " of size %lu bytes\n", - (long)GC_bytes_found, (unsigned long)GC_heapsize); -# endif +# ifdef USE_MUNMAP + GC_log_printf("Immediately reclaimed %ld bytes in heap" + " of size %lu bytes (%lu unmapped)\n", + (long)GC_bytes_found, (unsigned long)GC_heapsize, + (unsigned long)GC_unmapped_bytes); +# else + GC_log_printf( + "Immediately reclaimed %ld bytes in heap of size %lu bytes\n", + (long)GC_bytes_found, (unsigned long)GC_heapsize); +# endif } /* Reset or increment counters for next cycle */ @@ -928,7 +927,7 @@ STATIC void GC_finish_collection(void) /* A convenient place to output finalization statistics. */ GC_print_finalization_stats(); - GC_log_printf("Finalize + initiate sweep took %lu + %lu msecs\n", + GC_log_printf("Finalize plus initiate sweep took %lu + %lu msecs\n", MS_TIME_DIFF(finalize_time,start_time), MS_TIME_DIFF(done_time,finalize_time)); } @@ -1075,19 +1074,19 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes) { unsigned i; - GC_printf("Total heap size: %lu\n", (unsigned long) GC_heapsize); + GC_printf("Total heap size: %lu\n", (unsigned long)GC_heapsize); for (i = 0; i < GC_n_heap_sects; i++) { - ptr_t start = GC_heap_sects[i].hs_start; - size_t len = GC_heap_sects[i].hs_bytes; - struct hblk *h; - unsigned nbl = 0; + ptr_t start = GC_heap_sects[i].hs_start; + size_t len = GC_heap_sects[i].hs_bytes; + struct hblk *h; + unsigned nbl = 0; - for (h = (struct hblk *)start; h < (struct hblk *)(start + len); h++) { - if (GC_is_black_listed(h, HBLKSIZE)) nbl++; - } - GC_printf("Section %d from %p to %p %lu/%lu blacklisted\n", - i, start, start + len, - (unsigned long)nbl, (unsigned long)(len/HBLKSIZE)); + for (h = (struct hblk *)start; h < (struct hblk *)(start + len); h++) { + if (GC_is_black_listed(h, HBLKSIZE)) nbl++; + } + GC_printf("Section %d from %p to %p %lu/%lu blacklisted\n", + i, start, start + len, + (unsigned long)nbl, (unsigned long)(len/HBLKSIZE)); } } #endif @@ -1141,7 +1140,7 @@ GC_INNER GC_bool GC_expand_hp_inner(word n) } space = GET_MEM(bytes); GC_add_to_our_memory((ptr_t)space, bytes); - if( space == 0 ) { + if (space == 0) { if (GC_print_stats) { GC_log_printf("Failed to expand heap by %ld bytes\n", (unsigned long)bytes); @@ -1272,7 +1271,7 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, return(FALSE); } } else if (GC_fail_count && GC_print_stats) { - GC_printf("Memory available again...\n"); + GC_log_printf("Memory available again...\n"); } RESTORE_CANCEL(cancel_state); return(TRUE); diff --git a/checksums.c b/checksums.c index e565ccd6..0400697d 100644 --- a/checksums.c +++ b/checksums.c @@ -110,7 +110,7 @@ STATIC void GC_update_check_page(struct hblk *h, int index) pe -> new_sum = GC_checksum(h); # if !defined(MSWIN32) && !defined(MSWINCE) if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) { - GC_printf("GC_page_was_ever_dirty(%p) is wrong\n", h); + GC_err_printf("GC_page_was_ever_dirty(%p) is wrong\n", h); } # endif if (GC_page_was_dirty(h)) { @@ -165,12 +165,13 @@ STATIC void GC_check_blocks(void) GC_bytes_in_used_blocks = 0; GC_apply_to_all_blocks(GC_add_block, (word)0); - GC_printf("GC_bytes_in_used_blocks = %lu, bytes_in_free_blocks = %lu ", - (unsigned long)GC_bytes_in_used_blocks, - (unsigned long)bytes_in_free_blocks); - GC_printf("GC_heapsize = %lu\n", (unsigned long)GC_heapsize); + GC_log_printf( + "GC_bytes_in_used_blocks = %lu, bytes_in_free_blocks = %lu ", + (unsigned long)GC_bytes_in_used_blocks, + (unsigned long)bytes_in_free_blocks); + GC_log_printf("GC_heapsize = %lu\n", (unsigned long)GC_heapsize); if (GC_bytes_in_used_blocks + bytes_in_free_blocks != GC_heapsize) { - GC_printf("LOST SOME BLOCKS!!\n"); + GC_log_printf("LOST SOME BLOCKS!!\n"); } } @@ -202,18 +203,19 @@ void GC_check_dirty(void) } } out: - GC_printf("Checked %lu clean and %lu dirty pages\n", - (unsigned long) GC_n_clean, (unsigned long) GC_n_dirty); + GC_log_printf("Checked %lu clean and %lu dirty pages\n", + (unsigned long)GC_n_clean, (unsigned long)GC_n_dirty); if (GC_n_dirty_errors > 0) { - GC_printf("Found %d dirty bit errors (%d were faulted)\n", - GC_n_dirty_errors, GC_n_faulted_dirty_errors); + GC_log_printf("Found %d dirty bit errors (%d were faulted)\n", + GC_n_dirty_errors, GC_n_faulted_dirty_errors); } if (GC_n_changed_errors > 0) { - GC_printf("Found %lu changed bit errors\n", - (unsigned long)GC_n_changed_errors); - GC_printf("These may be benign (provoked by nonpointer changes)\n"); + GC_log_printf("Found %lu changed bit errors\n", + (unsigned long)GC_n_changed_errors); + GC_log_printf( + "These may be benign (provoked by nonpointer changes)\n"); # ifdef THREADS - GC_printf( + GC_log_printf( "Also expect 1 per thread currently allocating a stubborn obj\n"); # endif } diff --git a/darwin_stop_world.c b/darwin_stop_world.c index 50e2a539..4fcd7bac 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -145,7 +145,7 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, (natural_t *)&state, &thread_state_count); # ifdef DEBUG_THREADS - GC_printf("thread_get_state return value = %d\n", kern_result); + GC_log_printf("thread_get_state returns value = %d\n", kern_result); # endif if (kern_result != KERN_SUCCESS) ABORT("thread_get_state failed"); @@ -255,8 +255,8 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, *phi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end; # endif # ifdef DEBUG_THREADS - GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n", - (unsigned long) thread, lo, *phi); + GC_log_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n", + (unsigned long)thread, lo, *phi); # endif return lo; } @@ -386,8 +386,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, # endif # ifdef DEBUG_THREADS - GC_printf("Attempting to suspend thread 0x%lx\n", - (unsigned long)thread); + GC_log_printf("Attempting to suspend thread 0x%lx\n", + (unsigned long)thread); # endif /* find the current thread in the old list */ found = FALSE; @@ -431,8 +431,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, continue; } # ifdef DEBUG_THREADS - GC_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread, - info.run_state); + GC_log_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread, + info.run_state); # endif if (info.suspend_count != 0) { /* thread is already suspended. */ @@ -442,7 +442,7 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, } # ifdef DEBUG_THREADS - GC_printf("Suspending 0x%lx\n", (unsigned long)thread); + GC_log_printf("Suspending 0x%lx\n", (unsigned long)thread); # endif kern_result = thread_suspend(thread); if (kern_result != KERN_SUCCESS) { @@ -474,8 +474,8 @@ GC_INNER void GC_stop_world(void) kern_return_t kern_result; # ifdef DEBUG_THREADS - GC_printf("Stopping the world from thread 0x%lx\n", - (unsigned long)my_thread); + GC_log_printf("Stopping the world from thread 0x%lx\n", + (unsigned long)my_thread); # endif # ifdef PARALLEL_MARK if (GC_parallel) { @@ -564,7 +564,7 @@ GC_INNER void GC_stop_world(void) # endif # ifdef DEBUG_THREADS - GC_printf("World stopped from 0x%lx\n", (unsigned long)my_thread); + GC_log_printf("World stopped from 0x%lx\n", (unsigned long)my_thread); # endif mach_port_deallocate(my_task, my_thread); } @@ -581,8 +581,8 @@ GC_INLINE void GC_thread_resume(thread_act_t thread) ABORT("thread_info failed"); # endif # ifdef DEBUG_THREADS - GC_printf("Resuming thread 0x%lx with state %d\n", - (unsigned long)thread, info.run_state); + GC_log_printf("Resuming thread 0x%lx with state %d\n", + (unsigned long)thread, info.run_state); # endif /* Resume the thread */ kern_result = thread_resume(thread); @@ -597,7 +597,7 @@ GC_INNER void GC_start_world(void) task_t my_task = current_task(); int i; # ifdef DEBUG_THREADS - GC_printf("World starting\n"); + GC_log_printf("World starting\n"); # endif # ifdef MPROTECT_VDB if(GC_incremental) { @@ -639,8 +639,8 @@ GC_INNER void GC_start_world(void) /* The thread is found in GC_mach_threads. */ if (GC_mach_threads[j].already_suspended) { # ifdef DEBUG_THREADS - GC_printf("Not resuming already suspended thread 0x%lx\n", - (unsigned long)thread); + GC_log_printf("Not resuming already suspended thread 0x%lx\n", + (unsigned long)thread); # endif } else { GC_thread_resume(thread); @@ -669,7 +669,7 @@ GC_INNER void GC_start_world(void) } # ifdef DEBUG_THREADS - GC_printf("World started\n"); + GC_log_printf("World started\n"); # endif } diff --git a/dyn_load.c b/dyn_load.c index 698e8aa4..f504a956 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -998,6 +998,10 @@ GC_INNER void GC_register_dynamic_libraries(void) #include +extern char *sys_errlist[]; +extern int sys_nerr; +extern int errno; + GC_INNER void GC_register_dynamic_libraries(void) { int status; @@ -1031,18 +1035,15 @@ GC_INNER void GC_register_dynamic_libraries(void) /* Check status AFTER checking moduleid because */ /* of a bug in the non-shared ldr_next_module stub */ if (status != 0) { - if (GC_print_stats) { - extern char *sys_errlist[]; - extern int sys_nerr; - extern int errno; - GC_printf("dynamic_load: status = %d\n", status); - if (errno <= sys_nerr) { - GC_printf("dynamic_load: %s\n", sys_errlist[errno]); - } else { - GC_printf("dynamic_load: err_code = %d\n", errno); - } + if (GC_print_stats) { + GC_log_printf("dynamic_load: status = %d\n", status); + if (errno < sys_nerr) { + GC_log_printf("dynamic_load: %s\n", sys_errlist[errno]); + } else { + GC_log_printf("dynamic_load: err_code = %d\n", errno); } - ABORT("ldr_next_module failed"); + } + ABORT("ldr_next_module failed"); } /* Get the module information */ @@ -1056,11 +1057,11 @@ GC_INNER void GC_register_dynamic_libraries(void) continue; /* skip the main module */ # ifdef DL_VERBOSE - GC_printf("---Module---\n"); - GC_printf("Module ID = %16ld\n", moduleinfo.lmi_modid); - GC_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion); - GC_printf("flags for module = %16lx\n", moduleinfo.lmi_flags); - GC_printf("pathname of module = \"%s\"\n", moduleinfo.lmi_name); + GC_log_printf("---Module---\n"); + GC_log_printf("Module ID\t = %16ld\n", moduleinfo.lmi_modid); + GC_log_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion); + GC_log_printf("flags for module = %16lx\n", moduleinfo.lmi_flags); + GC_log_printf("module pathname\t = \"%s\"\n", moduleinfo.lmi_name); # endif /* For each region in this module */ @@ -1077,21 +1078,21 @@ GC_INNER void GC_register_dynamic_libraries(void) continue; # ifdef DL_VERBOSE - GC_printf("--- Region ---\n"); - GC_printf("Region number = %16ld\n", - regioninfo.lri_region_no); - GC_printf("Protection flags = %016x\n", regioninfo.lri_prot); - GC_printf("Virtual address = %16p\n", regioninfo.lri_vaddr); - GC_printf("Mapped address = %16p\n", regioninfo.lri_mapaddr); - GC_printf("Region size = %16ld\n", regioninfo.lri_size); - GC_printf("Region name = \"%s\"\n", regioninfo.lri_name); + GC_log_printf("--- Region ---\n"); + GC_log_printf("Region number\t = %16ld\n", + regioninfo.lri_region_no); + GC_log_printf("Protection flags = %016x\n", regioninfo.lri_prot); + GC_log_printf("Virtual address\t = %16p\n", regioninfo.lri_vaddr); + GC_log_printf("Mapped address\t = %16p\n", + regioninfo.lri_mapaddr); + GC_log_printf("Region size\t = %16ld\n", regioninfo.lri_size); + GC_log_printf("Region name\t = \"%s\"\n", regioninfo.lri_name); # endif /* register region as a garbage collection root */ - GC_add_roots_inner ( - (char *)regioninfo.lri_mapaddr, - (char *)regioninfo.lri_mapaddr + regioninfo.lri_size, - TRUE); + GC_add_roots_inner((char *)regioninfo.lri_mapaddr, + (char *)regioninfo.lri_mapaddr + regioninfo.lri_size, + TRUE); } } @@ -1129,10 +1130,10 @@ GC_INNER void GC_register_dynamic_libraries(void) break; /* Moved past end of shared library list --> finished */ } else { if (GC_print_stats) { - if (errno <= sys_nerr) { - GC_printf("dynamic_load: %s\n", sys_errlist[errno]); + if (errno < sys_nerr) { + GC_log_printf("dynamic_load: %s\n", sys_errlist[errno]); } else { - GC_printf("dynamic_load: err_code = %d\n", errno); + GC_log_printf("dynamic_load: err_code = %d\n", errno); } } ABORT("shl_get failed"); @@ -1141,16 +1142,16 @@ GC_INNER void GC_register_dynamic_libraries(void) } # ifdef DL_VERBOSE - GC_printf("---Shared library---\n"); - GC_printf("\tfilename = \"%s\"\n", shl_desc->filename); - GC_printf("\tindex = %d\n", index); - GC_printf("\thandle = %08x\n", - (unsigned long) shl_desc->handle); - GC_printf("\ttext seg. start = %08x\n", shl_desc->tstart); - GC_printf("\ttext seg. end = %08x\n", shl_desc->tend); - GC_printf("\tdata seg. start = %08x\n", shl_desc->dstart); - GC_printf("\tdata seg. end = %08x\n", shl_desc->dend); - GC_printf("\tref. count = %lu\n", shl_desc->ref_count); + GC_log_printf("---Shared library---\n"); + GC_log_printf("\tfilename\t= \"%s\"\n", shl_desc->filename); + GC_log_printf("\tindex\t\t= %d\n", index); + GC_log_printf("\thandle\t\t= %08x\n", + (unsigned long) shl_desc->handle); + GC_log_printf("\ttext seg.start\t= %08x\n", shl_desc->tstart); + GC_log_printf("\ttext seg.end\t= %08x\n", shl_desc->tend); + GC_log_printf("\tdata seg.start\t= %08x\n", shl_desc->dstart); + GC_log_printf("\tdata seg.end\t= %08x\n", shl_desc->dend); + GC_log_printf("\tref.count\t= %lu\n", shl_desc->ref_count); # endif /* register shared library's data segment as a garbage collection root */ @@ -1252,8 +1253,8 @@ STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide) /* The user callback is called holding the lock */ if (callback == 0 || callback(name, (void*)start, (size_t)sec->size)) { # ifdef DARWIN_DEBUG - GC_printf("Adding section at %p-%p (%lu bytes) from image %s\n", - start,end,sec->size,name); + GC_log_printf("Adding section at %p-%p (%lu bytes) from image %s\n", + start, end, sec->size, name); # endif GC_add_roots_inner((ptr_t)start, (ptr_t)end, FALSE); } @@ -1277,8 +1278,8 @@ STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, start = slide + sec->addr; end = start + sec->size; # ifdef DARWIN_DEBUG - GC_printf("Removing section at %p-%p (%lu bytes) from image %s\n", - start,end,sec->size,GC_dyld_name_for_hdr(hdr)); + GC_log_printf("Removing section at %p-%p (%lu bytes) from image %s\n", + start, end, sec->size, GC_dyld_name_for_hdr(hdr)); # endif GC_remove_roots((char*)start,(char*)end); } @@ -1306,7 +1307,7 @@ GC_INNER void GC_init_dyld(void) if (initialized) return; # ifdef DARWIN_DEBUG - GC_printf("Registering dyld callbacks...\n"); + GC_log_printf("Registering dyld callbacks...\n"); # endif /* Apple's Documentation: @@ -1341,7 +1342,7 @@ GC_INNER void GC_init_dyld(void) if (GETENV("DYLD_BIND_AT_LAUNCH") == 0) { /* The environment variable is unset, so we should bind manually. */ # ifdef DARWIN_DEBUG - GC_printf("Forcing full bind of GC code...\n"); + GC_log_printf("Forcing full bind of GC code...\n"); # endif /* FIXME: '_dyld_bind_fully_image_containing_address' is deprecated. */ if (!_dyld_bind_fully_image_containing_address( diff --git a/headers.c b/headers.c index c4f5023c..de82c204 100644 --- a/headers.c +++ b/headers.c @@ -145,7 +145,7 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes) GC_add_to_our_memory(result, bytes_to_get); if (result == 0) { if (GC_print_stats) - GC_printf("Out of memory - trying to allocate less\n"); + GC_log_printf("Out of memory - trying to allocate less\n"); scratch_free_ptr -= bytes; bytes_to_get = bytes; # ifdef USE_MMAP diff --git a/os_dep.c b/os_dep.c index 398d7d4b..3bb778c1 100644 --- a/os_dep.c +++ b/os_dep.c @@ -271,9 +271,10 @@ GC_INNER char * GC_get_maps(void) # ifdef THREADS if (maps_size > old_maps_size) { if (GC_print_stats) - GC_printf("Unexpected maps size growth from %lu to %lu\n", - (unsigned long)old_maps_size, - (unsigned long)maps_size); + GC_log_printf( + "Unexpected maps size growth from %lu to %lu\n", + (unsigned long)old_maps_size, + (unsigned long)maps_size); ABORT("Unexpected asynchronous /proc/self/maps growth: " "unregistered thread?"); } @@ -425,7 +426,7 @@ GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp) ptr_t my_start, my_end; if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) { if (GC_print_stats) { - GC_log_printf("Failed to find backing store base from /proc\n"); + GC_log_printf("Failed to find backing store base from /proc\n"); } return 0; } @@ -1775,8 +1776,8 @@ void GC_register_data_segments(void) } } if (GC_print_stats) - GC_log_printf("Found new system malloc AllocationBase at %p\n", - candidate); + GC_log_printf("Found new system malloc AllocationBase at %p\n", + candidate); new_l -> allocation_base = candidate; new_l -> next = GC_malloc_heap_l; GC_malloc_heap_l = new_l; @@ -2467,8 +2468,8 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) if (result != 0) { if (GC_print_stats) - GC_printf("Mprotect failed at %p (length %lu) with errno %d\n", - start_addr, (unsigned long)len, errno); + GC_log_printf("Mprotect failed at %p (length %lu) with errno %d\n", + start_addr, (unsigned long)len, errno); ABORT("mprotect remapping failed"); } GC_unmapped_bytes -= len; @@ -2940,19 +2941,19 @@ STATIC void GC_default_push_other_roots(void) # include # define PROTECT(addr, len) \ - if (mprotect((caddr_t)(addr), (size_t)(len), \ - PROT_READ \ - | (pages_executable ? PROT_EXEC : 0)) < 0) { \ - ABORT("mprotect failed"); \ - } + if (mprotect((caddr_t)(addr), (size_t)(len), \ + PROT_READ \ + | (pages_executable ? PROT_EXEC : 0)) < 0) { \ + ABORT("mprotect failed"); \ + } # define UNPROTECT(addr, len) \ - if (mprotect((caddr_t)(addr), (size_t)(len), \ - (PROT_READ | PROT_WRITE) \ - | (pages_executable ? PROT_EXEC : 0)) < 0) { \ - ABORT(pages_executable ? "un-mprotect executable page" \ - " failed (probably disabled by OS)" : \ - "un-mprotect failed"); \ - } + if (mprotect((caddr_t)(addr), (size_t)(len), \ + (PROT_READ | PROT_WRITE) \ + | (pages_executable ? PROT_EXEC : 0)) < 0) { \ + ABORT(pages_executable ? "un-mprotect executable page" \ + " failed (probably disabled by OS)" : \ + "un-mprotect failed"); \ + } # undef IGNORE_PAGES_EXECUTABLE # else /* MSWIN32 */ @@ -2962,21 +2963,21 @@ STATIC void GC_default_push_other_roots(void) static DWORD protect_junk; # define PROTECT(addr, len) \ - if (!VirtualProtect((addr), (len), \ - pages_executable ? PAGE_EXECUTE_READ : \ - PAGE_READONLY, \ - &protect_junk)) { \ - if (GC_print_stats) \ - GC_printf("Last error code: 0x%lx\n", (long)GetLastError()); \ - ABORT("VirtualProtect failed"); \ - } + if (!VirtualProtect((addr), (len), \ + pages_executable ? PAGE_EXECUTE_READ : \ + PAGE_READONLY, \ + &protect_junk)) { \ + if (GC_print_stats) \ + GC_log_printf("Last error code: 0x%lx\n", (long)GetLastError()); \ + ABORT("VirtualProtect failed"); \ + } # define UNPROTECT(addr, len) \ - if (!VirtualProtect((addr), (len), \ - pages_executable ? PAGE_EXECUTE_READWRITE : \ - PAGE_READWRITE, \ - &protect_junk)) { \ - ABORT("un-VirtualProtect failed"); \ - } + if (!VirtualProtect((addr), (len), \ + pages_executable ? PAGE_EXECUTE_READWRITE : \ + PAGE_READWRITE, \ + &protect_junk)) { \ + ABORT("un-VirtualProtect failed"); \ + } # endif /* MSWIN32 || MSWINCE || DARWIN */ # if defined(MSWIN32) @@ -3169,7 +3170,7 @@ STATIC void GC_default_push_other_roots(void) if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) { # if !defined(MSWIN32) && !defined(MSWINCE) if (GC_print_stats) - GC_printf("Unexpected segfault at %p\n", addr); + GC_log_printf("Unexpected segfault at %p\n", addr); ABORT("Unexpected bus error or segmentation fault"); # else return(EXCEPTION_CONTINUE_SEARCH); @@ -3221,7 +3222,7 @@ STATIC void GC_default_push_other_roots(void) return EXCEPTION_CONTINUE_SEARCH; # else if (GC_print_stats) - GC_printf("Unexpected segfault at %p\n", addr); + GC_log_printf("Unexpected segfault at %p\n", addr); ABORT("Unexpected bus error or segmentation fault"); # endif } @@ -3279,7 +3280,7 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, # endif /* SIG_SUSPEND */ # endif if (GC_print_stats == VERBOSE) - GC_log_printf( + GC_log_printf( "Initializing mprotect virtual dirty bit implementation\n"); GC_dirty_maintained = TRUE; if (GC_page_size % HBLKSIZE != 0) { @@ -3629,15 +3630,13 @@ GC_INNER void GC_dirty_init(void) GC_dirty_maintained = TRUE; if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { - register int i; - - for (i = 0; i < PHT_SIZE; i++) - GC_written_pages[i] = (word)(-1); - if (GC_print_stats == VERBOSE) - GC_log_printf( - "Allocated bytes:%lu:all pages may have been written\n", - (unsigned long) - (GC_bytes_allocd + GC_bytes_allocd_before_gc)); + register int i; + for (i = 0; i < PHT_SIZE; i++) + GC_written_pages[i] = (word)(-1); + if (GC_print_stats == VERBOSE) + GC_log_printf("Allocated bytes:%lu:all pages may have been written\n", + (unsigned long)(GC_bytes_allocd + + GC_bytes_allocd_before_gc)); } sprintf(buf, "/proc/%ld", (long)getpid()); fd = open(buf, O_RDONLY); @@ -3679,8 +3678,8 @@ GC_INNER void GC_read_dirty(void) char *new_buf; if (GC_print_stats) - GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n", - (unsigned long)GC_proc_buf_size); + GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n", + (unsigned long)GC_proc_buf_size); new_buf = GC_scratch_alloc(new_size); if (new_buf != 0) { @@ -4037,8 +4036,8 @@ STATIC void *GC_mprotect_thread(void *arg) if (r != MACH_MSG_SUCCESS) { if (GC_print_stats) - GC_printf("mach_msg failed with code %d: %s\n", (int)r, - mach_error_string(r)); + GC_log_printf("mach_msg failed with code %d: %s\n", (int)r, + mach_error_string(r)); ABORT("mach_msg failed"); } @@ -4297,8 +4296,9 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, if (exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) { # ifdef DEBUG_EXCEPTION_HANDLING /* We aren't interested, pass it on to the old handler */ - GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch...\n", exception, - code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1); + GC_log_printf("Exception: 0x%x Code: 0x%x 0x%x in catch...\n", + exception, code_count > 0 ? code[0] : -1, + code_count > 1 ? code[1] : -1); # endif return FWD(); } diff --git a/pthread_start.c b/pthread_start.c index cbe5a857..48c2d95a 100644 --- a/pthread_start.c +++ b/pthread_start.c @@ -60,7 +60,7 @@ void * GC_CALLBACK GC_inner_start_routine(struct GC_stack_base *sb, void *arg) # endif result = (*start)(start_arg); # ifdef DEBUG_THREADS - GC_printf("Finishing thread 0x%x\n", (unsigned)pthread_self()); + GC_log_printf("Finishing thread 0x%x\n", (unsigned)pthread_self()); # endif me -> status = result; # ifndef NACL diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 0687bbc8..4ec6fe1f 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -65,10 +65,11 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; int i; if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) - ABORT("pthread_sigmask failed"); + ABORT("pthread_sigmask failed"); GC_printf("Blocked: "); for (i = 1; i < NSIG; i++) { - if (sigismember(&blocked, i)) { GC_printf("%d ", i); } + if (sigismember(&blocked, i)) + GC_printf("%d ", i); } GC_printf("\n"); } @@ -196,7 +197,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) /* cancellation point is inherently a problem, unless there is */ /* some way to disable cancellation in the handler. */ # ifdef DEBUG_THREADS - GC_printf("Suspending 0x%x\n", (unsigned)my_thread); + GC_log_printf("Suspending 0x%x\n", (unsigned)my_thread); # endif me = GC_lookup_thread(my_thread); @@ -250,7 +251,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) /* unlikely to be efficient. */ # ifdef DEBUG_THREADS - GC_printf("Continuing 0x%x\n", (unsigned)my_thread); + GC_log_printf("Continuing 0x%x\n", (unsigned)my_thread); # endif RESTORE_CANCEL(cancel_state); } @@ -272,7 +273,8 @@ STATIC void GC_restart_handler(int sig) */ # ifdef DEBUG_THREADS - GC_printf("In GC_restart_handler for 0x%x\n", (unsigned)pthread_self()); + GC_log_printf("In GC_restart_handler for 0x%x\n", + (unsigned)pthread_self()); # endif } @@ -299,7 +301,7 @@ GC_INNER void GC_push_all_stacks(void) if (!GC_thr_initialized) GC_thr_init(); # ifdef DEBUG_THREADS - GC_printf("Pushing stacks from thread 0x%x\n", (unsigned) me); + GC_log_printf("Pushing stacks from thread 0x%x\n", (unsigned)me); # endif for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { @@ -327,8 +329,8 @@ GC_INNER void GC_push_all_stacks(void) IF_IA64(bs_lo = BACKING_STORE_BASE;) } # ifdef DEBUG_THREADS - GC_printf("Stack for thread 0x%x = [%p,%p)\n", - (unsigned)(p -> id), lo, hi); + GC_log_printf("Stack for thread 0x%x = [%p,%p)\n", + (unsigned)(p -> id), lo, hi); # endif if (0 == lo) ABORT("GC_push_all_stacks: sp not set!"); GC_push_all_stack_sections(lo, hi, p -> traced_stack_sect); @@ -345,8 +347,8 @@ GC_INNER void GC_push_all_stacks(void) # endif # ifdef IA64 # ifdef DEBUG_THREADS - GC_printf("Reg stack for thread 0x%x = [%p,%p)\n", - (unsigned)p -> id, bs_lo, bs_hi); + GC_log_printf("Reg stack for thread 0x%x = [%p,%p)\n", + (unsigned)p -> id, bs_lo, bs_hi); # endif /* FIXME: This (if p->id==me) may add an unbounded number of */ /* entries, and hence overflow the mark stack, which is bad. */ @@ -358,7 +360,7 @@ GC_INNER void GC_push_all_stacks(void) } } if (GC_print_stats == VERBOSE) { - GC_log_printf("Pushed %d thread stacks\n", (int)nthreads); + GC_log_printf("Pushed %d thread stacks\n", (int)nthreads); } if (!found_me && !GC_in_thread_creation) ABORT("Collecting from unknown thread"); @@ -417,8 +419,8 @@ STATIC int GC_suspend_all(void) n_live_threads++; # endif # ifdef DEBUG_THREADS - GC_printf("Sending suspend signal to 0x%x\n", - (unsigned)(p -> id)); + GC_log_printf("Sending suspend signal to 0x%x\n", + (unsigned)(p -> id)); # endif # ifdef GC_OPENBSD_THREADS @@ -457,8 +459,8 @@ STATIC int GC_suspend_all(void) # define NACL_PARK_WAIT_NANOSECONDS (100 * 1000) # endif # ifdef DEBUG_THREADS - GC_printf("pthread_stop_world: num_threads %d\n", - GC_nacl_num_gc_threads - 1); + GC_log_printf("pthread_stop_world: num_threads %d\n", + GC_nacl_num_gc_threads - 1); # endif GC_nacl_thread_parker = pthread_self(); GC_nacl_park_threads_now = 1; @@ -488,8 +490,8 @@ STATIC int GC_suspend_all(void) ts.tv_sec = 0; ts.tv_nsec = NACL_PARK_WAIT_NANOSECONDS; # ifdef DEBUG_THREADS - GC_printf("Sleep waiting for %d threads to park...\n", - GC_nacl_num_gc_threads - num_threads_parked - 1); + GC_log_printf("Sleep waiting for %d threads to park...\n", + GC_nacl_num_gc_threads - num_threads_parked - 1); # endif /* This requires _POSIX_TIMERS feature. */ nanosleep(&ts, 0); @@ -507,7 +509,7 @@ GC_INNER void GC_stop_world(void) # endif GC_ASSERT(I_HOLD_LOCK()); # ifdef DEBUG_THREADS - GC_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self()); + GC_log_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self()); # endif /* Make sure all free list construction has stopped before we start. */ @@ -576,7 +578,7 @@ GC_INNER void GC_stop_world(void) GC_release_mark_lock(); # endif # ifdef DEBUG_THREADS - GC_printf("World stopped from 0x%x\n", (unsigned)pthread_self()); + GC_log_printf("World stopped from 0x%x\n", (unsigned)pthread_self()); GC_stopping_thread = 0; # endif } @@ -723,7 +725,7 @@ GC_INNER void GC_start_world(void) # endif # ifdef DEBUG_THREADS - GC_printf("World starting\n"); + GC_log_printf("World starting\n"); # endif # ifndef GC_OPENBSD_THREADS @@ -738,8 +740,8 @@ GC_INNER void GC_start_world(void) n_live_threads++; # endif # ifdef DEBUG_THREADS - GC_printf("Sending restart signal to 0x%x\n", - (unsigned)(p -> id)); + GC_log_printf("Sending restart signal to 0x%x\n", + (unsigned)(p -> id)); # endif # ifdef GC_OPENBSD_THREADS @@ -770,16 +772,16 @@ GC_INNER void GC_start_world(void) while (0 != (code = sem_wait(&GC_restart_ack_sem))) if (errno != EINTR) { if (GC_print_stats) - GC_printf("sem_wait() returned %d\n", code); + GC_log_printf("sem_wait() returned %d\n", code); ABORT("sem_wait() for restart handler failed"); } # endif # ifdef DEBUG_THREADS - GC_printf("World started\n"); + GC_log_printf("World started\n"); # endif # else /* NACL */ # ifdef DEBUG_THREADS - GC_printf("World starting...\n"); + GC_log_printf("World starting...\n"); # endif GC_nacl_park_threads_now = 0; # endif @@ -839,7 +841,7 @@ GC_INNER void GC_stop_init(void) GC_retry_signals = FALSE; } if (GC_print_stats && GC_retry_signals) { - GC_log_printf("Will retry suspend signal if necessary\n"); + GC_log_printf("Will retry suspend signal if necessary\n"); } # endif /* !GC_OPENBSD_THREADS && !NACL */ } diff --git a/pthread_support.c b/pthread_support.c index c78faeaa..0f1d9242 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -388,8 +388,8 @@ STATIC void * GC_mark_thread(void * id) my_mark_no = GC_mark_no; } # ifdef DEBUG_THREADS - GC_printf("Starting mark helper for mark number %lu\n", - (unsigned long)my_mark_no); + GC_log_printf("Starting mark helper for mark number %lu\n", + (unsigned long)my_mark_no); # endif GC_help_marker(my_mark_no); } @@ -439,7 +439,7 @@ static void start_mark_threads(void) } } if (GC_print_stats) { - GC_log_printf("Started %ld mark helper threads\n", GC_markers - 1); + GC_log_printf("Started %ld mark helper threads\n", GC_markers - 1); } pthread_attr_destroy(&attr); } @@ -861,7 +861,7 @@ STATIC void GC_fork_child_proc(void) numCpus = pm_sysinfo.idle_vp_count; # ifdef DEBUG_THREADS - GC_printf("Number of active CPUs in this system: %d\n", numCpus); + GC_log_printf("Number of active CPUs in this system: %d\n", numCpus); # endif return(numCpus); } @@ -984,8 +984,9 @@ GC_INNER void GC_thr_init(void) } # ifdef PARALLEL_MARK if (GC_print_stats) { - GC_log_printf("Number of processors = %ld, " - "number of marker threads = %ld\n", GC_nprocs, GC_markers); + GC_log_printf( + "Number of processors = %ld, number of marker threads = %ld\n", + GC_nprocs, GC_markers); } if (GC_markers <= 1) { GC_parallel = FALSE; @@ -1406,8 +1407,8 @@ GC_INNER void * GC_start_rtn_prepare_thread(void *(**pstart)(void *), my_pthread = pthread_self(); # ifdef DEBUG_THREADS - GC_printf("Starting thread 0x%x, pid = %ld, sp = %p\n", - (unsigned)my_pthread, (long) getpid(), &arg); + GC_log_printf("Starting thread 0x%x, pid = %ld, sp = %p\n", + (unsigned)my_pthread, (long)getpid(), &arg); # endif LOCK(); me = GC_register_my_thread_inner(sb, my_pthread); @@ -1418,7 +1419,7 @@ GC_INNER void * GC_start_rtn_prepare_thread(void *(**pstart)(void *), UNLOCK(); *pstart = si -> start_routine; # ifdef DEBUG_THREADS - GC_printf("start_routine = %p\n", (void *)(signed_word)(*pstart)); + GC_log_printf("start_routine = %p\n", (void *)(signed_word)(*pstart)); # endif *pstart_arg = si -> arg; sem_post(&(si -> registered)); /* Last action on si. */ @@ -1523,15 +1524,15 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread, si -> flags = my_flags; UNLOCK(); # ifdef DEBUG_THREADS - GC_printf("About to start new thread from thread 0x%x\n", - (unsigned)pthread_self()); + GC_log_printf("About to start new thread from thread 0x%x\n", + (unsigned)pthread_self()); # endif GC_need_to_lock = TRUE; result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si); # ifdef DEBUG_THREADS - GC_printf("Started thread 0x%x\n", (unsigned)(*new_thread)); + GC_log_printf("Started thread 0x%x\n", (unsigned)(*new_thread)); # endif /* Wait until child has been added to the thread table. */ /* This also ensures that we hold onto si until the child is done */ diff --git a/reclaim.c b/reclaim.c index 0199d8c7..a0f6dd32 100644 --- a/reclaim.c +++ b/reclaim.c @@ -404,10 +404,10 @@ STATIC void GC_print_block_descr(struct hblk *h, if (hhdr -> hb_n_marks != n_marks) { GC_printf("(%u:%u,%u!=%u)", hhdr -> hb_obj_kind, (unsigned)bytes, - (unsigned)hhdr -> hb_n_marks, n_marks); + (unsigned)hhdr -> hb_n_marks, n_marks); } else { GC_printf("(%u:%u,%u)", hhdr -> hb_obj_kind, - (unsigned)bytes, n_marks); + (unsigned)bytes, n_marks); } bytes += HBLKSIZE-1; bytes &= ~(HBLKSIZE-1); @@ -436,15 +436,15 @@ void GC_print_free_list(int kind, size_t sz_in_granules) struct obj_kind * ok = &GC_obj_kinds[kind]; ptr_t flh = ok -> ok_freelist[sz_in_granules]; struct hblk *lastBlock = 0; - int n = 0; + int n; - while (flh) { + for (n = 1; flh; n++) { struct hblk *block = HBLKPTR(flh); if (block != lastBlock) { - GC_printf("\nIn heap block at %p:\n\t", block); - lastBlock = block; + GC_printf("\nIn heap block at %p:\n\t", block); + lastBlock = block; } - GC_printf("%d: %p;", ++n, flh); + GC_printf("%d: %p;", n, flh); flh = obj_link(flh); } } @@ -602,7 +602,7 @@ GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old) if (GC_print_stats == VERBOSE) { GET_TIME(done_time); GC_log_printf("Disposing of reclaim lists took %lu msecs\n", - MS_TIME_DIFF(done_time,start_time)); + MS_TIME_DIFF(done_time,start_time)); } # endif return(TRUE); -- cgit v1.2.1 From e3f97b0e72363503c53cc4e7aa05071b02c1f9a4 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 3 Apr 2011 15:39:05 +0000 Subject: 2011-04-03 Ivan Maidanski * misc.c (GC_stdout, GC_write): Rename GC_stdout to GC_log (Win32 only). * misc.c (GC_write): Add for MacOS (and OS/2); change WRITE() accordingly. * misc.c (GC_write): Reformat code (Unix only). * misc.c (GC_printf): Check GC_quiet before va_start(). --HG-- branch : bdwgc --- ChangeLog | 9 ++++ misc.c | 140 ++++++++++++++++++++++++++++++-------------------------------- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index e94be3a7..642646b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-04-03 Ivan Maidanski + + * misc.c (GC_stdout, GC_write): Rename GC_stdout to GC_log (Win32 + only). + * misc.c (GC_write): Add for MacOS (and OS/2); change WRITE() + accordingly. + * misc.c (GC_write): Reformat code (Unix only). + * misc.c (GC_printf): Check GC_quiet before va_start(). + 2011-04-03 Ivan Maidanski * allchblk.c (GC_freehblk): Use GC_log_printf instead of GC_printf diff --git a/misc.c b/misc.c index b9a01e5a..22f2ba01 100644 --- a/misc.c +++ b/misc.c @@ -1048,14 +1048,13 @@ GC_API void GC_CALL GC_enable_incremental(void) GC_init(); } - #if defined(MSWIN32) || defined(MSWINCE) # if defined(_MSC_VER) && defined(_DEBUG) && !defined(MSWINCE) # include # endif - STATIC HANDLE GC_stdout = 0; + STATIC HANDLE GC_log = 0; void GC_deinit(void) { @@ -1066,19 +1065,19 @@ GC_API void GC_CALL GC_enable_incremental(void) # endif } -#ifdef THREADS -# ifdef PARALLEL_MARK -# define IF_NEED_TO_LOCK(x) if (GC_parallel || GC_need_to_lock) x +# ifdef THREADS +# ifdef PARALLEL_MARK +# define IF_NEED_TO_LOCK(x) if (GC_parallel || GC_need_to_lock) x +# else +# define IF_NEED_TO_LOCK(x) if (GC_need_to_lock) x +# endif # else -# define IF_NEED_TO_LOCK(x) if (GC_need_to_lock) x -# endif -#else -# define IF_NEED_TO_LOCK(x) -#endif +# define IF_NEED_TO_LOCK(x) +# endif /* !THREADS */ -#ifndef _MAX_PATH -# define _MAX_PATH MAX_PATH -#endif +# ifndef _MAX_PATH +# define _MAX_PATH MAX_PATH +# endif STATIC HANDLE GC_CreateLogFile(void) { @@ -1127,19 +1126,19 @@ GC_API void GC_CALL GC_enable_incremental(void) # ifdef THREADS GC_ASSERT(!GC_write_disabled); # endif - if (GC_stdout == INVALID_HANDLE_VALUE) { + if (GC_log == INVALID_HANDLE_VALUE) { IF_NEED_TO_LOCK(LeaveCriticalSection(&GC_write_cs)); return -1; - } else if (GC_stdout == 0) { - GC_stdout = GC_CreateLogFile(); + } else if (GC_log == 0) { + GC_log = GC_CreateLogFile(); /* Ignore open log failure if the collector is built with */ /* print_stats always set on. */ # ifndef GC_PRINT_VERBOSE_STATS - if (GC_stdout == INVALID_HANDLE_VALUE) + if (GC_log == INVALID_HANDLE_VALUE) ABORT("Open of log file failed"); # endif } - tmp = WriteFile(GC_stdout, buf, (DWORD)len, &written, NULL); + tmp = WriteFile(GC_log, buf, (DWORD)len, &written, NULL); if (!tmp) DebugBreak(); # if defined(_MSC_VER) && defined(_DEBUG) @@ -1161,86 +1160,81 @@ GC_API void GC_CALL GC_enable_incremental(void) return tmp ? (int)written : -1; } -#endif /* MSWIN32 */ + /* FIXME: This is pretty ugly ... */ +# define WRITE(f, buf, len) GC_write(buf, len) -#if defined(OS2) || defined(MACOS) +#elif defined(OS2) || defined(MACOS) STATIC FILE * GC_stdout = NULL; STATIC FILE * GC_stderr = NULL; STATIC FILE * GC_log = NULL; + /* Initialize GC_log (and the friends) passed to GC_write(). */ STATIC void GC_set_files(void) { - if (GC_stdout == NULL) { - GC_stdout = stdout; + if (GC_stdout == NULL) { + GC_stdout = stdout; } if (GC_stderr == NULL) { - GC_stderr = stderr; + GC_stderr = stderr; } if (GC_log == NULL) { - GC_log = stderr; + GC_log = stderr; } } -#endif -#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) + GC_INLINE int GC_write(FILE *f, const char *buf, size_t len) + { + int res = fwrite(buf, 1, len, f); + fflush(f); + return res; + } + +# define WRITE(f, buf, len) (GC_set_files(), GC_write(f, buf, len)) + +#else STATIC int GC_stdout = 1; STATIC int GC_stderr = 2; + /* GC_log is defined above. */ # if !defined(AMIGA) # include # endif -#endif -#if defined(ECOS) || defined(NOSYS) STATIC int GC_write(int fd, const char *buf, size_t len) { -# ifdef ECOS - /* FIXME: This seems to be defined nowhere at present. */ - /* _Jv_diag_write(buf, len); */ +# if defined(ECOS) || defined(NOSYS) +# ifdef ECOS + /* FIXME: This seems to be defined nowhere at present. */ + /* _Jv_diag_write(buf, len); */ +# else + /* No writing. */ +# endif + return len; # else - /* No writing. */ + int bytes_written = 0; + int result; + IF_CANCEL(int cancel_state;) + + DISABLE_CANCEL(cancel_state); + while (bytes_written < len) { +# ifdef GC_SOLARIS_THREADS + result = syscall(SYS_write, fd, buf + bytes_written, + len - bytes_written); +# else + result = write(fd, buf + bytes_written, len - bytes_written); +# endif + if (-1 == result) { + RESTORE_CANCEL(cancel_state); + return(result); + } + bytes_written += result; + } + RESTORE_CANCEL(cancel_state); + return(bytes_written); # endif - return len; - } -#elif !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \ - && !defined(MACOS) - STATIC int GC_write(int fd, const char *buf, size_t len) - { - int bytes_written = 0; - int result; - IF_CANCEL(int cancel_state;) - - DISABLE_CANCEL(cancel_state); - while (bytes_written < len) { -# ifdef GC_SOLARIS_THREADS - result = syscall(SYS_write, fd, buf + bytes_written, - len - bytes_written); -# else - result = write(fd, buf + bytes_written, len - bytes_written); -# endif - if (-1 == result) { - RESTORE_CANCEL(cancel_state); - return(result); - } - bytes_written += result; - } - RESTORE_CANCEL(cancel_state); - return(bytes_written); } -#endif /* UN*X */ -#if defined(MSWIN32) || defined(MSWINCE) - /* FIXME: This is pretty ugly ... */ -# define WRITE(f, buf, len) GC_write(buf, len) -#else -# if defined(OS2) || defined(MACOS) - static int fwrite_gc_res; /* Should really be local ... */ -# define WRITE(f, buf, len) (GC_set_files(), \ - fwrite_gc_res = fwrite((buf), 1, (len), (f)), \ - fflush(f), fwrite_gc_res) -# else -# define WRITE(f, buf, len) GC_write((f), (buf), (len)) -# endif -#endif +# define WRITE(f, buf, len) GC_write(f, buf, len) +#endif /* !MSWIN32 && !OS2 && !MACOS */ #define BUFSZ 1024 #ifdef _MSC_VER @@ -1261,8 +1255,8 @@ void GC_printf(const char *format, ...) va_list args; char buf[BUFSZ+1]; - va_start(args, format); if (GC_quiet) return; + va_start(args, format); buf[BUFSZ] = 0x15; (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); -- cgit v1.2.1 From 50cc9c0285d3ad7ec401e14a2c66e74ef458def6 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 3 Apr 2011 19:29:08 +0000 Subject: 2011-04-03 Ivan Maidanski * misc.c (GC_stdout, GC_stderr): Move the definition to the place where GC_log is defined (Unix only). * misc.c (GC_init): Recognize "GC_ONLY_LOG_TO_FILE" environment variable and the similar macro; redirect GC_stdout and GC_stderr to GC_log if "GC_LOG_FILE" environment variable is set unless prohibited by GC_ONLY_LOG_TO_FILE (Unix only). * doc/README.environment (GC_ONLY_LOG_TO_FILE): Document. * doc/README.macros (GC_ONLY_LOG_TO_FILE): Ditto. --HG-- branch : bdwgc --- ChangeLog | 11 +++++++++++ doc/README.environment | 4 ++++ doc/README.macros | 4 ++++ misc.c | 23 +++++++++++++++++++---- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 642646b0..c349fc5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-04-03 Ivan Maidanski + + * misc.c (GC_stdout, GC_stderr): Move the definition to the place + where GC_log is defined (Unix only). + * misc.c (GC_init): Recognize "GC_ONLY_LOG_TO_FILE" environment + variable and the similar macro; redirect GC_stdout and GC_stderr + to GC_log if "GC_LOG_FILE" environment variable is set unless + prohibited by GC_ONLY_LOG_TO_FILE (Unix only). + * doc/README.environment (GC_ONLY_LOG_TO_FILE): Document. + * doc/README.macros (GC_ONLY_LOG_TO_FILE): Ditto. + 2011-04-03 Ivan Maidanski * misc.c (GC_stdout, GC_write): Rename GC_stdout to GC_log (Win32 diff --git a/doc/README.environment b/doc/README.environment index 07a4ebf3..ef7c7cb5 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -20,6 +20,10 @@ GC_PRINT_STATS - Turn on GC logging. Not functional with SMALL_CONFIG. GC_LOG_FILE - The name of the log file. Stderr by default. Not functional with SMALL_CONFIG. +GC_ONLY_LOG_TO_FILE - Turns off redirection of GC stdout and stderr to the log + file specified by GC_LOG_FILE. Has no effect unless + GC_LOG_FILE is set. Not functional with SMALL_CONFIG. + GC_PRINT_VERBOSE_STATS - Turn on even more logging. Not functional with SMALL_CONFIG. diff --git a/doc/README.macros b/doc/README.macros index ac788971..50eab283 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -502,6 +502,10 @@ GC_IGNORE_GCJ_INFO Disable GCJ-style type information (useful for GC_PRINT_VERBOSE_STATS Permanently turn on verbose logging (useful for debugging and profiling on WinCE). +GC_ONLY_LOG_TO_FILE Don't redirect GC stdout and stderr to the log file + specified by GC_LOG_FILE environment variable. Has effect only when the + variable is set (to anything other than "0"). + GC_DONT_EXPAND Don't expand the heap unless explicitly requested or forced to. GC_USE_ENTIRE_HEAP Causes the non-incremental collector to use the diff --git a/misc.c b/misc.c index 22f2ba01..a27d9aa4 100644 --- a/misc.c +++ b/misc.c @@ -627,7 +627,9 @@ STATIC void GC_exit_check(void) #endif #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) - STATIC int GC_log = 2; + STATIC int GC_stdout = 1; + STATIC int GC_stderr = 2; + STATIC int GC_log = 2; /* stderr */ #endif GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */ @@ -713,7 +715,23 @@ GC_API void GC_CALL GC_init(void) if (log_d < 0) { GC_err_printf("Failed to open %s as log file\n", file_name); } else { + char *str; GC_log = log_d; + str = GETENV("GC_ONLY_LOG_TO_FILE"); +# ifdef GC_ONLY_LOG_TO_FILE + /* The similar environment variable set to "0" */ + /* overrides the effect of the macro defined. */ + if (str != NULL && *str == '0' && *(str + 1) == '\0') +# else + /* Otherwise setting the environment variable */ + /* to anything other than "0" will prevent from */ + /* redirecting stdout/err to the log file. */ + if (str == NULL || (*str == '0' && *(str + 1) == '\0')) +# endif + { + GC_stdout = log_d; + GC_stderr = log_d; + } } } } @@ -1192,9 +1210,6 @@ GC_API void GC_CALL GC_enable_incremental(void) # define WRITE(f, buf, len) (GC_set_files(), GC_write(f, buf, len)) #else - STATIC int GC_stdout = 1; - STATIC int GC_stderr = 2; - /* GC_log is defined above. */ # if !defined(AMIGA) # include # endif -- cgit v1.2.1 From 0c33f9584ba9dc08c87a6ade32f50fadae8a164b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 4 Apr 2011 19:45:07 +0000 Subject: 2011-04-04 Ivan Maidanski * tests/test.c (reverse_test_inner): Undo one of the previous patches which shifts "c" and "d" pointers only if ALL_INTERIOR_POINTERS (since interior pointers are always recognized in stacks). --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ tests/test.c | 17 +++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c349fc5c..26522ba0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-04-04 Ivan Maidanski + + * tests/test.c (reverse_test_inner): Undo one of the previous + patches which shifts "c" and "d" pointers only if + ALL_INTERIOR_POINTERS (since interior pointers are always + recognized in stacks). + 2011-04-03 Ivan Maidanski * misc.c (GC_stdout, GC_stderr): Move the definition to the place diff --git a/tests/test.c b/tests/test.c index ee0cd97c..d6e2fc88 100644 --- a/tests/test.c +++ b/tests/test.c @@ -585,14 +585,12 @@ void *GC_CALLBACK reverse_test_inner(void *data) h[1999] = ints(1,200); # endif /* Try to force some collections and reuse of small list elements */ - for (i = 0; i < 10; i++) { - (void)ints(1, BIG); - } -# ifdef ALL_INTERIOR_POINTERS - /* Superficially test interior pointer recognition on stack */ - c = (sexpr)((char *)c + sizeof(char *)); - d = (sexpr)((char *)d + sizeof(char *)); -# endif + for (i = 0; i < 10; i++) { + (void)ints(1, BIG); + } + /* Superficially test interior pointer recognition on stack */ + c = (sexpr)((char *)c + sizeof(char *)); + d = (sexpr)((char *)d + sizeof(char *)); GC_FREE((void *)e); @@ -623,8 +621,11 @@ void *GC_CALLBACK reverse_test_inner(void *data) } check_ints(a,1,49); check_ints(b,1,50); + + /* Restore c and d values. */ c = (sexpr)((char *)c - sizeof(char *)); d = (sexpr)((char *)d - sizeof(char *)); + check_ints(c,1,BIG); check_uncollectable_ints(d, 1, 100); check_ints(f[5], 1,17); -- cgit v1.2.1 From f85b3cefdd7430b68aaef6a9b6b9d40848daf026 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 7 Apr 2011 20:35:46 +0000 Subject: 2011-04-07 Ivan Maidanski * alloc.c (GC_check_heap, GC_print_all_smashed): Move the definition from misc.c. * dbg_mlc.c (GC_debug_malloc_atomic_uncollectable): Define as public. * include/gc.h (GC_debug_malloc_atomic_uncollectable): Declare. * include/gc.h (GC_MALLOC_ATOMIC_UNCOLLECTABLE): Define new public macro. * dbg_mlc.c (MAX_SMASHED): Don't define if already set. * reclaim.c (MAX_LEAKED): Ditto. * dbg_mlc.c (GC_add_smashed): Add FIXME about the concurrent access to the global array. * reclaim.c (GC_add_leaked): Ditto. * misc.c (GC_print_back_height): Set on if GC_PRINT_BACK_HEIGHT (new macro) is defined. * doc/README.macros (GC_PRINT_BACK_HEIGHT): Document. * misc.c (GC_dump_regularly, GC_init): Replace 0/1 for GC_dump_regularly and GC_print_back_height variables with FALSE/TRUE. * reclaim.c (GC_print_all_errors): Refine the comment. --HG-- branch : bdwgc --- ChangeLog | 22 ++++++++++++++++++++++ alloc.c | 3 +++ dbg_mlc.c | 43 +++++++++++++++++++++++-------------------- doc/README.macros | 4 ++++ include/gc.h | 18 ++++++++++++------ include/private/gc_priv.h | 3 ++- misc.c | 15 ++++++++------- reclaim.c | 11 +++++++---- 8 files changed, 81 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 26522ba0..db572e12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-04-07 Ivan Maidanski + + * alloc.c (GC_check_heap, GC_print_all_smashed): Move the + definition from misc.c. + * dbg_mlc.c (GC_debug_malloc_atomic_uncollectable): Define as + public. + * include/gc.h (GC_debug_malloc_atomic_uncollectable): Declare. + * include/gc.h (GC_MALLOC_ATOMIC_UNCOLLECTABLE): Define new public + macro. + * dbg_mlc.c (MAX_SMASHED): Don't define if already set. + * reclaim.c (MAX_LEAKED): Ditto. + * dbg_mlc.c (GC_add_smashed): Add FIXME about the concurrent + access to the global array. + * reclaim.c (GC_add_leaked): Ditto. + * misc.c (GC_print_back_height): Set on if GC_PRINT_BACK_HEIGHT + (new macro) is defined. + * doc/README.macros (GC_PRINT_BACK_HEIGHT): Document. + * misc.c (GC_dump_regularly, GC_init): Replace 0/1 for + GC_dump_regularly and GC_print_back_height variables with + FALSE/TRUE. + * reclaim.c (GC_print_all_errors): Refine the comment. + 2011-04-04 Ivan Maidanski * tests/test.c (reverse_test_inner): Undo one of the previous diff --git a/alloc.c b/alloc.c index dffbc014..79fce2a2 100644 --- a/alloc.c +++ b/alloc.c @@ -541,6 +541,9 @@ GC_INNER void GC_collect_a_little_inner(int n) RESTORE_CANCEL(cancel_state); } +GC_INNER void (*GC_check_heap)(void) = 0; +GC_INNER void (*GC_print_all_smashed)(void) = 0; + GC_API int GC_CALL GC_collect_a_little(void) { int result; diff --git a/dbg_mlc.c b/dbg_mlc.c index f8727f6b..bc14d08c 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -571,11 +571,11 @@ 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 /* DBG_HDRS_ALL */ #ifdef STUBBORN_ALLOC -GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) -{ + GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) + { void * result = GC_malloc_stubborn(lb + DEBUG_BYTES); if (result == 0) { @@ -590,10 +590,10 @@ GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) } ADD_CALL_CHAIN(result, ra); return (GC_store_debug_info(result, (word)lb, s, (word)i)); -} + } -GC_API void GC_CALL GC_debug_change_stubborn(void *p) -{ + GC_API void GC_CALL GC_debug_change_stubborn(void *p) + { void * q = GC_base(p); hdr * hhdr; @@ -607,10 +607,10 @@ GC_API void GC_CALL GC_debug_change_stubborn(void *p) ABORT("GC_debug_change_stubborn: arg not stubborn"); } GC_change_stubborn(q); -} + } -GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) -{ + GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) + { void * q = GC_base(p); hdr * hhdr; @@ -624,21 +624,20 @@ GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) ABORT("GC_debug_end_stubborn_change: arg not stubborn"); } GC_end_stubborn_change(q); -} + } #else /* !STUBBORN_ALLOC */ -GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) -{ + GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) + { return GC_debug_malloc(lb, OPT_RA s, i); -} - -/*ARGSUSED*/ -GC_API void GC_CALL GC_debug_change_stubborn(void *p) {} + } -/*ARGSUSED*/ -GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) {} + /*ARGSUSED*/ + GC_API void GC_CALL GC_debug_change_stubborn(void *p) {} + /*ARGSUSED*/ + GC_API void GC_CALL GC_debug_end_stubborn_change(void *p) {} #endif /* !STUBBORN_ALLOC */ GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS) @@ -742,7 +741,8 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, } #ifdef ATOMIC_UNCOLLECTABLE - void * GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS) + GC_API void * GC_CALL GC_debug_malloc_atomic_uncollectable(size_t lb, + GC_EXTRA_PARAMS) { void * result = GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); @@ -913,13 +913,16 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) /* always print them nicely with the allocation lock held. */ /* We put them here instead of in GC_arrays, since it may be useful to */ /* be able to look at them with the debugger. */ -#define MAX_SMASHED 20 +#ifndef MAX_SMASHED +# define MAX_SMASHED 20 +#endif STATIC ptr_t GC_smashed[MAX_SMASHED] = {0}; STATIC unsigned GC_n_smashed = 0; STATIC void GC_add_smashed(ptr_t smashed) { GC_ASSERT(GC_is_marked(GC_base(smashed))); + /* FIXME: Prevent adding an object while printing smashed list. */ GC_smashed[GC_n_smashed] = smashed; if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed; /* In case of overflow, we keep the first MAX_SMASHED-1 */ diff --git a/doc/README.macros b/doc/README.macros index 50eab283..1b492000 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -416,6 +416,10 @@ MAKE_BACK_GRAPH Enable GC_PRINT_BACK_HEIGHT environment variable. support. Implies DBG_HDRS_ALL. All allocation should be done using the debug interface. +GC_PRINT_BACK_HEIGHT Permanently turn on back-height printing mode + (useful when NO_GETENV). See the similar environment variable description + in README.environment. Requires MAKE_BACK_GRAPH defined. + STUBBORN_ALLOC Allows allocation of "hard to change" objects, and thus makes incremental collection easier. Was enabled by default until 6.0. Rarely used, to my knowledge. diff --git a/include/gc.h b/include/gc.h index 2354acdc..e702fd25 100644 --- a/include/gc.h +++ b/include/gc.h @@ -364,12 +364,6 @@ GC_API void * GC_CALL GC_memalign(size_t /* align */, size_t /* lb */) GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */, size_t /* lb */); -/* The following is only defined if the library has been suitably */ -/* compiled: */ -GC_API void * GC_CALL GC_malloc_atomic_uncollectable( - size_t /* size_in_bytes */) - GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1); - /* Explicitly deallocate an object. Dangerous if used incorrectly. */ /* Requires a pointer to the base of an object. */ /* If the argument is stubborn, it should not be changeable when freed. */ @@ -597,6 +591,15 @@ GC_API void * GC_CALL GC_malloc_atomic_ignore_off_page(size_t /* lb */) # define GC_EXTRA_PARAMS const char * s, int i #endif +/* The following is only defined if the library has been suitably */ +/* compiled: */ +GC_API void * GC_CALL GC_malloc_atomic_uncollectable( + size_t /* size_in_bytes */) + GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1); +GC_API void * GC_CALL GC_debug_malloc_atomic_uncollectable(size_t, + GC_EXTRA_PARAMS) + GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1); + /* Debugging (annotated) allocation. GC_gcollect will check */ /* objects allocated in this way for overwrites, etc. */ GC_API void * GC_CALL GC_debug_malloc(size_t /* size_in_bytes */, @@ -661,6 +664,8 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */, # define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS) # define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS) # define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS) +# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) \ + GC_debug_malloc_atomic_uncollectable(sz, GC_EXTRAS) # define GC_MALLOC_UNCOLLECTABLE(sz) \ GC_debug_malloc_uncollectable(sz, GC_EXTRAS) # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ @@ -686,6 +691,7 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */, # define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz) # define GC_STRDUP(s) GC_strdup(s) # define GC_STRNDUP(s, sz) GC_strndup(s, sz) +# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) GC_malloc_atomic_uncollectable(sz) # define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz) # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ GC_malloc_ignore_off_page(sz) diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index b8f48792..89195327 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1788,7 +1788,8 @@ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ /* Call error printing routine */ - /* occasionally. */ + /* occasionally. It is ok to read it */ + /* without acquiring the lock. */ #ifndef SMALL_CONFIG /* GC_print_stats should be visible outside the GC in some cases. */ diff --git a/misc.c b/misc.c index a27d9aa4..51a92483 100644 --- a/misc.c +++ b/misc.c @@ -76,9 +76,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 */ -GC_INNER void (*GC_check_heap)(void) = 0; -GC_INNER void (*GC_print_all_smashed)(void) = 0; - ptr_t GC_stackbottom = 0; #ifdef IA64 @@ -95,10 +92,14 @@ GC_bool GC_quiet = 0; /* used also in pcr_interface.c */ GC_bool GC_print_stats = 0; #endif -GC_INNER GC_bool GC_print_back_height = 0; +#ifdef GC_PRINT_BACK_HEIGHT + GC_INNER GC_bool GC_print_back_height = TRUE; +#else + GC_INNER GC_bool GC_print_back_height = FALSE; +#endif #ifndef NO_DEBUGGING - GC_INNER GC_bool GC_dump_regularly = 0; + GC_INNER GC_bool GC_dump_regularly = FALSE; /* Generate regular debugging dumps. */ #endif @@ -739,7 +740,7 @@ GC_API void GC_CALL GC_init(void) # endif /* !SMALL_CONFIG */ # ifndef NO_DEBUGGING if (0 != GETENV("GC_DUMP_REGULARLY")) { - GC_dump_regularly = 1; + GC_dump_regularly = TRUE; } # endif # ifdef KEEP_BACK_PTRS @@ -761,7 +762,7 @@ GC_API void GC_CALL GC_init(void) GC_dont_gc = 1; } if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) { - GC_print_back_height = 1; + GC_print_back_height = TRUE; } if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) { GC_large_alloc_warn_interval = LONG_MAX; diff --git a/reclaim.c b/reclaim.c index a0f6dd32..e17d374a 100644 --- a/reclaim.c +++ b/reclaim.c @@ -33,7 +33,9 @@ GC_INNER signed_word GC_bytes_found = 0; /* We defer printing of leaked objects until we're done with the GC */ /* cycle, since the routine for printing objects needs to run outside */ /* the collector, e.g. without the allocation lock. */ -#define MAX_LEAKED 40 +#ifndef MAX_LEAKED +# define MAX_LEAKED 40 +#endif STATIC ptr_t GC_leaked[MAX_LEAKED] = { NULL }; STATIC unsigned GC_n_leaked = 0; @@ -41,16 +43,17 @@ GC_INNER GC_bool GC_have_errors = FALSE; STATIC void GC_add_leaked(ptr_t leaked) { + GC_have_errors = TRUE; + /* FIXME: Prevent adding an object while printing leaked ones. */ if (GC_n_leaked < MAX_LEAKED) { - GC_have_errors = TRUE; GC_leaked[GC_n_leaked++] = leaked; /* Make sure it's not reclaimed this cycle */ - GC_set_mark_bit(leaked); + GC_set_mark_bit(leaked); } } /* Print all objects on the list after printing any smashed objects. */ -/* Clear both lists. */ +/* Clear both lists. Called without the allocation lock held. */ GC_INNER void GC_print_all_errors(void) { static GC_bool printing_errors = FALSE; -- cgit v1.2.1 From d93efdc8ba272a4e4399f5b664f42b47830289de Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 9 Apr 2011 10:50:55 +0000 Subject: 2011-04-09 Ivan Maidanski * dbg_mlc.c (GC_register_finalizer_no_order): Remove redundant declaration. * dbg_mlc.c (GC_debug_malloc_replacement, GC_debug_realloc_replacement): Rename RA to GC_DBG_RA. * malloc.c (GC_debug_malloc_replacement): Ditto. * mallocx.c (GC_debug_realloc_replacement): Ditto. * dbg_mlc.c (GC_store_debug_info): Move proto from dbg_mlc.h. * malloc.c (GC_strdup, GC_strndup, GC_wcsdup): Move to mallocx.c. * malloc.c: Include errno.h only REDIRECT_MALLOC; remove redundant includes of string.h. * mallocx.c: Include string.h (for GC_strdup). * include/private/dbg_mlc.h (GC_store_debug_info): Move declaration to dbg_mlc.c. * include/private/gc_locks.h (UNCOND_LOCK, UNCOND_UNLOCK): Remove redundant trailing ';'. * include/private/gc_priv.h (START_WORLD, COND_DUMP): Ditto. * include/private/gc_locks.h (LOCK, UNLOCK): Place opening '{' properly. * include/private/gc_priv.h (GC_DBG_RA): Move from dbg_mlc.c, malloc.c, mallocx.c. --HG-- branch : bdwgc --- ChangeLog | 23 +++++++++++++ dbg_mlc.c | 36 ++++++++------------ gcj_mlc.c | 9 +++-- include/private/dbg_mlc.h | 5 --- include/private/gc_locks.h | 34 +++++++++---------- include/private/gc_priv.h | 12 +++++-- malloc.c | 82 +++++----------------------------------------- mallocx.c | 68 ++++++++++++++++++++++++++++++++++---- 8 files changed, 139 insertions(+), 130 deletions(-) diff --git a/ChangeLog b/ChangeLog index db572e12..46cdbc55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2011-04-09 Ivan Maidanski + + * dbg_mlc.c (GC_register_finalizer_no_order): Remove redundant + declaration. + * dbg_mlc.c (GC_debug_malloc_replacement, + GC_debug_realloc_replacement): Rename RA to GC_DBG_RA. + * malloc.c (GC_debug_malloc_replacement): Ditto. + * mallocx.c (GC_debug_realloc_replacement): Ditto. + * dbg_mlc.c (GC_store_debug_info): Move proto from dbg_mlc.h. + * malloc.c (GC_strdup, GC_strndup, GC_wcsdup): Move to mallocx.c. + * malloc.c: Include errno.h only REDIRECT_MALLOC; remove redundant + includes of string.h. + * mallocx.c: Include string.h (for GC_strdup). + * include/private/dbg_mlc.h (GC_store_debug_info): Move declaration + to dbg_mlc.c. + * include/private/gc_locks.h (UNCOND_LOCK, UNCOND_UNLOCK): Remove + redundant trailing ';'. + * include/private/gc_priv.h (START_WORLD, COND_DUMP): Ditto. + * include/private/gc_locks.h (LOCK, UNLOCK): Place opening '{' + properly. + * include/private/gc_priv.h (GC_DBG_RA): Move from dbg_mlc.c, + malloc.c, mallocx.c. + 2011-04-07 Ivan Maidanski * alloc.c (GC_check_heap, GC_print_all_smashed): Move the diff --git a/dbg_mlc.c b/dbg_mlc.c index bc14d08c..feaf51ad 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -24,10 +24,6 @@ GC_INNER 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); - #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 */ @@ -58,7 +54,7 @@ GC_API void GC_CALL GC_register_finalizer_no_order(void * obj, } return(FALSE); } -#endif +#endif /* !SHORT_DBG_HDRS */ #ifdef KEEP_BACK_PTRS @@ -459,16 +455,16 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) GC_INNER void GC_start_debugging(void) { -# ifndef SHORT_DBG_HDRS - GC_check_heap = GC_check_heap_proc; - GC_print_all_smashed = GC_print_all_smashed_proc; -# else - GC_check_heap = GC_do_nothing; - GC_print_all_smashed = GC_do_nothing; -# endif - GC_print_heap_obj = GC_debug_print_heap_obj_proc; - GC_debugging_started = TRUE; - GC_register_displacement((word)sizeof(oh)); +# ifndef SHORT_DBG_HDRS + GC_check_heap = GC_check_heap_proc; + GC_print_all_smashed = GC_print_all_smashed_proc; +# else + GC_check_heap = GC_do_nothing; + GC_print_all_smashed = GC_do_nothing; +# endif + GC_print_heap_obj = GC_debug_print_heap_obj_proc; + GC_debugging_started = TRUE; + GC_register_displacement((word)sizeof(oh)); } size_t GC_debug_header_size = sizeof(oh); @@ -1165,18 +1161,12 @@ GC_API void GC_CALL GC_debug_register_finalizer_ignore_self store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); } -#ifdef GC_ADD_CALLER -# define RA GC_RETURN_ADDR, -#else -# define RA -#endif - GC_API void * GC_CALL GC_debug_malloc_replacement(size_t lb) { - return GC_debug_malloc(lb, RA "unknown", 0); + return GC_debug_malloc(lb, GC_DBG_RA "unknown", 0); } GC_API void * GC_CALL GC_debug_realloc_replacement(void *p, size_t lb) { - return GC_debug_realloc(p, lb, RA "unknown", 0); + return GC_debug_realloc(p, lb, GC_DBG_RA "unknown", 0); } diff --git a/gcj_mlc.c b/gcj_mlc.c index 6c160c49..7afa6bf2 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -199,7 +199,12 @@ static void maybe_finalize(void) return((void *) op); } -GC_INNER void GC_start_debugging(void); +GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */ + +/* Store debugging info into p. Return displaced pointer. */ +/* Assumes we don't hold allocation lock. */ +GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, + word integer); /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ /* with GC_gcj_debug_kind. */ @@ -209,7 +214,7 @@ GC_API void * GC_CALL GC_debug_gcj_malloc(size_t lb, void * result; DCL_LOCK_STATE; - /* We're careful to avoid extra calls, which could */ + /* We're careful to avoid extra calls, which could */ /* confuse the backtrace. */ LOCK(); maybe_finalize(); diff --git a/include/private/dbg_mlc.h b/include/private/dbg_mlc.h index 45dc1812..a6f2ef6a 100644 --- a/include/private/dbg_mlc.h +++ b/include/private/dbg_mlc.h @@ -160,9 +160,4 @@ typedef struct { # define GC_HAS_DEBUG_INFO(p) GC_has_other_debug_info(p) #endif -/* Store debugging info into p. Return displaced pointer. */ -/* Assumes we don't hold allocation lock. */ -GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, - word integer); - #endif /* _DBG_MLC_H */ diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h index 3b0d1c3a..f5119b89 100644 --- a/include/private/gc_locks.h +++ b/include/private/gc_locks.h @@ -64,8 +64,8 @@ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ LeaveCriticalSection(&GC_allocate_ml); } # else -# define UNCOND_LOCK() EnterCriticalSection(&GC_allocate_ml); -# define UNCOND_UNLOCK() LeaveCriticalSection(&GC_allocate_ml); +# define UNCOND_LOCK() EnterCriticalSection(&GC_allocate_ml) +# define UNCOND_UNLOCK() LeaveCriticalSection(&GC_allocate_ml) # endif /* !GC_ASSERTIONS */ # define SET_LOCK_HOLDER() GC_lock_holder = GetCurrentThreadId() # define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD @@ -125,18 +125,17 @@ /* GC_call_with_alloc_lock. */ # ifdef GC_ASSERTIONS # define UNCOND_LOCK() \ - { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ - GC_lock(); \ - SET_LOCK_HOLDER(); } + { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ + GC_lock(); \ + SET_LOCK_HOLDER(); } # define UNCOND_UNLOCK() \ - { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ - AO_CLEAR(&GC_allocate_lock); } + { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ + AO_CLEAR(&GC_allocate_lock); } # else # define UNCOND_LOCK() \ - { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ - GC_lock(); } -# define UNCOND_UNLOCK() \ - AO_CLEAR(&GC_allocate_lock) + { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ + GC_lock(); } +# define UNCOND_UNLOCK() AO_CLEAR(&GC_allocate_lock) # endif /* !GC_ASSERTIONS */ # else /* THREAD_LOCAL_ALLOC || USE_PTHREAD_LOCKS */ # ifndef USE_PTHREAD_LOCKS @@ -147,18 +146,17 @@ # include GC_EXTERN pthread_mutex_t GC_allocate_ml; # ifdef GC_ASSERTIONS -# define UNCOND_LOCK() \ - { GC_lock(); \ - SET_LOCK_HOLDER(); } +# define UNCOND_LOCK() { GC_lock(); SET_LOCK_HOLDER(); } # define UNCOND_UNLOCK() \ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ pthread_mutex_unlock(&GC_allocate_ml); } # else /* !GC_ASSERTIONS */ # if defined(NO_PTHREAD_TRYLOCK) -# define UNCOND_LOCK() GC_lock(); +# define UNCOND_LOCK() GC_lock() # else /* !defined(NO_PTHREAD_TRYLOCK) */ # define UNCOND_LOCK() \ - { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); } + { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) \ + GC_lock(); } # endif # define UNCOND_UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) # endif /* !GC_ASSERTIONS */ @@ -201,8 +199,8 @@ #if defined(UNCOND_LOCK) && !defined(LOCK) /* At least two thread running; need to lock. */ -# define LOCK() if (GC_need_to_lock) { UNCOND_LOCK(); } -# define UNLOCK() if (GC_need_to_lock) { UNCOND_UNLOCK(); } +# define LOCK() { if (GC_need_to_lock) UNCOND_LOCK(); } +# define UNLOCK() { if (GC_need_to_lock) UNCOND_UNLOCK(); } #endif # ifndef ENTER_GC diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 89195327..7f3f5081 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -399,7 +399,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define START_WORLD() \ PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_null, \ PCR_allSigsBlocked, \ - PCR_waitForever); + PCR_waitForever) # else # if defined(GC_WIN32_THREADS) || defined(GC_PTHREADS) GC_INNER void GC_stop_world(void); @@ -1709,6 +1709,12 @@ GC_INNER ptr_t GC_allocobj(size_t sz, int kind); GC_INNER void * GC_clear_stack(void *); /* in misc.c, behaves like identity. */ +#ifdef GC_ADD_CALLER +# define GC_DBG_RA GC_RETURN_ADDR, +#else +# define GC_DBG_RA /* empty */ +#endif + /* We make the GC_clear_stack() call a tail one, hoping to get more of */ /* the stack. */ #define GENERAL_MALLOC(lb,k) \ @@ -1805,9 +1811,9 @@ GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ #ifndef NO_DEBUGGING GC_EXTERN GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */ -# define COND_DUMP if (GC_dump_regularly) GC_dump(); +# define COND_DUMP if (GC_dump_regularly) GC_dump() #else -# define COND_DUMP +# define COND_DUMP /* empty */ #endif #ifdef KEEP_BACK_PTRS diff --git a/malloc.c b/malloc.c index 026e3f9c..781d65ab 100644 --- a/malloc.c +++ b/malloc.c @@ -17,9 +17,6 @@ #include #include -#ifndef MSWINCE -# include -#endif GC_INNER void GC_extend_size_map(size_t); /* in misc.c */ @@ -232,65 +229,6 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) } } -/* provide a version of strdup() that uses the collector to allocate the - copy of the string */ -GC_API char * GC_CALL GC_strdup(const char *s) -{ - char *copy; - size_t lb; - if (s == NULL) return NULL; - lb = strlen(s) + 1; - if ((copy = GC_malloc_atomic(lb)) == NULL) { -# ifndef MSWINCE - errno = ENOMEM; -# endif - return NULL; - } -# ifndef MSWINCE - strcpy(copy, s); -# else - /* strcpy() is deprecated in WinCE */ - memcpy(copy, s, lb); -# endif - return copy; -} - -GC_API char * GC_CALL GC_strndup(const char *str, size_t size) -{ - char *copy; - size_t len = strlen(str); /* str is expected to be non-NULL */ - if (len > size) - len = size; - copy = GC_malloc_atomic(len + 1); - if (copy == NULL) { -# ifndef MSWINCE - errno = ENOMEM; -# endif - return NULL; - } - BCOPY(str, copy, len); - copy[len] = '\0'; - return copy; -} - -#ifdef GC_REQUIRE_WCSDUP -# include /* for wcslen() */ - - GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *str) - { - size_t lb = (wcslen(str) + 1) * sizeof(wchar_t); - wchar_t *copy = GC_malloc_atomic(lb); - if (copy == NULL) { -# ifndef MSWINCE - errno = ENOMEM; -# endif - return NULL; - } - BCOPY(str, copy, lb); - return copy; - } -#endif /* GC_REQUIRE_WCSDUP */ - /* Allocate lb bytes of composite (pointerful) data */ #ifdef THREAD_LOCAL_ALLOC GC_INNER void * GC_core_malloc(size_t lb) @@ -326,19 +264,19 @@ GC_API char * GC_CALL GC_strndup(const char *str, size_t size) } } -# ifdef REDIRECT_MALLOC +#ifdef REDIRECT_MALLOC + +# ifndef MSWINCE +# include +# endif /* Avoid unnecessary nested procedure calls here, by #defining some */ /* malloc replacements. Otherwise we end up saving a */ /* meaningless return address in the object. It also speeds things up, */ /* but it is admittedly quite ugly. */ -# ifdef GC_ADD_CALLER -# define RA GC_RETURN_ADDR, -# else -# define RA -# endif + # define GC_debug_malloc_replacement(lb) \ - GC_debug_malloc(lb, RA "unknown", 0) + GC_debug_malloc(lb, GC_DBG_RA "unknown", 0) void * malloc(size_t lb) { @@ -381,7 +319,7 @@ void * malloc(size_t lb) WARN("Failed to find ld.so text mapping: Expect crash\n", 0); } } -#endif +#endif /* GC_LINUX_THREADS */ void * calloc(size_t n, size_t lb) { @@ -408,7 +346,6 @@ void * calloc(size_t n, size_t lb) } #ifndef strdup -# include char *strdup(const char *s) { size_t lb = strlen(s) + 1; @@ -427,7 +364,6 @@ void * calloc(size_t n, size_t lb) #ifndef strndup /* This is similar to strdup(). */ -# include char *strndup(const char *str, size_t size) { char *copy; @@ -447,7 +383,7 @@ void * calloc(size_t n, size_t lb) #undef GC_debug_malloc_replacement -# endif /* REDIRECT_MALLOC */ +#endif /* REDIRECT_MALLOC */ /* Explicitly deallocate an object p. */ GC_API void GC_CALL GC_free(void * p) diff --git a/mallocx.c b/mallocx.c index 8d6939ba..82088c5b 100644 --- a/mallocx.c +++ b/mallocx.c @@ -24,6 +24,7 @@ */ #include +#include #ifdef MSWINCE # ifndef WIN32_LEAN_AND_MEAN @@ -152,13 +153,9 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) # ifdef REDIRECT_REALLOC /* As with malloc, avoid two levels of extra calls here. */ -# ifdef GC_ADD_CALLER -# define RA GC_RETURN_ADDR, -# else -# define RA -# endif + # define GC_debug_realloc_replacement(p, lb) \ - GC_debug_realloc(p, lb, RA "unknown", 0) + GC_debug_realloc(p, lb, GC_DBG_RA "unknown", 0) void * realloc(void * p, size_t lb) { @@ -598,3 +595,62 @@ GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb) } } #endif /* ATOMIC_UNCOLLECTABLE */ + +/* provide a version of strdup() that uses the collector to allocate the + copy of the string */ +GC_API char * GC_CALL GC_strdup(const char *s) +{ + char *copy; + size_t lb; + if (s == NULL) return NULL; + lb = strlen(s) + 1; + if ((copy = GC_malloc_atomic(lb)) == NULL) { +# ifndef MSWINCE + errno = ENOMEM; +# endif + return NULL; + } +# ifndef MSWINCE + strcpy(copy, s); +# else + /* strcpy() is deprecated in WinCE */ + memcpy(copy, s, lb); +# endif + return copy; +} + +GC_API char * GC_CALL GC_strndup(const char *str, size_t size) +{ + char *copy; + size_t len = strlen(str); /* str is expected to be non-NULL */ + if (len > size) + len = size; + copy = GC_malloc_atomic(len + 1); + if (copy == NULL) { +# ifndef MSWINCE + errno = ENOMEM; +# endif + return NULL; + } + BCOPY(str, copy, len); + copy[len] = '\0'; + return copy; +} + +#ifdef GC_REQUIRE_WCSDUP +# include /* for wcslen() */ + + GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *str) + { + size_t lb = (wcslen(str) + 1) * sizeof(wchar_t); + wchar_t *copy = GC_malloc_atomic(lb); + if (copy == NULL) { +# ifndef MSWINCE + errno = ENOMEM; +# endif + return NULL; + } + BCOPY(str, copy, lb); + return copy; + } +#endif /* GC_REQUIRE_WCSDUP */ -- cgit v1.2.1 From 705f35dade90d88affa06f618a924db2b2018000 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 9 Apr 2011 11:22:22 +0000 Subject: 2011-04-09 Ivan Maidanski * mallocx.c (GC_malloc_uncollectable): Move to malloc.c (since it is used internally in some places). --HG-- branch : bdwgc --- ChangeLog | 5 +++++ malloc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ mallocx.c | 51 --------------------------------------------------- 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 46cdbc55..a8cd985d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-09 Ivan Maidanski + + * mallocx.c (GC_malloc_uncollectable): Move to malloc.c (since + it is used internally in some places). + 2011-04-09 Ivan Maidanski * dbg_mlc.c (GC_register_finalizer_no_order): Remove redundant diff --git a/malloc.c b/malloc.c index 781d65ab..fceb9dc6 100644 --- a/malloc.c +++ b/malloc.c @@ -264,6 +264,57 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) } } +/* Allocate lb bytes of pointerful, traced, but not collectable data */ +GC_API void * GC_CALL GC_malloc_uncollectable(size_t lb) +{ + void *op; + void **opp; + size_t lg; + DCL_LOCK_STATE; + + if( SMALL_OBJ(lb) ) { + if (EXTRA_BYTES != 0 && lb != 0) lb--; + /* We don't need the extra byte, since this won't be */ + /* collected anyway. */ + lg = GC_size_map[lb]; + opp = &(GC_uobjfreelist[lg]); + LOCK(); + if( (op = *opp) != 0 ) { + *opp = obj_link(op); + obj_link(op) = 0; + GC_bytes_allocd += GRANULES_TO_BYTES(lg); + /* Mark bit ws already set on free list. It will be */ + /* cleared only temporarily during a collection, as a */ + /* result of the normal free list mark bit clearing. */ + GC_non_gc_bytes += GRANULES_TO_BYTES(lg); + UNLOCK(); + } else { + UNLOCK(); + op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE); + /* For small objects, the free lists are completely marked. */ + } + GC_ASSERT(0 == op || GC_is_marked(op)); + return((void *) op); + } else { + hdr * hhdr; + + op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE); + if (0 == op) return(0); + + GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */ + hhdr = HDR(op); + /* We don't need the lock here, since we have an undisguised */ + /* pointer. We do need to hold the lock while we adjust */ + /* mark bits. */ + LOCK(); + set_mark_bit_from_hdr(hhdr, 0); /* Only object. */ + GC_ASSERT(hhdr -> hb_n_marks == 0); + hhdr -> hb_n_marks = 1; + UNLOCK(); + return((void *) op); + } +} + #ifdef REDIRECT_MALLOC # ifndef MSWINCE diff --git a/mallocx.c b/mallocx.c index 82088c5b..d92014c9 100644 --- a/mallocx.c +++ b/mallocx.c @@ -438,57 +438,6 @@ GC_API void * GC_CALL GC_malloc_many(size_t lb) return result; } -/* Allocate lb bytes of pointerful, traced, but not collectable data */ -GC_API void * GC_CALL GC_malloc_uncollectable(size_t lb) -{ - void *op; - void **opp; - size_t lg; - DCL_LOCK_STATE; - - if( SMALL_OBJ(lb) ) { - if (EXTRA_BYTES != 0 && lb != 0) lb--; - /* We don't need the extra byte, since this won't be */ - /* collected anyway. */ - lg = GC_size_map[lb]; - opp = &(GC_uobjfreelist[lg]); - LOCK(); - if( (op = *opp) != 0 ) { - *opp = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - /* Mark bit ws already set on free list. It will be */ - /* cleared only temporarily during a collection, as a */ - /* result of the normal free list mark bit clearing. */ - GC_non_gc_bytes += GRANULES_TO_BYTES(lg); - UNLOCK(); - } else { - UNLOCK(); - op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE); - /* For small objects, the free lists are completely marked. */ - } - GC_ASSERT(0 == op || GC_is_marked(op)); - return((void *) op); - } else { - hdr * hhdr; - - op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE); - if (0 == op) return(0); - - GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */ - hhdr = HDR(op); - /* We don't need the lock here, since we have an undisguised */ - /* pointer. We do need to hold the lock while we adjust */ - /* mark bits. */ - LOCK(); - set_mark_bit_from_hdr(hhdr, 0); /* Only object. */ - GC_ASSERT(hhdr -> hb_n_marks == 0); - hhdr -> hb_n_marks = 1; - UNLOCK(); - return((void *) op); - } -} - /* Not well tested nor integrated. */ /* Debug version is tricky and currently missing. */ #include -- cgit v1.2.1 From 8232b165301ec111493cf791f15d18dc8bbbbe86 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 9 Apr 2011 11:47:02 +0000 Subject: 2011-04-09 Ivan Maidanski * os_dep.c (GC_unix_sbrk_get_mem, GC_unix_get_mem): Don't define for RTEMS. * include/private/gcconfig.h (RTEMS): Add support for. * include/private/gcconfig.h (GET_MEM): Use calloc() for RTEMS. --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ include/private/gcconfig.h | 23 ++++++++++++++++++----- os_dep.c | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8cd985d..ec8e719a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-04-09 Ivan Maidanski + + * os_dep.c (GC_unix_sbrk_get_mem, GC_unix_get_mem): Don't define + for RTEMS. + * include/private/gcconfig.h (RTEMS): Add support for. + * include/private/gcconfig.h (GET_MEM): Use calloc() for RTEMS. + 2011-04-09 Ivan Maidanski * mallocx.c (GC_malloc_uncollectable): Move to malloc.c (since diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 06c35d86..051391a3 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -338,6 +338,11 @@ # define DARWIN_DONT_PARSE_STACK # endif # endif +# if defined(__rtems__) && (defined(i386) || defined(__i386__)) +# define I386 +# define RTEMS +# define mach_type_known +# endif # if defined(NeXT) && defined(mc68000) # define M68K # define NEXT @@ -1373,6 +1378,13 @@ # define STACKBOTTOM ((ptr_t)0xc0000000) # define DATAEND /* not needed */ # endif +# ifdef RTEMS +# define OS_TYPE "RTEMS" + extern int etext[]; +# define DATASTART ((ptr_t)((((word) (etext)) + 0xfffff) & ~0xfffff)) +# define DATAENT ((ptr_t)(DATASTART + 0xfffff)) +# define STACKBOTTOM ((ptr_t) 0x03fff000) +# endif # ifdef DOS4GW # define OS_TYPE "DOS4GW" extern long __nullarea; @@ -2649,11 +2661,12 @@ # define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \ + GC_page_size) \ + GC_page_size-1) -# elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) || \ - (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \ - (defined(SOLARIS) && !defined(USE_MMAP)) -# define GET_MEM(bytes) HBLKPTR((size_t) calloc(1, (size_t)bytes + GC_page_size) \ - + GC_page_size-1) +# elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) \ + || (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) \ + || (defined(SOLARIS) && !defined(USE_MMAP)) || defined(RTEMS) +# define GET_MEM(bytes) HBLKPTR((size_t)calloc(1, \ + (size_t)bytes + GC_page_size) \ + + GC_page_size - 1) # elif defined(MSWIN32) || defined(CYGWIN32) ptr_t GC_win32_get_mem(GC_word bytes); # define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) diff --git a/os_dep.c b/os_dep.c index 3bb778c1..9fa42a5b 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2010,7 +2010,7 @@ void GC_register_data_segments(void) # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \ && !defined(MSWINCE) && !defined(MACOS) && !defined(DOS4GW) \ - && !defined(NONSTOP) && !defined(SN_TARGET_PS3) + && !defined(NONSTOP) && !defined(SN_TARGET_PS3) && !defined(RTEMS) # define SBRK_ARG_T ptrdiff_t -- cgit v1.2.1 From 82d8e7f968d5e83207d1a8d30720d894f059ae32 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 9 Apr 2011 13:42:09 +0000 Subject: 2011-04-09 Ivan Maidanski * reclaim.c (GC_print_all_errors): Recognize new GC_ABORT_ON_LEAK macro and environment variable; abort if any error has been printed provided the environment variable (or macro) is set. * doc/README.environment (GC_ABORT_ON_LEAK): Document. * doc/README.macros (GC_ABORT_ON_LEAK): Ditto. * doc/README.macros (FIND_LEAK, SUNOS5SIGS, PCR, USE_COMPILER_TLS): Reformat the text. --HG-- branch : bdwgc --- ChangeLog | 10 ++++++++++ doc/README.environment | 3 +++ doc/README.macros | 30 +++++++++++++++++------------- reclaim.c | 20 +++++++++++++++++++- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index ec8e719a..d54087d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-04-09 Ivan Maidanski + + * reclaim.c (GC_print_all_errors): Recognize new GC_ABORT_ON_LEAK + macro and environment variable; abort if any error has been + printed provided the environment variable (or macro) is set. + * doc/README.environment (GC_ABORT_ON_LEAK): Document. + * doc/README.macros (GC_ABORT_ON_LEAK): Ditto. + * doc/README.macros (FIND_LEAK, SUNOS5SIGS, PCR, + USE_COMPILER_TLS): Reformat the text. + 2011-04-09 Ivan Maidanski * os_dep.c (GC_unix_sbrk_get_mem, GC_unix_get_mem): Don't define diff --git a/doc/README.environment b/doc/README.environment index ef7c7cb5..ce12067c 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -158,6 +158,9 @@ GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. Forces a collection at program termination to detect leaks that would otherwise occur after the last GC. +GC_ABORT_ON_LEAK - Causes the application to be terminated once leaked or + smashed objects are found. + GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior pointer recognition. diff --git a/doc/README.macros b/doc/README.macros index 1b492000..c9951178 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -81,23 +81,27 @@ GC_REQUIRE_WCSDUP Force GC to export GC_wcsdup() (the Unicode version These define arguments influence the collector configuration: -FIND_LEAK causes GC_find_leak to be initially set. - This causes the collector to assume that all inaccessible - objects should have been explicitly deallocated, and reports exceptions. - Finalization and the test program are not usable in this mode. + +FIND_LEAK Causes GC_find_leak to be initially set. This causes the + collector to assume that all inaccessible objects should have been + explicitly deallocated, and reports exceptions. Finalization and the test + program are not usable in this mode. + +GC_ABORT_ON_LEAK Causes the application to be terminated once leaked or + smashed (corrupted on use-after-free) objects are found (after printing the + information about that objects). SUNOS5SIGS Solaris-like signal handling. This is probably misnamed, - since it really doesn't guarantee much more than Posix. - Currently set only for Solaris2.X, HPUX, and DRSNX. Should - probably be set for some other platforms. + since it really doesn't guarantee much more than POSIX. Currently set only + for Solaris2.X, HPUX, and DRSNX. Should probably be set for some other + platforms. -PCR Set if the collector is being built as part of the Xerox - Portable Common Runtime. +PCR Set if the collector is being built as part of the Xerox Portable + Common Runtime. -USE_COMPILER_TLS Assume the existence of __thread-style thread-local - storage. Set automatically for thread-local allocation with - the HP/UX vendor compiler. Usable with gcc on sufficiently - up-to-date ELF platforms. +USE_COMPILER_TLS Assume the existence of __thread-style thread-local storage. + Set automatically for thread-local allocation with the HP/UX vendor + compiler. Usable with gcc on sufficiently up-to-date ELF platforms. IMPORTANT: Any of the _THREADS options must normally also be defined in the client before including gc.h. This redefines thread primitives to diff --git a/reclaim.c b/reclaim.c index e17d374a..efade9b7 100644 --- a/reclaim.c +++ b/reclaim.c @@ -57,6 +57,7 @@ STATIC void GC_add_leaked(ptr_t leaked) GC_INNER void GC_print_all_errors(void) { static GC_bool printing_errors = FALSE; + GC_bool have_errors; unsigned i; DCL_LOCK_STATE; @@ -65,9 +66,16 @@ GC_INNER void GC_print_all_errors(void) UNLOCK(); return; } + have_errors = GC_have_errors; printing_errors = TRUE; UNLOCK(); - if (GC_debugging_started) GC_print_all_smashed(); + + if (GC_debugging_started) { + GC_print_all_smashed(); + } else { + have_errors = FALSE; + } + for (i = 0; i < GC_n_leaked; ++i) { ptr_t p = GC_leaked[i]; if (HDR(p) -> hb_obj_kind == PTRFREE) { @@ -79,8 +87,18 @@ GC_INNER void GC_print_all_errors(void) GC_err_printf("\n"); GC_free(p); GC_leaked[i] = 0; + have_errors = TRUE; } GC_n_leaked = 0; + + if (have_errors +# ifndef GC_ABORT_ON_LEAK + && GETENV("GC_ABORT_ON_LEAK") != NULL +# endif + ) { + ABORT("Leaked or smashed objects encountered"); + } + printing_errors = FALSE; } -- cgit v1.2.1 From 622433bdf85de2418f7c635ae60c057231b99e98 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 10 Apr 2011 09:13:47 +0000 Subject: 2011-04-10 Ivan Maidanski (mostly really Iain Sandoe) * tests/test.c (reverse_test): Modify count (BIG) for ppc64-darwin. --HG-- branch : bdwgc --- ChangeLog | 7 ++++++- tests/test.c | 28 ++++++++++++---------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index d54087d8..7a60eddd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-10 Ivan Maidanski (mostly really Iain Sandoe) + + * tests/test.c (reverse_test): Modify count (BIG) for + ppc64-darwin. + 2011-04-09 Ivan Maidanski * reclaim.c (GC_print_all_errors): Recognize new GC_ABORT_ON_LEAK @@ -8,7 +13,7 @@ * doc/README.macros (FIND_LEAK, SUNOS5SIGS, PCR, USE_COMPILER_TLS): Reformat the text. -2011-04-09 Ivan Maidanski +2011-04-09 Ivan Maidanski (really Jie Liu) * os_dep.c (GC_unix_sbrk_get_mem, GC_unix_get_mem): Don't define for RTEMS. diff --git a/tests/test.c b/tests/test.c index d6e2fc88..654332ee 100644 --- a/tests/test.c +++ b/tests/test.c @@ -536,23 +536,19 @@ void *GC_CALLBACK reverse_test_inner(void *data) # if /*defined(MSWIN32) ||*/ defined(MACOS) /* Win32S only allows 128K stacks */ # define BIG 1000 +# elif defined(PCR) + /* PCR default stack is 100K. Stack frames are up to 120 bytes. */ +# define BIG 700 +# elif defined(MSWINCE) + /* WinCE only allows 64K stacks */ +# define BIG 500 +# elif defined(OSF1) + /* OSF has limited stack space by default, and large frames. */ +# define BIG 200 +# elif defined(__MACH__) && defined(__ppc64__) +# define BIG 2500 # else -# if defined(PCR) - /* PCR default stack is 100K. Stack frames are up to 120 bytes. */ -# define BIG 700 -# else -# if defined(MSWINCE) - /* WinCE only allows 64K stacks */ -# define BIG 500 -# else -# if defined(OSF1) - /* OSF has limited stack space by default, and large frames. */ -# define BIG 200 -# else -# define BIG 4500 -# endif -# endif -# endif +# define BIG 4500 # endif A.dummy = 17; -- cgit v1.2.1 From 8e749bdb70db3e6bf31fa750011131765e78afed Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 10 Apr 2011 09:46:46 +0000 Subject: 2011-04-10 Ivan Maidanski * gcj_mlc.c (GC_gcj_malloc_initialized): Use STATIC unless GC_ASSERTIONS. * include/private/gc_priv.h (GC_gcj_malloc_initialized): Don't declare (as external) unless GC_ASSERTIONS. * os_dep.c (GC_win32_free_heap): Clear GC_heap_bases[] also for Cygwin; add FIXME. * include/private/gcconfig.h: Include for RTEMS. * include/private/gcconfig.h: Add "#error" for every "-->" mark. * include/private/gcconfig.h (CLEAR_DOUBLE): Turn the code into an expression. * include/private/pthread_support.h (SUSPENDED_EXT): Add new flag (which existed previously as SUSPENDED and still exists in GCJ). * include/private/pthread_support.h (DISABLED_GC): Change the value (as it is already used by SUSPENDED_EXT). --HG-- branch : bdwgc --- ChangeLog | 17 ++ gcj_mlc.c | 7 +- include/private/gc_priv.h | 4 +- include/private/gcconfig.h | 577 +++++++++++++++++++------------------- include/private/pthread_support.h | 7 +- os_dep.c | 17 +- 6 files changed, 330 insertions(+), 299 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7a60eddd..f42aff4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-04-10 Ivan Maidanski + + * gcj_mlc.c (GC_gcj_malloc_initialized): Use STATIC unless + GC_ASSERTIONS. + * include/private/gc_priv.h (GC_gcj_malloc_initialized): Don't + declare (as external) unless GC_ASSERTIONS. + * os_dep.c (GC_win32_free_heap): Clear GC_heap_bases[] also for + Cygwin; add FIXME. + * include/private/gcconfig.h: Include for RTEMS. + * include/private/gcconfig.h: Add "#error" for every "-->" mark. + * include/private/gcconfig.h (CLEAR_DOUBLE): Turn the code into + an expression. + * include/private/pthread_support.h (SUSPENDED_EXT): Add new flag + (which existed previously as SUSPENDED and still exists in GCJ). + * include/private/pthread_support.h (DISABLED_GC): Change the + value (as it is already used by SUSPENDED_EXT). + 2011-04-10 Ivan Maidanski (mostly really Iain Sandoe) * tests/test.c (reverse_test): Modify count (BIG) for diff --git a/gcj_mlc.c b/gcj_mlc.c index 7afa6bf2..a3d9358f 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -39,7 +39,12 @@ #include "gc_gcj.h" #include "private/dbg_mlc.h" -GC_INNER GC_bool GC_gcj_malloc_initialized = FALSE; +#ifdef GC_ASSERTIONS + GC_INNER /* variable is also used in thread_local_alloc.c */ +#else + STATIC +#endif +GC_bool GC_gcj_malloc_initialized = FALSE; int GC_gcj_kind = 0; /* Object kind for objects with descriptors */ /* in "vtable". */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 7f3f5081..cb0bfb4a 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -2007,7 +2007,9 @@ GC_EXTERN signed_word GC_bytes_found; #endif #ifdef GC_GCJ_SUPPORT - GC_EXTERN GC_bool GC_gcj_malloc_initialized; /* defined in gcj_mlc.c */ +# ifdef GC_ASSERTIONS + GC_EXTERN GC_bool GC_gcj_malloc_initialized; /* defined in gcj_mlc.c */ +# endif GC_EXTERN ptr_t * GC_gcjobjfreelist; #endif diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 051391a3..ec5e96ed 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -1380,6 +1380,7 @@ # endif # ifdef RTEMS # define OS_TYPE "RTEMS" +# include extern int etext[]; # define DATASTART ((ptr_t)((((word) (etext)) + 0xfffff) & ~0xfffff)) # define DATAENT ((ptr_t)(DATASTART + 0xfffff)) @@ -1741,7 +1742,7 @@ # define ALIGNMENT 4 # else # ifndef _LP64 - ---> unknown ABI +# error --> unknown ABI # endif # define CPP_WORDSZ 64 /* Requires 16 byte alignment for malloc */ @@ -2282,358 +2283,356 @@ # define USE_PROC_FOR_LIBRARIES #endif -# ifndef STACK_GROWS_UP -# define STACK_GROWS_DOWN -# endif +#ifndef STACK_GROWS_UP +# define STACK_GROWS_DOWN +#endif -# ifndef CPP_WORDSZ -# define CPP_WORDSZ 32 -# endif +#ifndef CPP_WORDSZ +# define CPP_WORDSZ 32 +#endif -# ifndef OS_TYPE -# define OS_TYPE "" -# endif +#ifndef OS_TYPE +# define OS_TYPE "" +#endif -# ifndef DATAEND - extern int end[]; -# define DATAEND (ptr_t)(end) -# endif +#ifndef DATAEND + extern int end[]; +# define DATAEND (ptr_t)(end) +#endif -# if defined(SVR4) && !defined(GETPAGESIZE) -# include -# define GETPAGESIZE() sysconf(_SC_PAGESIZE) -# endif +#if defined(SVR4) && !defined(GETPAGESIZE) +# include +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +#endif -# ifndef GETPAGESIZE -# if defined(SOLARIS) || defined(IRIX5) || defined(LINUX) \ - || defined(NETBSD) || defined(FREEBSD) || defined(HPUX) -# include -# endif -# define GETPAGESIZE() getpagesize() +#ifndef GETPAGESIZE +# if defined(SOLARIS) || defined(IRIX5) || defined(LINUX) \ + || defined(NETBSD) || defined(FREEBSD) || defined(HPUX) +# include # endif +# define GETPAGESIZE() getpagesize() +#endif -# if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) - /* OS has SVR4 generic features. */ - /* Probably others also qualify. */ -# define SVR4 -# endif +#if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) + /* OS has SVR4 generic features. */ + /* Probably others also qualify. */ +# define SVR4 +#endif -# if defined(SOLARIS) || defined(DRSNX) - /* OS has SOLARIS style semi-undocumented interface */ - /* to dynamic loader. */ -# define SOLARISDL - /* OS has SOLARIS style signal handlers. */ -# define SUNOS5SIGS -# endif +#if defined(SOLARIS) || defined(DRSNX) + /* OS has SOLARIS style semi-undocumented interface */ + /* to dynamic loader. */ +# define SOLARISDL + /* OS has SOLARIS style signal handlers. */ +# define SUNOS5SIGS +#endif -# if defined(HPUX) -# define SUNOS5SIGS -# endif +#if defined(HPUX) +# define SUNOS5SIGS +#endif -# if defined(FREEBSD) && \ - (defined(__DragonFly__) || __FreeBSD__ >= 4 || (__FreeBSD_kernel__ >= 4)) -# define SUNOS5SIGS -# endif +#if defined(FREEBSD) && (defined(__DragonFly__) || __FreeBSD__ >= 4 \ + || (__FreeBSD_kernel__ >= 4)) +# define SUNOS5SIGS +#endif -# ifdef GC_NETBSD_THREADS -# define SIGRTMIN 33 -# define SIGRTMAX 63 -# endif +#ifdef GC_NETBSD_THREADS +# define SIGRTMIN 33 +# define SIGRTMAX 63 +#endif -# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \ - || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ - || defined(DGUX) || defined(BSD) || defined(HURD) \ - || defined(AIX) || defined(DARWIN) || defined(OSF1) -# define UNIX_LIKE /* Basic Unix-like system calls work. */ -# endif +#if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \ + || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ + || defined(DGUX) || defined(BSD) || defined(HURD) \ + || defined(AIX) || defined(DARWIN) || defined(OSF1) +# define UNIX_LIKE /* Basic Unix-like system calls work. */ +#endif -# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 - -> bad word size -# endif +#if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 +# error --> bad word size +#endif -# ifndef ALIGNMENT - --> undefined ALIGNMENT -# endif +#ifndef ALIGNMENT +# error --> undefined ALIGNMENT +#endif -# ifdef PCR -# undef DYNAMIC_LOADING -# undef STACKBOTTOM -# undef HEURISTIC1 -# undef HEURISTIC2 -# undef PROC_VDB -# undef MPROTECT_VDB -# define PCR_VDB -# endif +#ifdef PCR +# undef DYNAMIC_LOADING +# undef STACKBOTTOM +# undef HEURISTIC1 +# undef HEURISTIC2 +# undef PROC_VDB +# undef MPROTECT_VDB +# define PCR_VDB +#endif -# if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) -# error --> undefined STACKBOTTOM -# endif +#if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) +# error --> undefined STACKBOTTOM +#endif -# ifdef IGNORE_DYNAMIC_LOADING -# undef DYNAMIC_LOADING -# endif +#ifdef IGNORE_DYNAMIC_LOADING +# undef DYNAMIC_LOADING +#endif -# if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL) - /* Presumably not worth the space it takes. */ -# define GC_DISABLE_INCREMENTAL -# endif +#if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL) + /* Presumably not worth the space it takes. */ +# define GC_DISABLE_INCREMENTAL +#endif -# ifdef GC_DISABLE_INCREMENTAL -# undef GWW_VDB -# undef MPROTECT_VDB -# undef PCR_VDB -# undef PROC_VDB -# undef CHECKSUMS -# endif +#ifdef GC_DISABLE_INCREMENTAL +# undef GWW_VDB +# undef MPROTECT_VDB +# undef PCR_VDB +# undef PROC_VDB +# undef CHECKSUMS +#endif -# ifdef USE_GLOBAL_ALLOC - /* Cannot pass MEM_WRITE_WATCH to GlobalAlloc(). */ -# undef GWW_VDB -# endif +#ifdef USE_GLOBAL_ALLOC + /* Cannot pass MEM_WRITE_WATCH to GlobalAlloc(). */ +# undef GWW_VDB +#endif -# ifdef USE_MUNMAP - /* FIXME: Remove this undef if possible. */ -# undef MPROTECT_VDB /* Can't deal with address space holes. */ -# endif +#ifdef USE_MUNMAP + /* FIXME: Remove this undef if possible. */ +# undef MPROTECT_VDB /* Can't deal with address space holes. */ +#endif /* PARALLEL_MARK does not cause undef MPROTECT_VDB any longer. */ -# if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB) - /* Choose MPROTECT_VDB manually (if multiple strategies available). */ -# undef PCR_VDB -# undef PROC_VDB - /* #undef GWW_VDB - handled in os_dep.c */ -# endif +#if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB) + /* Choose MPROTECT_VDB manually (if multiple strategies available). */ +# undef PCR_VDB +# undef PROC_VDB + /* #undef GWW_VDB - handled in os_dep.c */ +#endif -# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ +#if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ && !defined(GWW_VDB) && !defined(GC_DISABLE_INCREMENTAL) -# define DEFAULT_VDB -# endif +# define DEFAULT_VDB +#endif -# ifndef PREFETCH -# define PREFETCH(x) -# define NO_PREFETCH -# endif +#ifndef PREFETCH +# define PREFETCH(x) +# define NO_PREFETCH +#endif -# ifndef PREFETCH_FOR_WRITE -# define PREFETCH_FOR_WRITE(x) -# define NO_PREFETCH_FOR_WRITE -# endif +#ifndef PREFETCH_FOR_WRITE +# define PREFETCH_FOR_WRITE(x) +# define NO_PREFETCH_FOR_WRITE +#endif -# ifndef CACHE_LINE_SIZE -# define CACHE_LINE_SIZE 32 /* Wild guess */ -# endif +#ifndef CACHE_LINE_SIZE +# define CACHE_LINE_SIZE 32 /* Wild guess */ +#endif -# ifndef STATIC -# ifndef NO_DEBUGGING -# define STATIC /* ignore to aid profiling and possibly debugging */ -# else -# define STATIC static -# endif +#ifndef STATIC +# ifndef NO_DEBUGGING +# define STATIC /* ignore to aid profiling and possibly debugging */ +# else +# define STATIC static # endif +#endif -# if defined(LINUX) || defined(HURD) || defined(__GLIBC__) -# define REGISTER_LIBRARIES_EARLY - /* We sometimes use dl_iterate_phdr, which may acquire an internal */ - /* lock. This isn't safe after the world has stopped. So we must */ - /* call GC_register_dynamic_libraries before stopping the world. */ - /* For performance reasons, this may be beneficial on other */ - /* platforms as well, though it should be avoided in win32. */ -# endif /* LINUX */ +#if defined(LINUX) || defined(HURD) || defined(__GLIBC__) +# define REGISTER_LIBRARIES_EARLY + /* We sometimes use dl_iterate_phdr, which may acquire an internal */ + /* lock. This isn't safe after the world has stopped. So we must */ + /* call GC_register_dynamic_libraries before stopping the world. */ + /* For performance reasons, this may be beneficial on other */ + /* platforms as well, though it should be avoided in win32. */ +#endif /* LINUX */ + +#if defined(SEARCH_FOR_DATA_START) + extern ptr_t GC_data_start; +# define DATASTART GC_data_start +#endif -# if defined(SEARCH_FOR_DATA_START) - extern ptr_t GC_data_start; -# define DATASTART GC_data_start -# endif +#ifndef CLEAR_DOUBLE +# define CLEAR_DOUBLE(x) (((word*)(x))[0] = 0, ((word*)(x))[1] = 0) +#endif -# ifndef CLEAR_DOUBLE -# define CLEAR_DOUBLE(x) \ - ((word*)x)[0] = 0; \ - ((word*)x)[1] = 0; -# endif /* CLEAR_DOUBLE */ +#if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \ + && !defined(INCLUDE_LINUX_THREAD_DESCR) + /* Will not work, since libc and the dynamic loader use thread */ + /* locals, sometimes as the only reference. */ +# define INCLUDE_LINUX_THREAD_DESCR +#endif -# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \ - && !defined(INCLUDE_LINUX_THREAD_DESCR) - /* Will not work, since libc and the dynamic loader use thread */ - /* locals, sometimes as the only reference. */ -# define INCLUDE_LINUX_THREAD_DESCR -# endif +#if defined(GC_IRIX_THREADS) && !defined(IRIX5) +# error --> inconsistent configuration +#endif +#if defined(GC_LINUX_THREADS) && !defined(LINUX) && !defined(NACL) +# error --> inconsistent configuration +#endif +#if defined(GC_NETBSD_THREADS) && !defined(NETBSD) +# error --> inconsistent configuration +#endif +#if defined(GC_FREEBSD_THREADS) && !defined(FREEBSD) +# error --> inconsistent configuration +#endif +#if defined(GC_SOLARIS_THREADS) && !defined(SOLARIS) +# error --> inconsistent configuration +#endif +#if defined(GC_HPUX_THREADS) && !defined(HPUX) +# error --> inconsistent configuration +#endif +#if defined(GC_AIX_THREADS) && !defined(_AIX) +# error --> inconsistent configuration +#endif +#if defined(GC_GNU_THREADS) && !defined(HURD) +# error --> inconsistent configuration +#endif +#if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32) \ + && !defined(MSWINCE) +# error --> inconsistent configuration +#endif -# if defined(GC_IRIX_THREADS) && !defined(IRIX5) - --> inconsistent configuration -# endif -# if defined(GC_LINUX_THREADS) && !defined(LINUX) && !defined(NACL) - --> inconsistent configuration -# endif -# if defined(GC_NETBSD_THREADS) && !defined(NETBSD) - --> inconsistent configuration -# endif -# if defined(GC_FREEBSD_THREADS) && !defined(FREEBSD) - --> inconsistent configuration -# endif -# if defined(GC_SOLARIS_THREADS) && !defined(SOLARIS) - --> inconsistent configuration -# endif -# if defined(GC_HPUX_THREADS) && !defined(HPUX) - --> inconsistent configuration -# endif -# if defined(GC_AIX_THREADS) && !defined(_AIX) - --> inconsistent configuration -# endif -# if defined(GC_GNU_THREADS) && !defined(HURD) - --> inconsistent configuration -# endif -# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32) \ - && !defined(MSWINCE) - --> inconsistent configuration -# endif +#if defined(PCR) || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS) \ + || defined(SN_TARGET_PS3) +# define THREADS +#endif -# if defined(PCR) || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS) \ - || defined(SN_TARGET_PS3) -# define THREADS -# endif +#if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \ + && !defined(PLATFORM_ANDROID) + /* Make the code cancellation-safe. This basically means that we */ + /* ensure that cancellation requests are ignored while we are in */ + /* the collector. This applies only to Posix deferred cancellation; */ + /* we don't handle Posix asynchronous cancellation. */ + /* Note that this only works if pthread_setcancelstate is */ + /* async-signal-safe, at least in the absence of asynchronous */ + /* cancellation. This appears to be true for the glibc version, */ + /* though it is not documented. Without that assumption, there */ + /* seems to be no way to safely wait in a signal handler, which */ + /* we need to do for thread suspension. */ + /* Also note that little other code appears to be cancellation-safe. */ + /* Hence it may make sense to turn this off for performance. */ +# define CANCEL_SAFE +#endif -# if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \ - && !defined(PLATFORM_ANDROID) - /* Make the code cancellation-safe. This basically means that we */ - /* ensure that cancellation requests are ignored while we are in */ - /* the collector. This applies only to Posix deferred cancellation;*/ - /* we don't handle Posix asynchronous cancellation. */ - /* Note that this only works if pthread_setcancelstate is */ - /* async-signal-safe, at least in the absence of asynchronous */ - /* cancellation. This appears to be true for the glibc version, */ - /* though it is not documented. Without that assumption, there */ - /* seems to be no way to safely wait in a signal handler, which */ - /* we need to do for thread suspension. */ - /* Also note that little other code appears to be cancellation-safe.*/ - /* Hence it may make sense to turn this off for performance. */ -# define CANCEL_SAFE -# endif +#ifdef CANCEL_SAFE +# define IF_CANCEL(x) x +#else +# define IF_CANCEL(x) /* empty */ +#endif -# ifdef CANCEL_SAFE -# define IF_CANCEL(x) x +#if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) +# if defined(THREADS) && defined(PARALLEL_MARK) +# define USE_MARK_BYTES # else -# define IF_CANCEL(x) -# endif - -# if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) -# if defined(THREADS) && defined(PARALLEL_MARK) -# define USE_MARK_BYTES -# else -# define USE_MARK_BITS -# endif -# endif - -# if defined(MSWINCE) && !defined(__CEGCC__) && !defined(NO_GETENV) -# define NO_GETENV +# define USE_MARK_BITS # endif +#endif -# if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32) -# define NO_GETENV_WIN32 -# endif +#if defined(MSWINCE) && !defined(__CEGCC__) && !defined(NO_GETENV) +# define NO_GETENV +#endif -# ifndef STRTOULL -# if defined(_WIN64) && !defined(__GNUC__) -# define STRTOULL _strtoui64 -# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64) -# define STRTOULL strtoull -# else - /* strtoul() fits since sizeof(long) >= sizeof(word). */ -# define STRTOULL strtoul -# endif -# endif +#if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32) +# define NO_GETENV_WIN32 +#endif -# if defined(SPARC) -# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ - /* include assembly code to do it well. */ +#ifndef STRTOULL +# if defined(_WIN64) && !defined(__GNUC__) +# define STRTOULL _strtoui64 +# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64) +# define STRTOULL strtoull +# else + /* strtoul() fits since sizeof(long) >= sizeof(word). */ +# define STRTOULL strtoul # endif +#endif - /* Can we save call chain in objects for debugging? */ - /* SET NFRAMES (# of saved frames) and NARGS (#of args for each */ - /* frame) to reasonable values for the platform. */ - /* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */ - /* at build time, though we feel free to adjust it slightly. */ - /* Define NEED_CALLINFO if we either save the call stack or */ - /* GC_ADD_CALLER is defined. */ - /* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */ +#if defined(SPARC) +# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ + /* include assembly code to do it well. */ +#endif +/* Can we save call chain in objects for debugging? */ +/* SET NFRAMES (# of saved frames) and NARGS (#of args for each */ +/* frame) to reasonable values for the platform. */ +/* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */ +/* at build time, though we feel free to adjust it slightly. */ +/* Define NEED_CALLINFO if we either save the call stack or */ +/* GC_ADD_CALLER is defined. */ +/* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */ #if defined(SPARC) # define CAN_SAVE_CALL_ARGS #endif -#if (defined(I386) || defined(X86_64)) && (defined(LINUX) || defined(__GLIBC__)) - /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ - /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ +#if (defined(I386) || defined(X86_64)) \ + && (defined(LINUX) || defined(__GLIBC__)) + /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ + /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ # define CAN_SAVE_CALL_ARGS #endif -# if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \ - && defined(GC_CAN_SAVE_CALL_STACKS) -# define SAVE_CALL_CHAIN -# endif -# ifdef SAVE_CALL_CHAIN -# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS) -# define NARGS SAVE_CALL_NARGS -# else -# define NARGS 0 /* Number of arguments to save for each call. */ -# endif -# endif -# ifdef SAVE_CALL_CHAIN -# ifndef SAVE_CALL_COUNT -# define NFRAMES 6 /* Number of frames to save. Even for */ - /* alignment reasons. */ -# else -# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) -# endif -# define NEED_CALLINFO -# endif /* SAVE_CALL_CHAIN */ -# ifdef GC_ADD_CALLER -# define NFRAMES 1 -# define NARGS 0 -# define NEED_CALLINFO +#if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \ + && defined(GC_CAN_SAVE_CALL_STACKS) +# define SAVE_CALL_CHAIN +#endif +#ifdef SAVE_CALL_CHAIN +# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS) +# define NARGS SAVE_CALL_NARGS +# else +# define NARGS 0 /* Number of arguments to save for each call. */ # endif +#endif +#ifdef SAVE_CALL_CHAIN +# ifndef SAVE_CALL_COUNT +# define NFRAMES 6 /* Number of frames to save. Even for */ + /* alignment reasons. */ +# else +# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) +# endif +# define NEED_CALLINFO +#endif /* SAVE_CALL_CHAIN */ +#ifdef GC_ADD_CALLER +# define NFRAMES 1 +# define NARGS 0 +# define NEED_CALLINFO +#endif -# if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL) -# define DBG_HDRS_ALL -# endif +#if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL) +# define DBG_HDRS_ALL +#endif -# if defined(POINTER_MASK) && !defined(POINTER_SHIFT) -# define POINTER_SHIFT 0 -# endif +#if defined(POINTER_MASK) && !defined(POINTER_SHIFT) +# define POINTER_SHIFT 0 +#endif -# if defined(POINTER_SHIFT) && !defined(POINTER_MASK) -# define POINTER_MASK ((GC_word)(-1)) -# endif +#if defined(POINTER_SHIFT) && !defined(POINTER_MASK) +# define POINTER_MASK ((GC_word)(-1)) +#endif -# if !defined(FIXUP_POINTER) && defined(POINTER_MASK) -# define FIXUP_POINTER(p) (p = ((p) & POINTER_MASK) << POINTER_SHIFT) -# endif +#if !defined(FIXUP_POINTER) && defined(POINTER_MASK) +# define FIXUP_POINTER(p) (p = ((p) & POINTER_MASK) << POINTER_SHIFT) +#endif -# if defined(FIXUP_POINTER) -# define NEED_FIXUP_POINTER 1 -# else -# define NEED_FIXUP_POINTER 0 -# define FIXUP_POINTER(p) -# endif +#if defined(FIXUP_POINTER) +# define NEED_FIXUP_POINTER 1 +#else +# define NEED_FIXUP_POINTER 0 +# define FIXUP_POINTER(p) +#endif -# if !defined(MARK_BIT_PER_GRANULE) && !defined(MARK_BIT_PER_OBJ) -# define MARK_BIT_PER_GRANULE /* Usually faster */ -# endif +#if !defined(MARK_BIT_PER_GRANULE) && !defined(MARK_BIT_PER_OBJ) +# define MARK_BIT_PER_GRANULE /* Usually faster */ +#endif /* Some static sanity tests. */ -# if defined(MARK_BIT_PER_GRANULE) && defined(MARK_BIT_PER_OBJ) -# error Define only one of MARK_BIT_PER_GRANULE and MARK_BIT_PER_OBJ. -# endif +#if defined(MARK_BIT_PER_GRANULE) && defined(MARK_BIT_PER_OBJ) +# error Define only one of MARK_BIT_PER_GRANULE and MARK_BIT_PER_OBJ. +#endif -# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) -# error "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd." -# endif -# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN) -# error "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd." -# endif +#if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) +# error "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd." +#endif +#if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN) +# error "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd." +#endif -# if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) -# error "REDIRECT_MALLOC with THREADS works at most on Linux." -# endif +#if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) +# error "REDIRECT_MALLOC with THREADS works at most on Linux." +#endif #ifdef GC_PRIVATE_H /* This relies on some type definitions from gc_priv.h, from */ diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index 73fa8fee..2b16bd56 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -53,7 +53,7 @@ typedef struct GC_Thread_Rep { struct thread_stop_info stop_info; unsigned char flags; -# define FINISHED 1 /* Thread has exited. */ +# define FINISHED 1 /* Thread has exited. */ # define DETACHED 2 /* Thread is treated as detached. */ /* Thread may really be detached, or */ /* it may have have been explicitly */ @@ -62,7 +62,10 @@ typedef struct GC_Thread_Rep { /* it unregisters itself, since it */ /* may not return a GC pointer. */ # define MAIN_THREAD 4 /* True for the original thread only. */ -# define DISABLED_GC 8 /* Collections are disabled while the */ +# define SUSPENDED_EXT 8 /* Thread was suspended externally */ + /* (this is not used by the unmodified */ + /* GC itself at present). */ +# define DISABLED_GC 0x10 /* Collections are disabled while the */ /* thread is exiting. */ unsigned char thread_blocked; diff --git a/os_dep.c b/os_dep.c index 9fa42a5b..eed14b8f 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2257,13 +2257,18 @@ void * os2_alloc(size_t bytes) GC_API void GC_CALL GC_win32_free_heap(void) { # ifndef CYGWIN32 - if (GC_no_win32_dlls) { - while (GC_n_heap_bases > 0) { - GlobalFree (GC_heap_bases[--GC_n_heap_bases]); - GC_heap_bases[GC_n_heap_bases] = 0; - } - } + if (GC_no_win32_dlls) # endif + { + while (GC_n_heap_bases-- > 0) { +# ifdef CYGWIN32 + /* FIXME: Is it ok to use non-GC free() here? */ +# else + GlobalFree(GC_heap_bases[GC_n_heap_bases]); +# endif + GC_heap_bases[GC_n_heap_bases] = 0; + } + } } #endif /* MSWIN32 || CYGWIN32 */ -- cgit v1.2.1 From b8de92368830bbdf4c733adb7d2c03243b7f3b67 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 10 Apr 2011 11:48:09 +0000 Subject: 2011-04-10 Ivan Maidanski (really Iain Sandoe, Mike Stump) * dyn_load.c (GC_dyld_sections): Add more sctions. * dyn_load.c (GC_dyld_add_sect_fmts): New static varaible. * dyn_load.c (L2_MAX_OFILE_ALIGNMENT): New macro. * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Improve logging; add support for on-demand sections. * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Reformat the code. --HG-- branch : bdwgc --- ChangeLog | 10 ++++ dyn_load.c | 185 ++++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 145 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index f42aff4d..f2d1ded9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-04-10 Ivan Maidanski (really Iain Sandoe, Mike Stump) + + * dyn_load.c (GC_dyld_sections): Add more sctions. + * dyn_load.c (GC_dyld_add_sect_fmts): New static varaible. + * dyn_load.c (L2_MAX_OFILE_ALIGNMENT): New macro. + * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Improve + logging; add support for on-demand sections. + * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Reformat + the code. + 2011-04-10 Ivan Maidanski * gcj_mlc.c (GC_gcj_malloc_initialized): Use STATIC unless diff --git a/dyn_load.c b/dyn_load.c index f504a956..50ab3ca2 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -1210,15 +1210,44 @@ GC_INNER void GC_register_dynamic_libraries(void) /*#define DARWIN_DEBUG*/ +/* Writable sections generally available on Darwin. */ STATIC const struct { - const char *seg; - const char *sect; + const char *seg; + const char *sect; } GC_dyld_sections[] = { - { SEG_DATA, SECT_DATA }, - { SEG_DATA, SECT_BSS }, - { SEG_DATA, SECT_COMMON } + { SEG_DATA, SECT_DATA }, + /* Used by FSF GCC, but not by OS X system tools, so far. */ + { SEG_DATA, "__static_data" }, + { SEG_DATA, SECT_BSS }, + { SEG_DATA, SECT_COMMON }, + /* FSF GCC - zero-sized object sections for targets */ + /*supporting section anchors. */ + { SEG_DATA, "__zobj_data" }, + { SEG_DATA, "__zobj_bss" } }; +/* Additional writable sections: */ +/* GCC on Darwin constructs aligned sections "on demand", where */ +/* the alignment size is embedded in the section name. */ +/* Furthermore, there are distinctions between sections */ +/* containing private vs. public symbols. It also constructs */ +/* sections specifically for zero-sized objects, when the */ +/* target supports section anchors. */ +STATIC const char * GC_dyld_add_sect_fmts[] = +{ + "__bss%u", + "__pu_bss%u", + "__zo_bss%u", + "__zo_pu_bss%u", + NULL +}; + +/* Currently, mach-o will allow up to the max of 2^15 alignment */ +/* in an object file. */ +#ifndef L2_MAX_OFILE_ALIGNMENT +# define L2_MAX_OFILE_ALIGNMENT 15 +#endif + STATIC const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) { unsigned long i, c; @@ -1229,63 +1258,119 @@ STATIC const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) return NULL; } -/* This should never be called by a thread holding the lock */ -STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide) +/* This should never be called by a thread holding the lock. */ +STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, + intptr_t slide) { - unsigned long start,end,i; - const struct GC_MACH_SECTION *sec; - const char *name; - GC_has_static_roots_func callback = GC_has_static_roots; - DCL_LOCK_STATE; - if (GC_no_dls) return; -# ifdef DARWIN_DEBUG - name = GC_dyld_name_for_hdr(hdr); -# else - name = callback != 0 ? GC_dyld_name_for_hdr(hdr) : NULL; -# endif - for(i=0;isize < sizeof(word)) continue; + unsigned long start, end; + int i, j; + const struct GC_MACH_SECTION *sec; + const char *name; + GC_has_static_roots_func callback = GC_has_static_roots; + char secnam[16]; + const char *fmt; + DCL_LOCK_STATE; + + if (GC_no_dls) return; +# ifdef DARWIN_DEBUG + name = GC_dyld_name_for_hdr(hdr); +# else + name = callback != 0 ? GC_dyld_name_for_hdr(hdr) : NULL; +# endif + for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) { + sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg, + GC_dyld_sections[i].sect); + if (sec == NULL || sec->size < sizeof(word)) + continue; + start = slide + sec->addr; + end = start + sec->size; + LOCK(); + /* The user callback is called holding the lock. */ + if (callback == 0 || callback(name, (void*)start, (size_t)sec->size)) { +# ifdef DARWIN_DEBUG + GC_log_printf( + "Adding section __DATA,%s at %p-%p (%lu bytes) from image %s\n", + GC_dyld_sections[i].sect, (void*)start, (void*)end, + (unsigned long)sec->size, name); +# endif + GC_add_roots_inner((ptr_t)start, (ptr_t)end, FALSE); + } + UNLOCK(); + } + + /* Sections constructed on demand. */ + for (j = 0; (fmt = GC_dyld_add_sect_fmts[j]) != NULL; j++) { + /* Add our manufactured aligned BSS sections. */ + for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { + snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); + sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); + if (sec == NULL || sec->size == 0) + continue; start = slide + sec->addr; end = start + sec->size; - LOCK(); - /* The user callback is called holding the lock */ - if (callback == 0 || callback(name, (void*)start, (size_t)sec->size)) { -# ifdef DARWIN_DEBUG - GC_log_printf("Adding section at %p-%p (%lu bytes) from image %s\n", - start, end, sec->size, name); -# endif - GC_add_roots_inner((ptr_t)start, (ptr_t)end, FALSE); - } - UNLOCK(); +# ifdef DARWIN_DEBUG + GC_log_printf("Adding on-demand section __DATA,%s at" + " %p-%p (%lu bytes) from image %s\n", + secnam, (void*)start, (void*)end, + (unsigned long)sec->size, name); +# endif + GC_add_roots((char*)start, (char*)end); } -# ifdef DARWIN_DEBUG - GC_print_static_roots(); -# endif + } + +# ifdef DARWIN_DEBUG + GC_print_static_roots(); +# endif } -/* This should never be called by a thread holding the lock */ +/* This should never be called by a thread holding the lock. */ STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, intptr_t slide) { - unsigned long start,end,i; - const struct GC_MACH_SECTION *sec; - for(i=0;isize == 0) continue; - start = slide + sec->addr; - end = start + sec->size; + unsigned long start, end; + int i, j; + const struct GC_MACH_SECTION *sec; + char secnam[16]; + const char *fmt; + + for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) { + sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg, + GC_dyld_sections[i].sect); + if (sec == NULL || sec->size == 0) + continue; + start = slide + sec->addr; + end = start + sec->size; # ifdef DARWIN_DEBUG - GC_log_printf("Removing section at %p-%p (%lu bytes) from image %s\n", - start, end, sec->size, GC_dyld_name_for_hdr(hdr)); + GC_log_printf( + "Removing section __DATA,%s at %p-%p (%lu bytes) from image %s\n", + GC_dyld_sections[i].sect, (void*)start, (void*)end, + (unsigned long)sec->size, GC_dyld_name_for_hdr(hdr)); # endif - GC_remove_roots((char*)start,(char*)end); + GC_remove_roots((char*)start, (char*)end); + } + + /* Remove our on-demand sections. */ + for (j = 0; (fmt = GC_dyld_add_sect_fmts[j]) != NULL; j++) { + for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { + snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); + sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); + if (sec == NULL || sec->size == 0) + continue; + start = slide + sec->addr; + end = start + sec->size; +# ifdef DARWIN_DEBUG + GC_log_printf("Removing on-demand section __DATA,%s at" + " %p-%p (%lu bytes) from image %s\n", secnam, + (void*)start, (void*)end, (unsigned long)sec->size, + GC_dyld_name_for_hdr(hdr)); +# endif + GC_remove_roots((char*)start, (char*)end); } -# ifdef DARWIN_DEBUG - GC_print_static_roots(); -# endif + } + +# ifdef DARWIN_DEBUG + GC_print_static_roots(); +# endif } GC_INNER void GC_register_dynamic_libraries(void) -- cgit v1.2.1 From 4669783378a4bbf3629fadded87a1d885245dc8b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 11 Apr 2011 19:51:55 +0000 Subject: 2011-04-11 Ivan Maidanski (mostly really Jim Meyering) * configure.host: Remove doubled words in comments. * os_dep.c: Ditto. * doc/README: Ditto. * extra/setjmp_t.c: Ditto. * tests/huge_test.c: Ditto. * extra/setjmp_t.c (getpagesize, nested_sp, main, g): Replace the K&R-style function definition with the ANSI C one. * extra/setjmp_t.c: Expand all tabs to spaces. * extra/setjmp_t.c (nested_sp): Implement in the same way as GC_approx_sp. --HG-- branch : bdwgc --- ChangeLog | 13 ++++ configure.host | 4 +- doc/README | 2 +- extra/setjmp_t.c | 177 +++++++++++++++++++++++++++--------------------------- os_dep.c | 4 +- tests/huge_test.c | 2 +- 6 files changed, 108 insertions(+), 94 deletions(-) diff --git a/ChangeLog b/ChangeLog index f2d1ded9..8d700e09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-04-11 Ivan Maidanski (mostly really Jim Meyering) + + * configure.host: Remove doubled words in comments. + * os_dep.c: Ditto. + * doc/README: Ditto. + * extra/setjmp_t.c: Ditto. + * tests/huge_test.c: Ditto. + * extra/setjmp_t.c (getpagesize, nested_sp, main, g): Replace the + K&R-style function definition with the ANSI C one. + * extra/setjmp_t.c: Expand all tabs to spaces. + * extra/setjmp_t.c (nested_sp): Implement in the same way as + GC_approx_sp. + 2011-04-10 Ivan Maidanski (really Iain Sandoe, Mike Stump) * dyn_load.c (GC_dyld_sections): Add more sctions. diff --git a/configure.host b/configure.host index a98a0a7c..898c9236 100644 --- a/configure.host +++ b/configure.host @@ -2,7 +2,7 @@ # This shell script handles all host based configuration for the garbage # collector. -# It sets various shell variables based on the the host and the +# It sets various shell variables based on the host and the # configuration options. You can modify this shell script without # needing to rerun autoconf. @@ -26,7 +26,7 @@ gc_cflags="" if test :"$GCC": = :yes: ; then gc_cflags="${gc_cflags} -fexceptions" else - case "$host" in + case "$host" in hppa*-*-hpux* ) if test :$GCC: != :"yes": ; then gc_cflags="${gc_flags} +ESdbgasm" diff --git a/doc/README b/doc/README index 5ca93f09..e9252bc5 100644 --- a/doc/README +++ b/doc/README @@ -129,7 +129,7 @@ ALL_INTERIOR_POINTERS defined, or GC_all_interior_pointers is otherwise set, as is now the default. Compiling without ALL_INTERIOR_POINTERS may reduce accidental retention -of garbage objects, by requiring pointers from the heap to to the beginning +of garbage objects, by requiring pointers from the heap to the beginning of an object. But this no longer appears to be a significant issue for most programs occupying a small fraction of the possible address space. diff --git a/extra/setjmp_t.c b/extra/setjmp_t.c index 5a171df0..5f4519b2 100644 --- a/extra/setjmp_t.c +++ b/extra/setjmp_t.c @@ -10,126 +10,127 @@ * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. */ - + /* Check whether setjmp actually saves registers in jmp_buf. */ /* If it doesn't, the generic mark_regs code won't work. */ -/* Compilers vary as to whether they will put x in a */ -/* (callee-save) register without -O. The code is */ +/* Compilers vary as to whether they will put x in a */ +/* (callee-save) register without -O. The code is */ /* contrived such that any decent compiler should put x in */ -/* a callee-save register with -O. Thus it is is */ +/* a callee-save register with -O. Thus it is */ /* recommended that this be run optimized. (If the machine */ /* has no callee-save registers, then the generic code is */ /* safe, but this will not be noticed by this piece of */ -/* code.) This test appears to be far from perfect. */ +/* code.) This test appears to be far from perfect. */ #include #include #include #include "private/gc_priv.h" #ifdef OS2 -/* GETPAGESIZE() is set to getpagesize() by default, but that */ -/* doesn't really exist, and the collector doesn't need it. */ +/* GETPAGESIZE() is set to getpagesize() by default, but that */ +/* doesn't really exist, and the collector doesn't need it. */ #define INCL_DOSFILEMGR #define INCL_DOSMISC #define INCL_DOSERRORS #include -int -getpagesize() +int getpagesize(void) { ULONG result[1]; - + if (DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, - (void *)result, sizeof(ULONG)) != NO_ERROR) { - fprintf(stderr, "DosQuerySysInfo failed\n"); - result[0] = 4096; + (void *)result, sizeof(ULONG)) != NO_ERROR) { + fprintf(stderr, "DosQuerySysInfo failed\n"); + result[0] = 4096; } return((int)(result[0])); } #endif -struct {char a_a; char * a_b;} a; +struct { + char a_a; + char * a_b; +} a; -int * nested_sp() +int * nested_sp(void) { - int dummy; - - return(&dummy); + volatile int sp; + sp = (int)&sp; + return (int *)sp; } -int main() +int main(void) { - int dummy; - long ps = GETPAGESIZE(); - jmp_buf b; - register int x = (int)strlen("a"); /* 1, slightly disguised */ - static int y = 0; + int dummy; + long ps = GETPAGESIZE(); + jmp_buf b; + register int x = (int)strlen("a"); /* 1, slightly disguised */ + static int y = 0; - printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE); - if (nested_sp() < &dummy) { - printf("Stack appears to grow down, which is the default.\n"); - printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", - ((unsigned long)(&dummy) + ps) & ~(ps-1)); - } else { - printf("Stack appears to grow up.\n"); - printf("Define STACK_GROWS_UP in gc_private.h\n"); - printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", - ((unsigned long)(&dummy) + ps) & ~(ps-1)); - } - printf("Note that this may vary between machines of ostensibly\n"); - printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n"); - printf("On many machines the value is not fixed.\n"); - printf("A good guess for ALIGNMENT on this machine is %ld.\n", - (unsigned long)(&(a.a_b))-(unsigned long)(&a)); - - printf("The following is a very dubious test of one root marking" - " strategy.\n"); - printf("Results may not be accurate/useful:\n"); - /* Encourage the compiler to keep x in a callee-save register */ - x = 2*x-1; - printf(""); - x = 2*x-1; - setjmp(b); - if (y == 1) { - if (x == 2) { - printf("Setjmp-based generic mark_regs code probably wont work.\n"); - printf("But we rarely try that anymore. If you have getcontect()\n"); - printf("this probably doesn't matter.\n"); - } else if (x == 1) { - printf("Setjmp-based register marking code may work.\n"); - } else { - printf("Very strange setjmp implementation.\n"); - } - } - y++; - x = 2; - if (y == 1) longjmp(b,1); - printf("Some GC internal configuration stuff: \n"); - printf("\tWORDSZ = %d, ALIGNMENT = %d, GC_GRANULE_BYTES = %d\n", - WORDSZ, ALIGNMENT, GC_GRANULE_BYTES); - printf("\tUsing one mark "); -# if defined(USE_MARK_BYTES) - printf("byte"); -# elif defined(USE_MARK_BITS) - printf("bit"); -# endif - printf(" per "); -# if defined(MARK_BIT_PER_OBJ) - printf("object.\n"); -# elif defined(MARK_BIT_PER_GRANULE) - printf("granule.\n"); -# endif -# ifdef THREAD_LOCAL_ALLOC - printf("Thread local allocation enabled.\n"); -# endif -# ifdef PARALLEL_MARK - printf("Parallel marking enabled.\n"); -# endif - return(0); + printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE); + if (nested_sp() < &dummy) { + printf("Stack appears to grow down, which is the default.\n"); + printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", + ((unsigned long)(&dummy) + ps) & ~(ps-1)); + } else { + printf("Stack appears to grow up.\n"); + printf("Define STACK_GROWS_UP in gc_private.h\n"); + printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", + ((unsigned long)(&dummy) + ps) & ~(ps-1)); + } + printf("Note that this may vary between machines of ostensibly\n"); + printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n"); + printf("On many machines the value is not fixed.\n"); + printf("A good guess for ALIGNMENT on this machine is %ld.\n", + (unsigned long)(&(a.a_b))-(unsigned long)(&a)); + + printf("The following is a very dubious test of one root marking" + " strategy.\n"); + printf("Results may not be accurate/useful:\n"); + /* Encourage the compiler to keep x in a callee-save register */ + x = 2*x-1; + printf(""); + x = 2*x-1; + setjmp(b); + if (y == 1) { + if (x == 2) { + printf("Setjmp-based generic mark_regs code probably wont work.\n"); + printf("But we rarely try that anymore. If you have getcontect()\n"); + printf("this probably doesn't matter.\n"); + } else if (x == 1) { + printf("Setjmp-based register marking code may work.\n"); + } else { + printf("Very strange setjmp implementation.\n"); + } + } + y++; + x = 2; + if (y == 1) longjmp(b,1); + printf("Some GC internal configuration stuff: \n"); + printf("\tWORDSZ = %d, ALIGNMENT = %d, GC_GRANULE_BYTES = %d\n", + WORDSZ, ALIGNMENT, GC_GRANULE_BYTES); + printf("\tUsing one mark "); +# if defined(USE_MARK_BYTES) + printf("byte"); +# elif defined(USE_MARK_BITS) + printf("bit"); +# endif + printf(" per "); +# if defined(MARK_BIT_PER_OBJ) + printf("object.\n"); +# elif defined(MARK_BIT_PER_GRANULE) + printf("granule.\n"); +# endif +# ifdef THREAD_LOCAL_ALLOC + printf("Thread local allocation enabled.\n"); +# endif +# ifdef PARALLEL_MARK + printf("Parallel marking enabled.\n"); +# endif + return(0); } -int g(x) -int x; +int g(int x) { - return(x); + return(x); } diff --git a/os_dep.c b/os_dep.c index eed14b8f..61ce2e2e 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2707,7 +2707,7 @@ STATIC void GC_default_push_other_roots(void) * the underlying memory was not allocated with the appropriate * flag. This is common if GC_enable_incremental is called * shortly after GC initialization. To avoid modifying the - * interface, we silently work around such a failure, it it only + * interface, we silently work around such a failure, it only * affects the initial (small) heap allocation. * If there are more dirty * pages than will fit in the buffer, this is not treated as a @@ -4467,7 +4467,7 @@ GC_API int GC_CALL GC_get_pages_executable(void) # include # endif # if NARGS > 6 -# error We only know how to to get the first 6 arguments +# error We only know how to get the first 6 arguments # endif #endif /* SPARC */ diff --git a/tests/huge_test.c b/tests/huge_test.c index 5ecc8311..bde9836d 100644 --- a/tests/huge_test.c +++ b/tests/huge_test.c @@ -14,7 +14,7 @@ /* * Check that very large allocation requests fail. "Success" would usually - * indicate that the the size was somehow converted to a negative + * indicate that the size was somehow converted to a negative * number. Clients shouldn't do this, but we should fail in the * expected manner. */ -- cgit v1.2.1 From e6faf3f59d26878a98c22f0c026dd5ddd87bdcd9 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 11 Apr 2011 20:20:06 +0000 Subject: 2011-04-11 Ivan Maidanski (really Jie Liu) * mach_dep.c (NO_GETCONTEXT); Define for RTEMS. * mach_dep.c (GC_with_callee_saves_pushed): Don't call __builtin_unwind_init() for RTEMS; use setjmp() without the leading underscore (for RTEMS). * tests/test.c (BIG): Use smaller value for RTEMS. * tests/test.c (main): Customize for RTEMS. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ mach_dep.c | 21 ++++++++++----------- tests/test.c | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d700e09..318e6a3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-04-11 Ivan Maidanski (really Jie Liu) + + * mach_dep.c (NO_GETCONTEXT); Define for RTEMS. + * mach_dep.c (GC_with_callee_saves_pushed): Don't call + __builtin_unwind_init() for RTEMS; use setjmp() without the + leading underscore (for RTEMS). + * tests/test.c (BIG): Use smaller value for RTEMS. + * tests/test.c (main): Customize for RTEMS. + 2011-04-11 Ivan Maidanski (mostly really Jim Meyering) * configure.host: Remove doubled words in comments. diff --git a/mach_dep.c b/mach_dep.c index 54697759..416dec8a 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -171,13 +171,11 @@ asm static void PushMacRegisters() # undef HAVE_PUSH_REGS #endif -#if defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) && \ - (defined(DARWIN) || defined(HURD) || defined(OPENBSD) \ - || defined(ARM32) || defined(MIPS) || defined(AVR32)) -# define NO_GETCONTEXT -#endif - -#if defined(LINUX) && defined(SPARC) && !defined(NO_GETCONTEXT) +#if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ + || defined(OPENBSD) || defined(ARM32) \ + || defined(MIPS) || defined(AVR32))) \ + || (defined(LINUX) && defined(SPARC)) \ + || (defined(RTEMS) && defined(I386))) && !defined(NO_GETCONTEXT) # define NO_GETCONTEXT #endif @@ -244,8 +242,9 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* subsumed by the getcontext() call. */ GC_save_regs_ret_val = GC_save_regs_in_stack(); # endif /* register windows. */ -# elif defined(HAVE_BUILTIN_UNWIND_INIT) && \ - !(defined(POWERPC) && defined(DARWIN)) +# elif defined(HAVE_BUILTIN_UNWIND_INIT) \ + && !(defined(POWERPC) && defined(DARWIN)) \ + && !(defined(I386) && defined(RTEMS)) /* This was suggested by Richard Henderson as the way to */ /* force callee-save registers and register windows onto */ /* the stack. */ @@ -267,8 +266,8 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), for (; (char *)i < lim; i++) { *i = 0; } -# if defined(MSWIN32) || defined(MSWINCE) \ - || defined(UTS4) || defined(LINUX) || defined(EWS4800) +# if defined(MSWIN32) || defined(MSWINCE) || defined(UTS4) \ + || defined(LINUX) || defined(EWS4800) || defined(RTEMS) (void) setjmp(regs); # else (void) _setjmp(regs); diff --git a/tests/test.c b/tests/test.c index 654332ee..63a10527 100644 --- a/tests/test.c +++ b/tests/test.c @@ -539,7 +539,7 @@ void *GC_CALLBACK reverse_test_inner(void *data) # elif defined(PCR) /* PCR default stack is 100K. Stack frames are up to 120 bytes. */ # define BIG 700 -# elif defined(MSWINCE) +# elif defined(MSWINCE) || defined(RTEMS) /* WinCE only allows 64K stacks */ # define BIG 500 # elif defined(OSF1) @@ -1377,12 +1377,21 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) # define WINMAIN_LPTSTR LPSTR #endif -#if !defined(PCR) \ - && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \ +#if !defined(PCR) && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \ || defined(LINT) #if defined(MSWIN32) && !defined(__MINGW32__) || defined(MSWINCE) int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, WINMAIN_LPTSTR cmd, int n) +#elif defined(RTEMS) +# include +# define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER +# define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +# define CONFIGURE_RTEMS_INIT_TASKS_TABLE +# define CONFIGURE_MAXIMUM_TASKS 1 +# define CONFIGURE_INIT +# define CONFIGURE_INIT_TASK_STACK_SIZE (64*1024) +# include + rtems_task Init(rtems_task_argument ignord) #else int main(void) #endif -- cgit v1.2.1 From 03a57b22d27848211ab70212463b262f53b09927 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 13 Apr 2011 19:49:11 +0000 Subject: 2011-04-13 Ivan Maidanski (mostly really Rainer Orth) * configure.ac (THREADDLLIBS): Use alternate thread library on Solaris 8. * configure.ac (need_atomic_ops_asm): Set to true only for Sparc Solaris. * configure.ac: Don't use libdl on mips-sgi-irix6. * configure: Regenerate. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ configure | 23 +++++++++++++++++------ configure.ac | 25 ++++++++++++++++++------- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 318e6a3f..f3b6fce1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-04-13 Ivan Maidanski (mostly really Rainer Orth) + + * configure.ac (THREADDLLIBS): Use alternate thread library on + Solaris 8. + * configure.ac (need_atomic_ops_asm): Set to true only for Sparc + Solaris. + * configure.ac: Don't use libdl on mips-sgi-irix6. + * configure: Regenerate. + 2011-04-11 Ivan Maidanski (really Jie Liu) * mach_dep.c (NO_GETCONTEXT); Define for RTEMS. diff --git a/configure b/configure index a06db048..01b690bd 100755 --- a/configure +++ b/configure @@ -5167,11 +5167,11 @@ $as_echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;} $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h - THREADDLLIBS="-lpthread -lrt" - if test "$GCC" != yes; then - CFLAGS="$CFLAGS -O" - need_atomic_ops_asm=true - fi + # Need to use alternate thread library, otherwise gctest hangs + # on Solaris 8. + multi_os_directory=`$CC -print-multi-os-directory` + THREADDLLIBS="-L/usr/lib/lwp/$multi_os_directory \ + -R/usr/lib/lwp/$multi_os_directory -lpthread -lrt" ;; *-*-irix*) $as_echo "#define GC_IRIX_THREADS 1" >>confdefs.h @@ -5225,6 +5225,14 @@ $as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; as_fn_error $? "\"Pthreads not supported by the GC on this platform.\"" "$LINENO" 5 ;; esac + case "$host" in + sparc*-*-solaris*) + if test "$GCC" != yes; then + CFLAGS="$CFLAGS -O" + need_atomic_ops_asm=true + fi + ;; + esac ;; win32) $as_echo "#define GC_THREADS 1" >>confdefs.h @@ -5366,9 +5374,12 @@ $as_echo "#define DARWIN_DONT_PARSE_STACK 1" >>confdefs.h fi +case "$host" in +# While IRIX 6 has libdl for the O32 and N32 ABIs, it's missing for N64 +# and unnecessary everywhere. + mips-sgi-irix6*) ;; # We never want libdl on darwin. It is a fake libdl that just ends up making # dyld calls anyway. The same applies to Cygwin. -case "$host" in *-*-darwin*) ;; *-*-cygwin*) ;; *) diff --git a/configure.ac b/configure.ac index 6df2ea87..f39e35dc 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_INIT(gc,7.2alpha5,Hans.Boehm@hp.com) AC_CONFIG_SRCDIR(gcj_mlc.c) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET -AC_PREREQ(2.53) +AC_PREREQ(2.64) AC_REVISION($Revision$) GC_SET_VERSION AM_INIT_AUTOMAKE([foreign dist-bzip2 nostdinc]) @@ -180,11 +180,11 @@ case "$THREADS" in *-*-solaris*) AC_DEFINE(GC_SOLARIS_THREADS) AC_DEFINE(THREAD_LOCAL_ALLOC) - THREADDLLIBS="-lpthread -lrt" - if test "$GCC" != yes; then - CFLAGS="$CFLAGS -O" - need_atomic_ops_asm=true - fi + # Need to use alternate thread library, otherwise gctest hangs + # on Solaris 8. + multi_os_directory=`$CC -print-multi-os-directory` + THREADDLLIBS="-L/usr/lib/lwp/$multi_os_directory \ + -R/usr/lib/lwp/$multi_os_directory -lpthread -lrt" ;; *-*-irix*) AC_DEFINE(GC_IRIX_THREADS) @@ -226,6 +226,14 @@ case "$THREADS" in AC_MSG_ERROR("Pthreads not supported by the GC on this platform.") ;; esac + case "$host" in + sparc*-*-solaris*) + if test "$GCC" != yes; then + CFLAGS="$CFLAGS -O" + need_atomic_ops_asm=true + fi + ;; + esac ;; win32) AC_DEFINE(GC_THREADS) @@ -293,9 +301,12 @@ if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then AC_DEFINE([DARWIN_DONT_PARSE_STACK], 1, [See doc/README.macros.]) fi +case "$host" in +# While IRIX 6 has libdl for the O32 and N32 ABIs, it's missing for N64 +# and unnecessary everywhere. + mips-sgi-irix6*) ;; # We never want libdl on darwin. It is a fake libdl that just ends up making # dyld calls anyway. The same applies to Cygwin. -case "$host" in *-*-darwin*) ;; *-*-cygwin*) ;; *) -- cgit v1.2.1 From 03bc0b5352658079f2e951cbb46a667a3f14d301 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 13 Apr 2011 20:27:47 +0000 Subject: 2011-04-13 Ivan Maidanski * dbg_mlc.c (GC_generate_random_backtrace_no_gc): Fix a message typo. * dbg_mlc.c (GC_debug_malloc): Add a comment (about zero size). * dbg_mlc.c (GC_debug_generic_malloc_inner): Reformat the comment. * dbg_mlc.c (GC_strdup): Call GC_err_printf instead of WARN (in case of NULL argument). * dbg_mlc.c (GC_free): In case of NULL argument, just return (without any warning printed); eliminate "uncollectable" local variable. --HG-- branch : bdwgc --- ChangeLog | 12 ++++++++++ dbg_mlc.c | 82 +++++++++++++++++++++++++++++---------------------------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3b6fce1..db1717ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-04-13 Ivan Maidanski + + * dbg_mlc.c (GC_generate_random_backtrace_no_gc): Fix a message + typo. + * dbg_mlc.c (GC_debug_malloc): Add a comment (about zero size). + * dbg_mlc.c (GC_debug_generic_malloc_inner): Reformat the comment. + * dbg_mlc.c (GC_strdup): Call GC_err_printf instead of WARN (in + case of NULL argument). + * dbg_mlc.c (GC_free): In case of NULL argument, just return + (without any warning printed); eliminate "uncollectable" local + variable. + 2011-04-13 Ivan Maidanski (mostly really Rainer Orth) * configure.ac (THREADDLLIBS): Use alternate thread library on diff --git a/dbg_mlc.c b/dbg_mlc.c index feaf51ad..0f05da96 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -233,7 +233,7 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); { void * current; current = GC_generate_random_valid_address(); - GC_printf("\n****Chose address %p in object\n", current); + GC_printf("\n****Chosen address %p in object\n", current); GC_print_backtrace(current); } @@ -477,7 +477,11 @@ GC_API void GC_CALL GC_debug_register_displacement(size_t offset) GC_API void * GC_CALL GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc(lb + DEBUG_BYTES); + void * result; + /* Note that according to malloc() specification, if size is 0 then */ + /* malloc() returns either NULL, or a unique pointer value that can */ + /* later be successfully passed to free(). We always do the latter. */ + result = GC_malloc(lb + DEBUG_BYTES); if (result == 0) { GC_err_printf("GC_debug_malloc(%lu) returning NULL (", @@ -519,7 +523,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, if (result == 0) { GC_err_printf("GC_debug_malloc_atomic_ignore_off_page(%lu)" - " returning NULL (", (unsigned long) lb); + " returning NULL (", (unsigned long)lb); GC_err_puts(s); GC_err_printf(":%lu)\n", (unsigned long)i); return(0); @@ -532,14 +536,11 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, } #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. - */ + /* 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. */ GC_INNER void * GC_debug_generic_malloc_inner(size_t lb, int k) { void * result = GC_generic_malloc_inner(lb + DEBUG_BYTES, k); @@ -660,9 +661,10 @@ GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS) size_t lb; if (str == NULL) { if (GC_find_leak) - WARN("strdup(NULL) behavior is undefined\n", 0); + GC_err_printf("strdup(NULL) behavior is undefined\n"); return NULL; } + lb = strlen(str) + 1; copy = GC_debug_malloc_atomic(lb, OPT_RA s, i); if (copy == NULL) { @@ -765,12 +767,8 @@ GC_API void GC_CALL GC_debug_free(void * p) # ifndef SHORT_DBG_HDRS ptr_t clobbered; # endif + if (0 == p) return; - if (0 == p) { - if (GC_find_leak) - WARN("free(NULL) is non-portable\n", 0); - return; - } base = GC_base(p); if (base == 0) { GC_err_printf("Attempt to free invalid pointer %p\n", p); @@ -799,18 +797,12 @@ GC_API void GC_CALL GC_debug_free(void * p) GC_free(base); } else { hdr * hhdr = HDR(p); - GC_bool uncollectable = FALSE; - - if (hhdr -> hb_obj_kind == UNCOLLECTABLE) { - uncollectable = TRUE; - } -# ifdef ATOMIC_UNCOLLECTABLE - if (hhdr -> hb_obj_kind == AUNCOLLECTABLE) { - uncollectable = TRUE; - } -# endif - if (uncollectable) { - GC_free(base); + if (hhdr -> hb_obj_kind == UNCOLLECTABLE +# ifdef ATOMIC_UNCOLLECTABLE + || hhdr -> hb_obj_kind == AUNCOLLECTABLE +# endif + ) { + GC_free(base); } else { size_t i; size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh)); @@ -845,11 +837,11 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) ptr_t clobbered; # endif void * result; - size_t copy_sz = lb; size_t old_sz; hdr * hhdr; + if (p == 0) + return(GC_debug_malloc(lb, OPT_RA s, i)); - if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i)); base = GC_base(p); if (base == 0) { GC_err_printf("Attempt to reallocate invalid pointer %p\n", p); @@ -886,6 +878,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) GC_err_printf("GC_debug_realloc: encountered bad kind\n"); ABORT("Bad kind"); } + # ifdef SHORT_DBG_HDRS old_sz = GC_size(base) - sizeof(oh); # else @@ -896,10 +889,11 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) } old_sz = ((oh *)base) -> oh_sz; # endif - if (old_sz < copy_sz) copy_sz = old_sz; - if (result == 0) return(0); - BCOPY(p, result, copy_sz); - GC_debug_free(p); + + if (result != NULL) { + BCOPY(p, result, old_sz < lb ? old_sz : lb); + GC_debug_free(p); + } return(result); } @@ -960,16 +954,16 @@ STATIC void GC_check_heap_block(struct hblk *hbp, word dummy) plim = hbp->hb_body + HBLKSIZE - sz; } /* go through all words in block */ - while( p <= plim ) { - if( mark_bit_from_hdr(hhdr, bit_no) - && GC_HAS_DEBUG_INFO((ptr_t)p)) { - ptr_t clobbered = GC_check_annotated_obj((oh *)p); - - if (clobbered != 0) GC_add_smashed(clobbered); - } - bit_no += MARK_BIT_OFFSET(sz); - p += sz; + while( p <= plim ) { + if( mark_bit_from_hdr(hhdr, bit_no) + && GC_HAS_DEBUG_INFO((ptr_t)p)) { + ptr_t clobbered = GC_check_annotated_obj((oh *)p); + + if (clobbered != 0) GC_add_smashed(clobbered); } + bit_no += MARK_BIT_OFFSET(sz); + p += sz; + } } /* This assumes that all accessible objects are marked, and that */ -- cgit v1.2.1 From a29c3976a30d09a79a3eccbf328f6ed29a988f90 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 16 Apr 2011 09:32:15 +0000 Subject: 2011-04-16 Ivan Maidanski * os_dep.c (GC_get_main_stack_base): Try to use pthread_attr_getstack first for Linux if THREADS. * doc/README.macros (USE_GET_STACKBASE_FOR_MAIN): Adjust text alignment. --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ doc/README.macros | 12 ++++++------ os_dep.c | 6 +++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index db1717ad..2b1d0494 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-04-16 Ivan Maidanski + + * os_dep.c (GC_get_main_stack_base): Try to use + pthread_attr_getstack first for Linux if THREADS. + * doc/README.macros (USE_GET_STACKBASE_FOR_MAIN): Adjust text + alignment. + 2011-04-13 Ivan Maidanski * dbg_mlc.c (GC_generate_random_backtrace_no_gc): Fix a message diff --git a/doc/README.macros b/doc/README.macros index c9951178..c4a33c4c 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -82,12 +82,12 @@ GC_REQUIRE_WCSDUP Force GC to export GC_wcsdup() (the Unicode version These define arguments influence the collector configuration: -FIND_LEAK Causes GC_find_leak to be initially set. This causes the +FIND_LEAK Causes GC_find_leak to be initially set. This causes the collector to assume that all inaccessible objects should have been explicitly deallocated, and reports exceptions. Finalization and the test program are not usable in this mode. -GC_ABORT_ON_LEAK Causes the application to be terminated once leaked or +GC_ABORT_ON_LEAK Causes the application to be terminated once leaked or smashed (corrupted on use-after-free) objects are found (after printing the information about that objects). @@ -96,7 +96,7 @@ SUNOS5SIGS Solaris-like signal handling. This is probably misnamed, for Solaris2.X, HPUX, and DRSNX. Should probably be set for some other platforms. -PCR Set if the collector is being built as part of the Xerox Portable +PCR Set if the collector is being built as part of the Xerox Portable Common Runtime. USE_COMPILER_TLS Assume the existence of __thread-style thread-local storage. @@ -551,6 +551,6 @@ PLATFORM_ANDROID Compile for Android NDK platform. SN_TARGET_PS3 Compile for Sony PS/3. USE_GET_STACKBASE_FOR_MAIN (Linux only) Use pthread_attr_getstack() instead -of __libc_stack_end (or instead of any hard-coded value) for getting the -primordial thread stack base (useful if the client modifies the program's -address space). + of __libc_stack_end (or instead of any hard-coded value) for getting the + primordial thread stack base (useful if the client modifies the program's + address space). diff --git a/os_dep.c b/os_dep.c index 61ce2e2e..b67e00ee 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1156,7 +1156,8 @@ GC_INNER word GC_page_size = 0; ptr_t GC_get_main_stack_base(void) { ptr_t result; /* also used as "dummy" to get the approx. sp value */ -# if defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN) && !defined(NACL) +# if defined(LINUX) && !defined(NACL) \ + && (defined(USE_GET_STACKBASE_FOR_MAIN) || defined(THREADS)) pthread_attr_t attr; void *stackaddr; size_t size; @@ -1221,8 +1222,7 @@ GC_INNER word GC_page_size = 0; } #endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */ -#if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE) \ - && !defined(NACL) +#if defined(GC_LINUX_THREADS) && !defined(NACL) # include /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */ -- cgit v1.2.1 From c6ead028f43bd1c334fb31e2b8b74d1c7b0b8f3d Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 18 Apr 2011 21:14:55 +0000 Subject: 2011-04-18 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner): Always define; add "const" to its string argument. * dbg_mlc.c (GC_store_debug_info): Call GC_store_debug_info_inner. * dbg_mlc.c (GC_debug_free): Set GC_have_errors in case of smashed or previously deallocated found. * dbg_mlc.c (GC_check_heap_block): Replace while loop with a for one. * reclaim.c (GC_reclaim_check): Ditto. * dbg_mlc.c (GC_check_heap_proc): Remove redundant cast to word. * os_dep.c (GC_get_stack_base): Don't initialize stackbase_main_self/ss_sp on Solaris if thr_main() is zero (thus calling GC_INIT() from a non-primordial thread is possible now). * reclaim.c (GC_add_leaked): Turn into an inline one. * reclaim.c (GC_reclaim_small_nonempty_block): Change report_if_found type from int/word to boolean. * include/private/gc_priv.h (GC_start_reclaim): Ditto. * include/private/gc_priv.h (set_mark_bit_from_hdr, clear_mark_bit_from_hdr): Place closing parenthesis properly; reformat the code. --HG-- branch : bdwgc --- ChangeLog | 22 ++++++++++++++ dbg_mlc.c | 77 +++++++++++++++++------------------------------ include/private/gc_priv.h | 21 ++++++------- os_dep.c | 2 +- reclaim.c | 26 +++++++--------- 5 files changed, 71 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b1d0494..08f60a65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-04-18 Ivan Maidanski + + * dbg_mlc.c (GC_store_debug_info_inner): Always define; add + "const" to its string argument. + * dbg_mlc.c (GC_store_debug_info): Call GC_store_debug_info_inner. + * dbg_mlc.c (GC_debug_free): Set GC_have_errors in case of + smashed or previously deallocated found. + * dbg_mlc.c (GC_check_heap_block): Replace while loop with a for + one. + * reclaim.c (GC_reclaim_check): Ditto. + * dbg_mlc.c (GC_check_heap_proc): Remove redundant cast to word. + * os_dep.c (GC_get_stack_base): Don't initialize + stackbase_main_self/ss_sp on Solaris if thr_main() is zero (thus + calling GC_INIT() from a non-primordial thread is possible now). + * reclaim.c (GC_add_leaked): Turn into an inline one. + * reclaim.c (GC_reclaim_small_nonempty_block): + Change report_if_found type from int/word to boolean. + * include/private/gc_priv.h (GC_start_reclaim): Ditto. + * include/private/gc_priv.h (set_mark_bit_from_hdr, + clear_mark_bit_from_hdr): Place closing parenthesis properly; + reformat the code. + 2011-04-16 Ivan Maidanski * os_dep.c (GC_get_main_stack_base): Try to use diff --git a/dbg_mlc.c b/dbg_mlc.c index 0f05da96..4ab78f97 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -251,39 +251,10 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); # define CROSSES_HBLK(p, sz) \ (((word)(p + sizeof(oh) + sz - 1) ^ (word)p) >= HBLKSIZE) -/* Store debugging info into p. Return displaced pointer. */ -/* Assumes we don't hold allocation lock. */ -GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, - word integer) -{ - word * result = (word *)((oh *)p + 1); - DCL_LOCK_STATE; - - LOCK(); - GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); - GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); -# ifdef KEEP_BACK_PTRS - ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); -# endif -# ifdef MAKE_BACK_GRAPH - ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0); -# endif - ((oh *)p) -> oh_string = string; - ((oh *)p) -> oh_int = integer; -# ifndef SHORT_DBG_HDRS - ((oh *)p) -> oh_sz = sz; - ((oh *)p) -> oh_sf = START_FLAG ^ (word)result; - ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] = - result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; -# endif - UNLOCK(); - return((ptr_t)result); -} -#ifdef DBG_HDRS_ALL /* Store debugging info into p. Return displaced pointer. */ /* This version assumes we do hold the allocation lock. */ -STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string, +STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, const char *string, word integer) { word * result = (word *)((oh *)p + 1); @@ -306,7 +277,18 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string, # endif return((ptr_t)result); } -#endif + +GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, + word integer) +{ + ptr_t result; + DCL_LOCK_STATE; + + LOCK(); + result = GC_store_debug_info_inner(p, sz, string, integer); + UNLOCK(); + return result; +} #ifndef SHORT_DBG_HDRS /* Check the object with debugging info at ohdr */ @@ -764,9 +746,6 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_API void GC_CALL GC_debug_free(void * p) { ptr_t base; -# ifndef SHORT_DBG_HDRS - ptr_t clobbered; -# endif if (0 == p) return; base = GC_base(p); @@ -776,18 +755,19 @@ GC_API void GC_CALL GC_debug_free(void * p) } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { GC_err_printf( - "GC_debug_free called on pointer %p w/o debugging info\n", p); + "GC_debug_free called on pointer %p w/o debugging info\n", p); } else { # ifndef SHORT_DBG_HDRS - clobbered = GC_check_annotated_obj((oh *)base); + ptr_t clobbered = GC_check_annotated_obj((oh *)base); if (clobbered != 0) { if (((oh *)base) -> oh_sz == GC_size(base)) { GC_err_printf( - "GC_debug_free: found previously deallocated (?) object at "); + "GC_debug_free: found previously deallocated (?) object at "); } else { GC_err_printf("GC_debug_free: found smashed location at "); } GC_print_smashed_obj(p, clobbered); + GC_have_errors = TRUE; } /* Invalidate size */ ((oh *)base) -> oh_sz = GC_size(base); @@ -886,6 +866,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) if (clobbered != 0) { GC_err_printf("GC_debug_realloc: found smashed location at "); GC_print_smashed_obj(p, clobbered); + GC_have_errors = TRUE; } old_sz = ((oh *)base) -> oh_sz; # endif @@ -947,22 +928,18 @@ STATIC void GC_check_heap_block(struct hblk *hbp, word dummy) char *p, *plim; p = hbp->hb_body; - bit_no = 0; if (sz > MAXOBJBYTES) { - plim = p; + plim = p; } else { - plim = hbp->hb_body + HBLKSIZE - sz; + plim = hbp->hb_body + HBLKSIZE - sz; } /* go through all words in block */ - while( p <= plim ) { - if( mark_bit_from_hdr(hhdr, bit_no) - && GC_HAS_DEBUG_INFO((ptr_t)p)) { - ptr_t clobbered = GC_check_annotated_obj((oh *)p); - - if (clobbered != 0) GC_add_smashed(clobbered); - } - bit_no += MARK_BIT_OFFSET(sz); - p += sz; + for (bit_no = 0; p <= plim; bit_no += MARK_BIT_OFFSET(sz), p += sz) { + if (mark_bit_from_hdr(hhdr, bit_no) && GC_HAS_DEBUG_INFO((ptr_t)p)) { + ptr_t clobbered = GC_check_annotated_obj((oh *)p); + if (clobbered != 0) + GC_add_smashed(clobbered); + } } } @@ -972,7 +949,7 @@ STATIC void GC_check_heap_proc(void) { GC_STATIC_ASSERT((sizeof(oh) & (GRANULE_BYTES - 1)) == 0); /* FIXME: Should we check for twice that alignment? */ - GC_apply_to_all_blocks(GC_check_heap_block, (word)0); + GC_apply_to_all_blocks(GC_check_heap_block, 0); } #endif /* !SHORT_DBG_HDRS */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index cb0bfb4a..df8bd04d 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1355,16 +1355,15 @@ struct GC_traced_stack_sect_s { #ifdef USE_MARK_BYTES # define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) -# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 1 -# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 0 +# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 1) +# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 0) #else /* !USE_MARK_BYTES */ -# define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ - >> (modWORDSZ(n))) & (word)1) +# define mark_bit_from_hdr(hhdr,n) \ + (((hhdr)->hb_marks[divWORDSZ(n)] >> (modWORDSZ(n))) & (word)1) # define set_mark_bit_from_hdr(hhdr,n) \ - OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ - (word)1 << modWORDSZ(n)) -# define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ - &= ~((word)1 << modWORDSZ(n)) + OR_WORD((hhdr)->hb_marks+divWORDSZ(n), (word)1 << modWORDSZ(n)) +# define clear_mark_bit_from_hdr(hhdr,n) \ + ((hhdr)->hb_marks[divWORDSZ(n)] &= ~((word)1 << modWORDSZ(n))) #endif /* !USE_MARK_BYTES */ #ifdef MARK_BIT_PER_OBJ @@ -1381,8 +1380,8 @@ struct GC_traced_stack_sect_s { # define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz) # define IF_PER_OBJ(x) # define FINAL_MARK_BIT(sz) \ - ((sz) > MAXOBJBYTES? MARK_BITS_PER_HBLK \ - : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) + ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \ + : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) #endif /* Important internal collector routines */ @@ -1628,7 +1627,7 @@ GC_INNER void GC_freehblk(struct hblk * p); /* Misc GC: */ GC_INNER GC_bool GC_expand_hp_inner(word n); -GC_INNER void GC_start_reclaim(int abort_if_found); +GC_INNER void GC_start_reclaim(GC_bool abort_if_found); /* Restore unmarked objects to free */ /* lists, or (if abort_if_found is */ /* TRUE) report them. */ diff --git a/os_dep.c b/os_dep.c index b67e00ee..75f9c7a7 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1361,7 +1361,7 @@ GC_INNER word GC_page_size = 0; /* s.ss_sp holds the pointer to the stack bottom. */ GC_ASSERT((void *)&s HOTTER_THAN s.ss_sp); - if (!stackbase_main_self) + if (!stackbase_main_self && thr_main() != 0) { /* Cache the stack base value for the primordial thread (this */ /* is done during GC_init, so there is no race). */ diff --git a/reclaim.c b/reclaim.c index efade9b7..6a204f71 100644 --- a/reclaim.c +++ b/reclaim.c @@ -41,7 +41,7 @@ STATIC unsigned GC_n_leaked = 0; GC_INNER GC_bool GC_have_errors = FALSE; -STATIC void GC_add_leaked(ptr_t leaked) +GC_INLINE void GC_add_leaked(ptr_t leaked) { GC_have_errors = TRUE; /* FIXME: Prevent adding an object while printing leaked ones. */ @@ -204,24 +204,20 @@ STATIC ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz, /* Don't really reclaim objects, just check for unmarked ones: */ STATIC void GC_reclaim_check(struct hblk *hbp, hdr *hhdr, word sz) { - word bit_no = 0; + word bit_no; ptr_t p, plim; - GC_ASSERT(sz == hhdr -> hb_sz); - p = hbp->hb_body; - plim = p + HBLKSIZE - sz; /* go through all words in block */ - while (p <= plim) { - if( !mark_bit_from_hdr(hhdr, bit_no) ) { - GC_add_leaked(p); - } - p += sz; - bit_no += MARK_BIT_OFFSET(sz); - } + p = hbp->hb_body; + plim = p + HBLKSIZE - sz; + for (bit_no = 0; p <= plim; p += sz, bit_no += MARK_BIT_OFFSET(sz)) { + if (!mark_bit_from_hdr(hhdr, bit_no)) { + GC_add_leaked(p); + } + } } - /* * Generic procedure to rebuild a free list in hbp. * Also called directly from GC_malloc_many. @@ -254,7 +250,7 @@ GC_INNER ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz, * caller should perform that check. */ STATIC void GC_reclaim_small_nonempty_block(struct hblk *hbp, - int report_if_found) + GC_bool report_if_found) { hdr *hhdr = HDR(hbp); size_t sz = hhdr -> hb_sz; @@ -326,7 +322,7 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) GC_atomic_in_use += sz * hhdr -> hb_n_marks; } if (report_if_found) { - GC_reclaim_small_nonempty_block(hbp, (int)report_if_found); + GC_reclaim_small_nonempty_block(hbp, (GC_bool)report_if_found); } else if (empty) { GC_bytes_found += HBLKSIZE; GC_freehblk(hbp); -- cgit v1.2.1 From 2c72ad8af41c592e53f8a1c0a1049691cd9d6d74 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 18 Apr 2011 22:11:59 +0000 Subject: 2011-04-18 Ivan Maidanski (really Ludovic Courtes) * tests/tests.am (TESTS, check_PROGRAMS): Add 'initsecondarythread'. * tests/tests.am (initsecondarythread_SOURCES, initsecondarythread_LDADD): New variable. * Makefile.in: Regenerate. * configure: Ditto. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ Makefile.in | 43 ++++++++++++++++++++++++++++++++++++------- configure | 2 +- tests/tests.am | 5 +++++ 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 08f60a65..cf253592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-04-18 Ivan Maidanski (really Ludovic Courtes) + + * tests/tests.am (TESTS, check_PROGRAMS): Add + 'initsecondarythread'. + * tests/tests.am (initsecondarythread_SOURCES, + initsecondarythread_LDADD): New variable. + * Makefile.in: Regenerate. + * configure: Ditto. + 2011-04-18 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner): Always define; add diff --git a/Makefile.in b/Makefile.in index 27163860..d043c3b0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -121,8 +121,9 @@ DIST_COMMON = $(am__configure_deps) $(am__pkginclude_HEADERS_DIST) \ mkinstalldirs @KEEP_BACK_PTRS_TRUE@am__append_7 = tracetest$(EXEEXT) @KEEP_BACK_PTRS_TRUE@am__append_8 = tracetest -@THREADS_TRUE@am__append_9 = threadleaktest$(EXEEXT) -@THREADS_TRUE@am__append_10 = threadleaktest +@THREADS_TRUE@am__append_9 = threadleaktest$(EXEEXT) \ +@THREADS_TRUE@ initsecondarythread$(EXEEXT) +@THREADS_TRUE@am__append_10 = threadleaktest initsecondarythread @CPLUSPLUS_TRUE@am__append_11 = test_cpp$(EXEEXT) @CPLUSPLUS_TRUE@am__append_12 = test_cpp subdir = . @@ -213,13 +214,20 @@ libstaticrootslib_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libstaticrootslib_la_LDFLAGS) $(LDFLAGS) -o $@ @KEEP_BACK_PTRS_TRUE@am__EXEEXT_1 = tracetest$(EXEEXT) -@THREADS_TRUE@am__EXEEXT_2 = threadleaktest$(EXEEXT) +@THREADS_TRUE@am__EXEEXT_2 = threadleaktest$(EXEEXT) \ +@THREADS_TRUE@ initsecondarythread$(EXEEXT) @CPLUSPLUS_TRUE@am__EXEEXT_3 = test_cpp$(EXEEXT) am_gctest_OBJECTS = test.$(OBJEXT) gctest_OBJECTS = $(am_gctest_OBJECTS) am_hugetest_OBJECTS = huge_test.$(OBJEXT) hugetest_OBJECTS = $(am_hugetest_OBJECTS) hugetest_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__initsecondarythread_SOURCES_DIST = tests/initsecondarythread.c +@THREADS_TRUE@am_initsecondarythread_OBJECTS = \ +@THREADS_TRUE@ initsecondarythread.$(OBJEXT) +initsecondarythread_OBJECTS = $(am_initsecondarythread_OBJECTS) +@THREADS_TRUE@initsecondarythread_DEPENDENCIES = \ +@THREADS_TRUE@ $(am__DEPENDENCIES_2) am_leaktest_OBJECTS = leak_test.$(OBJEXT) leaktest_OBJECTS = $(am_leaktest_OBJECTS) leaktest_DEPENDENCIES = $(am__DEPENDENCIES_2) @@ -283,16 +291,17 @@ LTCCASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ SOURCES = $(libcord_la_SOURCES) $(libgc_la_SOURCES) \ $(EXTRA_libgc_la_SOURCES) $(nodist_libgc_la_SOURCES) \ $(libgccpp_la_SOURCES) $(libstaticrootslib_la_SOURCES) \ - $(gctest_SOURCES) $(hugetest_SOURCES) $(leaktest_SOURCES) \ + $(gctest_SOURCES) $(hugetest_SOURCES) \ + $(initsecondarythread_SOURCES) $(leaktest_SOURCES) \ $(middletest_SOURCES) $(smashtest_SOURCES) \ $(staticrootstest_SOURCES) $(test_cpp_SOURCES) \ $(threadleaktest_SOURCES) $(tracetest_SOURCES) DIST_SOURCES = $(libcord_la_SOURCES) $(am__libgc_la_SOURCES_DIST) \ $(EXTRA_libgc_la_SOURCES) $(am__libgccpp_la_SOURCES_DIST) \ $(libstaticrootslib_la_SOURCES) $(gctest_SOURCES) \ - $(hugetest_SOURCES) $(leaktest_SOURCES) $(middletest_SOURCES) \ - $(smashtest_SOURCES) $(staticrootstest_SOURCES) \ - $(am__test_cpp_SOURCES_DIST) \ + $(hugetest_SOURCES) $(am__initsecondarythread_SOURCES_DIST) \ + $(leaktest_SOURCES) $(middletest_SOURCES) $(smashtest_SOURCES) \ + $(staticrootstest_SOURCES) $(am__test_cpp_SOURCES_DIST) \ $(am__threadleaktest_SOURCES_DIST) \ $(am__tracetest_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -662,6 +671,8 @@ libstaticrootslib_la_DEPENDENCIES = $(top_builddir)/libgc.la @KEEP_BACK_PTRS_TRUE@tracetest_LDADD = $(test_ldadd) @THREADS_TRUE@threadleaktest_SOURCES = tests/thread_leak_test.c @THREADS_TRUE@threadleaktest_LDADD = $(test_ldadd) +@THREADS_TRUE@initsecondarythread_SOURCES = tests/initsecondarythread.c +@THREADS_TRUE@initsecondarythread_LDADD = $(test_ldadd) @CPLUSPLUS_TRUE@test_cpp_SOURCES = tests/test_cpp.cc @AVOID_CPP_LIB_FALSE@@CPLUSPLUS_TRUE@test_cpp_LDADD = libgccpp.la $(test_ldadd) @AVOID_CPP_LIB_TRUE@@CPLUSPLUS_TRUE@test_cpp_LDADD = gc_cpp.o $(test_ldadd) @@ -826,6 +837,9 @@ gctest$(EXEEXT): $(gctest_OBJECTS) $(gctest_DEPENDENCIES) hugetest$(EXEEXT): $(hugetest_OBJECTS) $(hugetest_DEPENDENCIES) @rm -f hugetest$(EXEEXT) $(LINK) $(hugetest_OBJECTS) $(hugetest_LDADD) $(LIBS) +initsecondarythread$(EXEEXT): $(initsecondarythread_OBJECTS) $(initsecondarythread_DEPENDENCIES) + @rm -f initsecondarythread$(EXEEXT) + $(LINK) $(initsecondarythread_OBJECTS) $(initsecondarythread_LDADD) $(LIBS) leaktest$(EXEEXT): $(leaktest_OBJECTS) $(leaktest_DEPENDENCIES) @rm -f leaktest$(EXEEXT) $(LINK) $(leaktest_OBJECTS) $(leaktest_LDADD) $(LIBS) @@ -875,6 +889,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcj_mlc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/headers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huge_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsecondarythread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/leak_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mallocx.Plo@am__quote@ @@ -1018,6 +1033,20 @@ huge_test.obj: tests/huge_test.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o huge_test.obj `if test -f 'tests/huge_test.c'; then $(CYGPATH_W) 'tests/huge_test.c'; else $(CYGPATH_W) '$(srcdir)/tests/huge_test.c'; fi` +initsecondarythread.o: tests/initsecondarythread.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT initsecondarythread.o -MD -MP -MF $(DEPDIR)/initsecondarythread.Tpo -c -o initsecondarythread.o `test -f 'tests/initsecondarythread.c' || echo '$(srcdir)/'`tests/initsecondarythread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/initsecondarythread.Tpo $(DEPDIR)/initsecondarythread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/initsecondarythread.c' object='initsecondarythread.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o initsecondarythread.o `test -f 'tests/initsecondarythread.c' || echo '$(srcdir)/'`tests/initsecondarythread.c + +initsecondarythread.obj: tests/initsecondarythread.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT initsecondarythread.obj -MD -MP -MF $(DEPDIR)/initsecondarythread.Tpo -c -o initsecondarythread.obj `if test -f 'tests/initsecondarythread.c'; then $(CYGPATH_W) 'tests/initsecondarythread.c'; else $(CYGPATH_W) '$(srcdir)/tests/initsecondarythread.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/initsecondarythread.Tpo $(DEPDIR)/initsecondarythread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/initsecondarythread.c' object='initsecondarythread.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o initsecondarythread.obj `if test -f 'tests/initsecondarythread.c'; then $(CYGPATH_W) 'tests/initsecondarythread.c'; else $(CYGPATH_W) '$(srcdir)/tests/initsecondarythread.c'; fi` + leak_test.o: tests/leak_test.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT leak_test.o -MD -MP -MF $(DEPDIR)/leak_test.Tpo -c -o leak_test.o `test -f 'tests/leak_test.c' || echo '$(srcdir)/'`tests/leak_test.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/leak_test.Tpo $(DEPDIR)/leak_test.Po diff --git a/configure b/configure index 01b690bd..3681b580 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 1.64 . +# From configure.ac Revision: 1.65 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for gc 7.2alpha5. # diff --git a/tests/tests.am b/tests/tests.am index b655c2ba..e773c45a 100644 --- a/tests/tests.am +++ b/tests/tests.am @@ -67,6 +67,11 @@ TESTS += threadleaktest$(EXEEXT) check_PROGRAMS += threadleaktest threadleaktest_SOURCES = tests/thread_leak_test.c threadleaktest_LDADD = $(test_ldadd) + +TESTS += initsecondarythread$(EXEEXT) +check_PROGRAMS += initsecondarythread +initsecondarythread_SOURCES = tests/initsecondarythread.c +initsecondarythread_LDADD = $(test_ldadd) endif if CPLUSPLUS -- cgit v1.2.1 From afd0824df28b7246d38058990adc6cc4c54dd1f0 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 18 Apr 2011 22:15:40 +0000 Subject: 2011-04-18 Ivan Maidanski (really Ludovic Courtes) * tests/tests.am (TESTS, check_PROGRAMS): Add 'initsecondarythread'. * tests/tests.am (initsecondarythread_SOURCES, initsecondarythread_LDADD): New variable. * Makefile.in: Regenerate. * configure: Ditto. --HG-- branch : bdwgc --- tests/initsecondarythread.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100755 tests/initsecondarythread.c diff --git a/tests/initsecondarythread.c b/tests/initsecondarythread.c new file mode 100755 index 00000000..feed5604 --- /dev/null +++ b/tests/initsecondarythread.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 Ludovic Courtes + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* Make sure 'GC_INIT' can be called from threads other than the initial + * thread. + */ + +#ifndef GC_THREADS +# define GC_THREADS +#endif + +#define GC_NO_THREAD_REDIRECTS 1 + +#include "gc.h" + +#include +#include + +static void *thread(void *arg) +{ + GC_INIT (); + GC_MALLOC (123); + GC_MALLOC (12345); + return NULL; +} + +int main(void) +{ + pthread_t t; + pthread_create (&t, NULL, thread, NULL); + pthread_join (t, NULL); + return 0; +} -- cgit v1.2.1 From 1c88d591b7a61d122f4700b53bcfa4c4e861d8f1 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 19 Apr 2011 11:27:59 +0000 Subject: 2011-04-19 Ivan Maidanski * include/private/gc_priv.h (_GNU_SOURCE): Include features.h first (except for NaCl) and then define the macro to 1 if not yet. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ include/private/gc_priv.h | 33 +++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf253592..9079f5a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-19 Ivan Maidanski + + * include/private/gc_priv.h (_GNU_SOURCE): Include features.h + first (except for NaCl) and then define the macro to 1 if not yet. + 2011-04-18 Ivan Maidanski (really Ludovic Courtes) * tests/tests.am (TESTS, check_PROGRAMS): Add diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index df8bd04d..b1bb9c78 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -26,11 +26,15 @@ # define GC_BUILD #endif -#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \ - && !defined(_GNU_SOURCE) +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) /* Can't test LINUX, since this must be defined before other includes. */ -# define _GNU_SOURCE -#endif +# if !defined(__native_client__) +# include +# endif +# ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# endif +#endif /* __linux__ */ #if (defined(DGUX) && defined(GC_THREADS) || defined(DGUX386_THREADS) \ || defined(GC_DGUX386_THREADS)) && !defined(_USING_POSIX4A_DRAFT10) @@ -1355,15 +1359,16 @@ struct GC_traced_stack_sect_s { #ifdef USE_MARK_BYTES # define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) -# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 1) -# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 0) +# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 1 +# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 0 #else /* !USE_MARK_BYTES */ -# define mark_bit_from_hdr(hhdr,n) \ - (((hhdr)->hb_marks[divWORDSZ(n)] >> (modWORDSZ(n))) & (word)1) +# define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ + >> (modWORDSZ(n))) & (word)1) # define set_mark_bit_from_hdr(hhdr,n) \ - OR_WORD((hhdr)->hb_marks+divWORDSZ(n), (word)1 << modWORDSZ(n)) -# define clear_mark_bit_from_hdr(hhdr,n) \ - ((hhdr)->hb_marks[divWORDSZ(n)] &= ~((word)1 << modWORDSZ(n))) + OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ + (word)1 << modWORDSZ(n)) +# define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ + &= ~((word)1 << modWORDSZ(n)) #endif /* !USE_MARK_BYTES */ #ifdef MARK_BIT_PER_OBJ @@ -1380,8 +1385,8 @@ struct GC_traced_stack_sect_s { # define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz) # define IF_PER_OBJ(x) # define FINAL_MARK_BIT(sz) \ - ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \ - : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) + ((sz) > MAXOBJBYTES? MARK_BITS_PER_HBLK \ + : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) #endif /* Important internal collector routines */ @@ -1627,7 +1632,7 @@ GC_INNER void GC_freehblk(struct hblk * p); /* Misc GC: */ GC_INNER GC_bool GC_expand_hp_inner(word n); -GC_INNER void GC_start_reclaim(GC_bool abort_if_found); +GC_INNER void GC_start_reclaim(int abort_if_found); /* Restore unmarked objects to free */ /* lists, or (if abort_if_found is */ /* TRUE) report them. */ -- cgit v1.2.1 From ca53c4749552bd401300f6aee262834a2d6162e7 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 19 Apr 2011 17:49:22 +0000 Subject: 2011-04-19 Ivan Maidanski * misc.c (GC_parse_mem_size_arg): New function. * misc.c (GC_init): Use GC_parse_mem_size_arg(). * pthread_stop_world.c (tkill): Declare for Android. --HG-- branch : bdwgc --- ChangeLog | 6 ++++++ misc.c | 12 ++++++++++-- pthread_stop_world.c | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9079f5a6..ffc1aa2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-04-19 Ivan Maidanski + + * misc.c (GC_parse_mem_size_arg): New function. + * misc.c (GC_init): Use GC_parse_mem_size_arg(). + * pthread_stop_world.c (tkill): Declare for Android. + 2011-04-19 Ivan Maidanski * include/private/gc_priv.h (_GNU_SOURCE): Include features.h diff --git a/misc.c b/misc.c index 51a92483..59bdd127 100644 --- a/misc.c +++ b/misc.c @@ -633,6 +633,14 @@ STATIC void GC_exit_check(void) STATIC int GC_log = 2; /* stderr */ #endif +STATIC word GC_parse_mem_size_arg(const char *str) +{ + char *endptr; + word result = (word)STRTOULL(str, &endptr, 10); + /* TODO: allow 'k', 'M', 'G' suffix */ + return result; +} + GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */ GC_INNER void GC_bl_init(void); /* defined in blacklst.c */ @@ -941,7 +949,7 @@ GC_API void GC_CALL GC_init(void) { char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE"); if (sz_str != NULL) { - initial_heap_sz = (word)STRTOULL(sz_str, NULL, 10); + initial_heap_sz = GC_parse_mem_size_arg(sz_str); if (initial_heap_sz <= MINHINCR * HBLKSIZE) { WARN("Bad initial heap size %s - ignoring it.\n", sz_str); } @@ -951,7 +959,7 @@ GC_API void GC_CALL GC_init(void) { char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); if (sz_str != NULL) { - word max_heap_sz = (word)STRTOULL(sz_str, NULL, 10); + word max_heap_sz = GC_parse_mem_size_arg(sz_str); if (max_heap_sz < initial_heap_sz * HBLKSIZE) { WARN("Bad maximum heap size %s - ignoring it.\n", sz_str); } diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 4ec6fe1f..af0c62e5 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -375,6 +375,8 @@ GC_INNER void GC_push_all_stacks(void) #endif #ifdef PLATFORM_ANDROID + extern int tkill(pid_t tid, int sig); /* from sys/linux-unistd.h */ + static int android_thread_kill(pid_t tid, int sig) { int ret; -- cgit v1.2.1 From 4db2a15f3cc1c893e5f11ef8a18512c20a6b5cae Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 20 Apr 2011 21:25:19 +0000 Subject: 2011-04-20 Ivan Maidanski * misc.c (GC_parse_mem_size_arg): Allow 'k', 'M', 'G' suffixes in heap size specifier; return 0 if not a valid one. * include/gc_cpp.h: Explicitly define inline one-argument delete operator for Cygwin (as a workaround). * include/gc_cpp.h: Reformat the code. * tests/test_cpp.cc: Ditto. * tests/test_cpp.cc (main): Suppress compiler warnings about "assigned value is unused". --HG-- branch : bdwgc --- ChangeLog | 11 ++++++++ include/gc_cpp.h | 76 ++++++++++++++++++++++++++++--------------------------- misc.c | 30 ++++++++++++++++++++-- tests/test_cpp.cc | 58 +++++++++++++++++++++++------------------- 4 files changed, 110 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffc1aa2c..5dda048c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-04-20 Ivan Maidanski + + * misc.c (GC_parse_mem_size_arg): Allow 'k', 'M', 'G' suffixes in + heap size specifier; return 0 if not a valid one. + * include/gc_cpp.h: Explicitly define inline one-argument delete + operator for Cygwin (as a workaround). + * include/gc_cpp.h: Reformat the code. + * tests/test_cpp.cc: Ditto. + * tests/test_cpp.cc (main): Suppress compiler warnings about + "assigned value is unused". + 2011-04-19 Ivan Maidanski * misc.c (GC_parse_mem_size_arg): New function. diff --git a/include/gc_cpp.h b/include/gc_cpp.h index ff77a1fd..302fdc2d 100644 --- a/include/gc_cpp.h +++ b/include/gc_cpp.h @@ -244,9 +244,9 @@ inline void* operator new( classes derived from "gc_cleanup" or containing members derived from "gc_cleanup". */ -# ifdef GC_PLACEMENT_DELETE - inline void operator delete( void*, GCPlacement, GCCleanUpFunc, void * ); -# endif +#ifdef GC_PLACEMENT_DELETE + inline void operator delete( void*, GCPlacement, GCCleanUpFunc, void * ); +#endif #ifdef _MSC_VER /** This ensures that the system default operator new[] doesn't get @@ -255,27 +255,26 @@ inline void* operator new( * There seems to be no way to redirect new in this environment without * including this everywhere. */ -#if _MSC_VER > 1020 - void *operator new[]( size_t size ); +# if _MSC_VER > 1020 + void *operator new[]( size_t size ); - void operator delete[](void* obj); -#endif + void operator delete[](void* obj); +# endif - void* operator new( size_t size); + void* operator new(size_t size); - void operator delete(void* obj); + void operator delete(void* obj); - // This new operator is used by VC++ in case of Debug builds ! - void* operator new( size_t size, + // This new operator is used by VC++ in case of Debug builds ! + void* operator new( size_t size, int ,//nBlockUse, const char * szFileName, int nLine ); #endif /* _MSC_VER */ - #ifdef GC_OPERATOR_NEW_ARRAY -inline void* operator new[]( + inline void* operator new[]( size_t size, GCPlacement gcp, GCCleanUpFunc cleanup = 0, @@ -317,30 +316,26 @@ inline void gc::operator delete( void* obj ) { #endif #ifdef GC_OPERATOR_NEW_ARRAY - -inline void* gc::operator new[]( size_t size ) { + inline void* gc::operator new[]( size_t size ) { return gc::operator new( size );} -inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { + inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { return gc::operator new( size, gcp );} -inline void* gc::operator new[]( size_t size, void *p ) { + inline void* gc::operator new[]( size_t size, void *p ) { return p;} -inline void gc::operator delete[]( void* obj ) { + inline void gc::operator delete[]( void* obj ) { gc::operator delete( obj );} -#ifdef GC_PLACEMENT_DELETE - inline void gc::operator delete[]( void*, void* ) {} - - inline void gc::operator delete[]( void* p, GCPlacement gcp ) { - gc::operator delete(p); } - -#endif +# ifdef GC_PLACEMENT_DELETE + inline void gc::operator delete[]( void*, void* ) {} + inline void gc::operator delete[]( void* p, GCPlacement gcp ) { + gc::operator delete(p); } +# endif #endif /* GC_OPERATOR_NEW_ARRAY */ - inline gc_cleanup::~gc_cleanup() { GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );} @@ -354,7 +349,7 @@ inline gc_cleanup::gc_cleanup() { if (0 != base) { // Don't call the debug version, since this is a real base address. GC_register_finalizer_ignore_self( - base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base), + base, (GC_finalization_proc)cleanup, (void*)((char*)this - (char*)base), &oldProc, &oldData ); if (0 != oldProc) { GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}} @@ -378,27 +373,34 @@ inline void* operator new( obj = GC_MALLOC_UNCOLLECTABLE( size );}; return obj;} -# ifdef GC_PLACEMENT_DELETE -inline void operator delete ( +#ifdef GC_PLACEMENT_DELETE + inline void operator delete ( void *p, GCPlacement gcp, GCCleanUpFunc cleanup, void* clientData ) -{ + { GC_FREE(p); -} -# endif + } +#endif /* GC_PLACEMENT_DELETE */ #ifdef GC_OPERATOR_NEW_ARRAY - -inline void* operator new[]( + inline void* operator new[]( size_t size, GCPlacement gcp, GCCleanUpFunc cleanup, void* clientData ) -{ - return ::operator new( size, gcp, cleanup, clientData );} - + { + return ::operator new( size, gcp, cleanup, clientData ); + } #endif /* GC_OPERATOR_NEW_ARRAY */ +#if defined(__CYGWIN__) +# include // for delete throw() + inline void operator delete(void *p) + { + GC_FREE(p); + } +#endif + #endif /* GC_CPP_H */ diff --git a/misc.c b/misc.c index 59bdd127..ee6fa963 100644 --- a/misc.c +++ b/misc.c @@ -636,8 +636,34 @@ STATIC void GC_exit_check(void) STATIC word GC_parse_mem_size_arg(const char *str) { char *endptr; - word result = (word)STRTOULL(str, &endptr, 10); - /* TODO: allow 'k', 'M', 'G' suffix */ + word result = 0; /* bad value */ + char ch; + + if (*str != '\0') { + result = (word)STRTOULL(str, &endptr, 10); + ch = *endptr; + if (ch != '\0') { + if (*(endptr + 1) != '\0') + return 0; + /* Allow k, M or G suffix. */ + switch (ch) { + case 'K': + case 'k': + result <<= 10; + break; + case 'M': + case 'm': + result <<= 20; + break; + case 'G': + case 'g': + result <<= 30; + break; + default: + result = 0; + } + } + } return result; } diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 94a8ca37..ce683af4 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -27,12 +27,17 @@ few minutes to complete. #ifdef HAVE_CONFIG_H # include "private/config.h" #endif + #undef GC_BUILD + #include "gc_cpp.h" + #include #include #include + #define USE_STD_ALLOCATOR + #ifdef USE_STD_ALLOCATOR # include "gc_allocator.h" #elif __GNUC__ @@ -40,6 +45,7 @@ few minutes to complete. #else # include "gc_alloc.h" #endif + extern "C" { # include "private/gcconfig.h" GC_API void GC_printf(const char *format, ...); @@ -47,17 +53,18 @@ extern "C" { /* Don't include gc_priv.h, since that may include Windows system */ /* header files that don't take kindly to this context. */ } + #ifdef MSWIN32 -# include +# include #endif + #ifdef GC_NAME_CONFLICT -# define USE_GC UseGC - struct foo * GC; +# define USE_GC UseGC + struct foo * GC; #else -# define USE_GC GC +# define USE_GC GC #endif - #define my_assert( e ) \ if (! (e)) { \ GC_printf( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \ @@ -180,7 +187,6 @@ GC_word Disguise( void* p ) { void* Undisguise( GC_word i ) { return (void*) ~ i;} - #ifdef MSWIN32 int APIENTRY WinMain( HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) @@ -188,29 +194,25 @@ int APIENTRY WinMain( int argc; char* argv[ 3 ]; - for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) { + for (argc = 1; argc < (int)(sizeof(argv) / sizeof(argv[0])); argc++) { argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" ); if (0 == argv[ argc ]) break;} - +#elif defined(MACOS) + int main() { + char* argv_[] = {"test_cpp", "10"}; // MacOS doesn't have a commandline + argv = argv_; + argc = sizeof(argv_)/sizeof(argv_[0]); #else -# ifdef MACOS - int main() { -# else - int main( int argc, char* argv[] ) { -# endif + int main( int argc, char* argv[] ) { #endif - GC_INIT(); + GC_INIT(); -# if defined(MACOS) // MacOS - char* argv_[] = {"test_cpp", "10"}; // doesn't - argv = argv_; // have a - argc = sizeof(argv_)/sizeof(argv_[0]); // commandline -# endif int i, iters, n; # ifdef USE_STD_ALLOCATOR int *x = gc_allocator().allocate(1); - int *xio = gc_allocator_ignore_off_page().allocate(1); + int *xio; + xio = gc_allocator_ignore_off_page().allocate(1); int **xptr = traceable_allocator().allocate(1); # else # ifdef __GNUC__ @@ -237,7 +239,7 @@ int APIENTRY WinMain( GC_word as[ 1000 ]; GC_word bs[ 1000 ]; for (i = 0; i < 1000; i++) { - as[ i ] = Disguise( new (NoGC) A( i ) ); + as[ i ] = Disguise( new (NoGC ) A( i ) ); bs[ i ] = Disguise( new (NoGC) B( i ) );} /* Allocate a fair number of finalizable Cs, Ds, and Fs. @@ -245,15 +247,18 @@ int APIENTRY WinMain( for (i = 0; i < 1000; i++) { C* c = new C( 2 ); C c1( 2 ); /* stack allocation should work too */ - D* d = ::new (USE_GC, D::CleanUp, (void*)(GC_word)i) D( i ); - F* f = new F; + D* d; + F* f; + d = ::new (USE_GC, D::CleanUp, (void*)(GC_word)i) D( i ); + f = new F; if (0 == i % 10) delete c;} /* Allocate a very large number of collectable As and Bs and drop the references to them immediately, forcing many collections. */ for (i = 0; i < 1000000; i++) { - A* a = new (USE_GC) A( i ); + A* a; + a = new (USE_GC) A( i ); B* b = new B( i ); b = new (USE_GC) B( i ); if (0 == i % 10) { @@ -278,7 +283,6 @@ int APIENTRY WinMain( # ifdef FINALIZE_ON_DEMAND GC_invoke_finalizers(); # endif - } /* Make sure most of the finalizable Cs, Ds, and Fs have @@ -292,4 +296,6 @@ int APIENTRY WinMain( # endif my_assert (29 == x[0]); GC_printf( "The test appears to have succeeded.\n" ); - return( 0 );} + return( 0 ); +} + -- cgit v1.2.1 From 16a9cb0b85324a9e474276014b4187dff0ca7060 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 21 Apr 2011 07:10:16 +0000 Subject: 2011-04-21 Ivan Maidanski * doc/README.environment (GC_INITIAL_HEAP_SIZE, GC_MAXIMUM_HEAP_SIZE): Update. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ doc/README.environment | 26 ++++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5dda048c..caad631c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-21 Ivan Maidanski + + * doc/README.environment (GC_INITIAL_HEAP_SIZE, + GC_MAXIMUM_HEAP_SIZE): Update. + 2011-04-20 Ivan Maidanski * misc.c (GC_parse_mem_size_arg): Allow 'k', 'M', 'G' suffixes in diff --git a/doc/README.environment b/doc/README.environment index ce12067c..d9995f59 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -1,15 +1,17 @@ -The garbage collector looks at a number of environment variables which are -then used to affect its operation. These are examined only on Un*x-like -platforms and win32. +The garbage collector looks at a number of environment variables which are, +then, used to affect its operation. GC_INITIAL_HEAP_SIZE= - Initial heap size in bytes. May speed up - process start-up. + process start-up. Optionally, may be + specified with a multiplier ('k', 'M' or 'G') + suffix. -GC_MAXIMUM_HEAP_SIZE= - Maximum collected heap size. +GC_MAXIMUM_HEAP_SIZE= - Maximum collected heap size. Allows + a multiplier suffix. GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop. This may make it easier to debug, such a process, especially - for multithreaded platforms that don't produce usable core + for multi-threaded platforms that don't produce usable core files, or if a core file would be too large. On some platforms, this also causes SIGSEGV to be caught and result in an infinite loop in a handler, allowing @@ -32,7 +34,7 @@ GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup if you have a bug to report, but please include only the last complete dump. -GC_BACKTRACES= - Generate n random backtraces (for heap profiling) after +GC_BACKTRACES= - Generate n random back-traces (for heap profiling) after each GC. Collector must have been built with KEEP_BACK_PTRS. This won't generate useful output unless most objects in the heap were allocated through debug @@ -74,7 +76,7 @@ GC_IGNORE_GCJ_INFO - Ignore the type descriptors implicitly supplied by descriptor generation problems, and possibly for temporarily working around such problems. It forces a fully conservative scan of all heap objects except - those known to be pointerfree, and may thus have other + those known to be pointer-free, and may thus have other adverse effects. GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects @@ -118,10 +120,10 @@ other means, but this may help with debugging and testing: GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that, depending on platform and collector configuration, this may involve write protecting pieces of the heap to - track modifications. These pieces may include pointerfree - objects or not. Although this is intended to be - transparent, it may cause unintended system call failures. - Use with caution. + track modifications. These pieces may include + pointer-free objects or not. Although this is intended + to be transparent, it may cause unintended system call + failures. Use with caution. GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs. This only has an effect if incremental collection is -- cgit v1.2.1 From 818f431092a17475e315cb61ccc72094d29659ca Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 21 Apr 2011 15:20:01 +0000 Subject: 2011-04-21 Ivan Maidanski * include/private/gc_priv.h (_GNU_SOURCE): Revert one of the recent patches regarding this macro as the macro should be set (to 1) before including any other system header. --HG-- branch : bdwgc --- ChangeLog | 6 ++++++ include/private/gc_priv.h | 12 ++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index caad631c..80f1b0cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-04-21 Ivan Maidanski + + * include/private/gc_priv.h (_GNU_SOURCE): Revert one of the + recent patches regarding this macro as the macro should be set + (to 1) before including any other system header. + 2011-04-21 Ivan Maidanski * doc/README.environment (GC_INITIAL_HEAP_SIZE, diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index b1bb9c78..9d97e327 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -26,15 +26,11 @@ # define GC_BUILD #endif -#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) +#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \ + && !defined(_GNU_SOURCE) /* Can't test LINUX, since this must be defined before other includes. */ -# if !defined(__native_client__) -# include -# endif -# ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -# endif -#endif /* __linux__ */ +# define _GNU_SOURCE 1 +#endif #if (defined(DGUX) && defined(GC_THREADS) || defined(DGUX386_THREADS) \ || defined(GC_DGUX386_THREADS)) && !defined(_USING_POSIX4A_DRAFT10) -- cgit v1.2.1 From be522b1f8b6eaa6b355e86f567fb7cf5b10f6788 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 22 Apr 2011 11:54:12 +0000 Subject: 2011-04-22 Ivan Maidanski * os_dep.c (GC_get_stack_base): Implement for Android (same as for Linux). * pthread_support.c (GC_get_nprocs): Return 1 (instead of -1) if failed to open "stat" file (not to issue a warning twice); update the comment. * pthread_support.c (GC_thr_init): Call sysconf() on Android to get the number of CPUs. --HG-- branch : bdwgc --- ChangeLog | 10 ++++++++++ os_dep.c | 2 +- pthread_support.c | 20 +++++++++++--------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80f1b0cd..b57c19e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-04-22 Ivan Maidanski + + * os_dep.c (GC_get_stack_base): Implement for Android (same as + for Linux). + * pthread_support.c (GC_get_nprocs): Return 1 (instead of -1) if + failed to open "stat" file (not to issue a warning twice); update + the comment. + * pthread_support.c (GC_thr_init): Call sysconf() on Android to + get the number of CPUs. + 2011-04-21 Ivan Maidanski * include/private/gc_priv.h (_GNU_SOURCE): Revert one of the diff --git a/os_dep.c b/os_dep.c index 75f9c7a7..a562b79c 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1222,7 +1222,7 @@ GC_INNER word GC_page_size = 0; } #endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */ -#if defined(GC_LINUX_THREADS) && !defined(NACL) +#if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) && !defined(NACL) # include /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */ diff --git a/pthread_support.c b/pthread_support.c index 0f1d9242..16d0dc9a 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -708,7 +708,7 @@ STATIC void GC_remove_all_threads_but_me(void) #endif /* IA64 */ #if defined(GC_LINUX_THREADS) && !defined(NACL) - /* Return the number of processors, or i<= 0 if it can't be determined. */ + /* Return the number of processors. */ STATIC int GC_get_nprocs(void) { /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ @@ -732,16 +732,18 @@ STATIC void GC_remove_all_threads_but_me(void) f = open("/proc/stat", O_RDONLY); if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) { WARN("Couldn't read /proc/stat\n", 0); - return -1; + return 1; /* assume an uniprocessor */ } + close(f); + for (i = 0; i < len - 100; ++i) { if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c' && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') { - int cpu_no = atoi(stat_buf + i + 4); - if (cpu_no >= result) result = cpu_no + 1; + int cpu_no = atoi(&stat_buf[i + 4]); + if (cpu_no >= result) + result = cpu_no + 1; } } - close(f); return result; } #endif /* GC_LINUX_THREADS && !NACL */ @@ -849,7 +851,7 @@ STATIC void GC_fork_child_proc(void) /* */ int numCpus; struct dg_sys_info_pm_info pm_sysinfo; - int status =0; + int status = 0; status = dg_sys_info((long int *) &pm_sysinfo, DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION); @@ -945,7 +947,7 @@ GC_INNER void GC_thr_init(void) GC_nprocs = pthread_num_processors_np(); # elif defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \ || defined(GC_SOLARIS_THREADS) || defined(GC_GNU_THREADS) \ - || defined(NACL) + || defined(PLATFORM_ANDROID) || defined(NACL) GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN); if (GC_nprocs <= 0) GC_nprocs = 1; # elif defined(GC_IRIX_THREADS) @@ -960,7 +962,7 @@ GC_INNER void GC_thr_init(void) } if (GC_nprocs <= 0) { WARN("GC_get_nprocs() returned %" GC_PRIdPTR "\n", GC_nprocs); - GC_nprocs = 2; + GC_nprocs = 2; /* assume dual-core */ # ifdef PARALLEL_MARK GC_markers = 1; # endif @@ -1844,4 +1846,4 @@ GC_INNER void GC_notify_all_marker(void) #endif /* PARALLEL_MARK */ -#endif /* GC_LINUX_THREADS and friends */ +#endif /* GC_PTHREADS */ -- cgit v1.2.1 From 781eb1a1cf9478b803b285eaf9bd7ba005ba8b1e Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 22 Apr 2011 21:40:16 +0000 Subject: 2011-04-22 Ivan Maidanski * os_dep.c (GC_get_maps): Always close the file. * pthread_support.c (GC_get_nprocs): Ditto. * os_dep.c (READ): Define similarly across the file (without parameters). * pthread_support.c (GC_get_nprocs): Use signed int type for "i" and "len" local variables (since read() may return -1). * include/private/gc_pmark.h (LONG_MULT): Add prefix/suffix double underscore; add "volatile" for asm. * include/private/gc_pmark.h (LONG_MULT): Add missing parentheses. * include/private/gc_priv.h (OR_WORD): Ditto. * include/private/gc_priv.h (OR_WORD): Remove unnecessary brackets and ';' symbol. --HG-- branch : bdwgc --- ChangeLog | 16 ++++++++++++++++ include/private/gc_pmark.h | 11 +++++------ include/private/gc_priv.h | 30 ++++++++++++++---------------- os_dep.c | 7 +++++-- pthread_support.c | 5 +++-- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index b57c19e6..a61a85ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-04-22 Ivan Maidanski + + * os_dep.c (GC_get_maps): Always close the file. + * pthread_support.c (GC_get_nprocs): Ditto. + * os_dep.c (READ): Define similarly across the file (without + parameters). + * pthread_support.c (GC_get_nprocs): Use signed int type for "i" + and "len" local variables (since read() may return -1). + * include/private/gc_pmark.h (LONG_MULT): Add prefix/suffix + double underscore; add "volatile" for asm. + * include/private/gc_pmark.h (LONG_MULT): Add missing + parentheses. + * include/private/gc_priv.h (OR_WORD): Ditto. + * include/private/gc_priv.h (OR_WORD): Remove unnecessary brackets + and ';' symbol. + 2011-04-22 Ivan Maidanski * os_dep.c (GC_get_stack_base): Implement for Android (same as diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index a24dda83..05b082b4 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -189,20 +189,20 @@ exit_label: ; \ # define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \ { \ word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(bit_no); \ - \ OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(bit_no), \ exit_label); \ } -#endif +#endif /* USE_MARK_BITS */ #if defined(I386) && defined(__GNUC__) # define LONG_MULT(hprod, lprod, x, y) { \ - asm("mull %2" : "=a"(lprod), "=d"(hprod) : "g"(y), "0"(x)); \ + __asm__ __volatile__("mull %2" : "=a"(lprod), "=d"(hprod) \ + : "g"(y), "0"(x)); \ } #else /* No in-line X86 assembly code */ # define LONG_MULT(hprod, lprod, x, y) { \ - unsigned long long prod = (unsigned long long)x \ - * (unsigned long long)y; \ + unsigned long long prod = (unsigned long long)(x) \ + * (unsigned long long)(y); \ hprod = prod >> 32; \ lprod = (unsigned32)prod; \ } @@ -216,7 +216,6 @@ exit_label: ; \ { \ char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \ char mark_byte = *mark_byte_addr; \ - \ if (mark_byte) goto exit_label; \ *mark_byte_addr = 1; \ } diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 9d97e327..7168c147 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -787,7 +787,7 @@ typedef word page_hash_table[PHT_SIZE]; # if defined(THREADS) && defined(MPROTECT_VDB) # include "atomic_ops.h" # endif -#endif +#endif /* !PARALLEL_MARK */ /* We maintain layout maps for heap blocks containing objects of a given */ /* size. Each entry in this map describes a byte offset and has the */ @@ -1338,10 +1338,9 @@ struct GC_traced_stack_sect_s { /* Set mark bit correctly, even if mark bits may be concurrently */ /* accessed. */ #ifdef PARALLEL_MARK -# define OR_WORD(addr, bits) \ - { AO_or((volatile AO_t *)(addr), (AO_t)bits); } +# define OR_WORD(addr, bits) AO_or((volatile AO_t *)(addr), (AO_t)(bits)) #else -# define OR_WORD(addr, bits) *(addr) |= (bits) +# define OR_WORD(addr, bits) (void)(*(addr) |= (bits)) #endif /* Mark bit operations */ @@ -1355,16 +1354,15 @@ struct GC_traced_stack_sect_s { #ifdef USE_MARK_BYTES # define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) -# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 1 -# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 0 -#else /* !USE_MARK_BYTES */ -# define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ - >> (modWORDSZ(n))) & (word)1) +# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 1) +# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 0) +#else +# define mark_bit_from_hdr(hhdr,n) \ + (((hhdr)->hb_marks[divWORDSZ(n)] >> modWORDSZ(n)) & (word)1) # define set_mark_bit_from_hdr(hhdr,n) \ - OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ - (word)1 << modWORDSZ(n)) -# define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ - &= ~((word)1 << modWORDSZ(n)) + OR_WORD((hhdr)->hb_marks+divWORDSZ(n), (word)1 << modWORDSZ(n)) +# define clear_mark_bit_from_hdr(hhdr,n) \ + ((hhdr)->hb_marks[divWORDSZ(n)] &= ~((word)1 << modWORDSZ(n))) #endif /* !USE_MARK_BYTES */ #ifdef MARK_BIT_PER_OBJ @@ -1381,8 +1379,8 @@ struct GC_traced_stack_sect_s { # define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz) # define IF_PER_OBJ(x) # define FINAL_MARK_BIT(sz) \ - ((sz) > MAXOBJBYTES? MARK_BITS_PER_HBLK \ - : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) + ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \ + : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) #endif /* Important internal collector routines */ @@ -1628,7 +1626,7 @@ GC_INNER void GC_freehblk(struct hblk * p); /* Misc GC: */ GC_INNER GC_bool GC_expand_hp_inner(word n); -GC_INNER void GC_start_reclaim(int abort_if_found); +GC_INNER void GC_start_reclaim(GC_bool abort_if_found); /* Restore unmarked objects to free */ /* lists, or (if abort_if_found is */ /* TRUE) report them. */ diff --git a/os_dep.c b/os_dep.c index a562b79c..db3fd2b3 100644 --- a/os_dep.c +++ b/os_dep.c @@ -264,10 +264,13 @@ GC_INNER char * GC_get_maps(void) maps_size = 0; do { result = GC_repeat_read(f, maps_buf, maps_buf_sz-1); - if (result <= 0) return 0; + if (result <= 0) + break; maps_size += result; } while (result == maps_buf_sz-1); close(f); + if (result <= 0) + return 0; # ifdef THREADS if (maps_size > old_maps_size) { if (GC_print_stats) @@ -3662,7 +3665,7 @@ GC_INNER void GC_dirty_init(void) GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) {} -# define READ(fd,buf,nbytes) read(fd, buf, nbytes) +#define READ read GC_INNER void GC_read_dirty(void) { diff --git a/pthread_support.c b/pthread_support.c index 16d0dc9a..d9c3792c 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -727,13 +727,14 @@ STATIC void GC_remove_all_threads_but_me(void) /* Some old kernels only have a single "cpu nnnn ..." */ /* entry in /proc/stat. We identify those as */ /* uniprocessors. */ - size_t i, len = 0; + int i, len; f = open("/proc/stat", O_RDONLY); - if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) { + if (f < 0) { WARN("Couldn't read /proc/stat\n", 0); return 1; /* assume an uniprocessor */ } + len = STAT_READ(f, stat_buf, STAT_BUF_SIZE); close(f); for (i = 0; i < len - 100; ++i) { -- cgit v1.2.1 From 69833c7f4a465d334dc8f55fc9105538a51904e2 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 23 Apr 2011 08:51:53 +0000 Subject: 2011-04-23 Ivan Maidanski * mark.c (GC_clear_hdr_marks): Don't test USE_MARK_BYTES. * extra/setjmp_t.c (main): Don't test USE_MARK_BITS. * include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Ditto. * include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Remove "mark_byte" local variable. * include/private/gc_pmark.h (OR_WORD_EXIT_IF_SET): Add a comment about that AO_or() is not used by GC unless USE_MARK_BITS explicitly set. * include/private/gc_priv.h (OR_WORD): Ditto. * include/private/gc_pmark.h (INCR_MARKS): Remove trailing ';', add parentheses. * include/private/gc_priv.h (ONES): Define before use by MAKE_COOLER. * include/private/gc_priv.h (MARK_BITS_SZ): Define where used. * include/private/gc_priv.h (OR_WORD): Don't define if USE_MARK_BYTES. * include/private/gcconfig.h (USE_MARK_BYTES); Remove duplicate definition; simplify expression. --HG-- branch : bdwgc --- ChangeLog | 21 ++++++++++++++++ extra/setjmp_t.c | 2 +- include/private/gc_pmark.h | 61 ++++++++++++++++++++++------------------------ include/private/gc_priv.h | 37 +++++++++++++--------------- include/private/gcconfig.h | 21 +++++----------- mark.c | 12 +++------ 6 files changed, 77 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index a61a85ff..8fa4db2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-04-23 Ivan Maidanski + + * mark.c (GC_clear_hdr_marks): Don't test USE_MARK_BYTES. + * extra/setjmp_t.c (main): Don't test USE_MARK_BITS. + * include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Ditto. + * include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Remove + "mark_byte" local variable. + * include/private/gc_pmark.h (OR_WORD_EXIT_IF_SET): Add a comment + about that AO_or() is not used by GC unless USE_MARK_BITS + explicitly set. + * include/private/gc_priv.h (OR_WORD): Ditto. + * include/private/gc_pmark.h (INCR_MARKS): Remove trailing ';', + add parentheses. + * include/private/gc_priv.h (ONES): Define before use by + MAKE_COOLER. + * include/private/gc_priv.h (MARK_BITS_SZ): Define where used. + * include/private/gc_priv.h (OR_WORD): Don't define if + USE_MARK_BYTES. + * include/private/gcconfig.h (USE_MARK_BYTES); Remove duplicate + definition; simplify expression. + 2011-04-22 Ivan Maidanski * os_dep.c (GC_get_maps): Always close the file. diff --git a/extra/setjmp_t.c b/extra/setjmp_t.c index 5f4519b2..0952fb03 100644 --- a/extra/setjmp_t.c +++ b/extra/setjmp_t.c @@ -112,7 +112,7 @@ int main(void) printf("\tUsing one mark "); # if defined(USE_MARK_BYTES) printf("byte"); -# elif defined(USE_MARK_BITS) +# else printf("bit"); # endif printf(" per "); diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index 05b082b4..d99e0b7f 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -164,9 +164,19 @@ exit_label: ; \ } /* Set mark bit, exit if it was already set. */ - -#ifdef USE_MARK_BITS +#ifdef USE_MARK_BYTES + /* There is a race here, and we may set */ + /* the bit twice in the concurrent case. This can result in the */ + /* object being pushed twice. But that's only a performance issue. */ +# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \ + { \ + char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \ + if (*mark_byte_addr) goto exit_label; \ + *mark_byte_addr = 1; \ + } +#else # ifdef PARALLEL_MARK + /* This is used only if we explicitly set USE_MARK_BITS. */ /* The following may fail to exit even if the bit was already set. */ /* For our uses, that's benign: */ # define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ @@ -192,40 +202,13 @@ exit_label: ; \ OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(bit_no), \ exit_label); \ } -#endif /* USE_MARK_BITS */ - -#if defined(I386) && defined(__GNUC__) -# define LONG_MULT(hprod, lprod, x, y) { \ - __asm__ __volatile__("mull %2" : "=a"(lprod), "=d"(hprod) \ - : "g"(y), "0"(x)); \ - } -#else /* No in-line X86 assembly code */ -# define LONG_MULT(hprod, lprod, x, y) { \ - unsigned long long prod = (unsigned long long)(x) \ - * (unsigned long long)(y); \ - hprod = prod >> 32; \ - lprod = (unsigned32)prod; \ - } -#endif - -#ifdef USE_MARK_BYTES - /* There is a race here, and we may set */ - /* the bit twice in the concurrent case. This can result in the */ - /* object being pushed twice. But that's only a performance issue. */ -# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \ - { \ - char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \ - char mark_byte = *mark_byte_addr; \ - if (mark_byte) goto exit_label; \ - *mark_byte_addr = 1; \ - } -#endif /* USE_MARK_BYTES */ +#endif /* !USE_MARK_BYTES */ #ifdef PARALLEL_MARK # define INCR_MARKS(hhdr) \ - AO_store(&(hhdr -> hb_n_marks), AO_load(&(hhdr -> hb_n_marks))+1); + AO_store(&hhdr->hb_n_marks, AO_load(&hhdr->hb_n_marks) + 1) #else -# define INCR_MARKS(hhdr) ++(hhdr -> hb_n_marks) +# define INCR_MARKS(hhdr) (void)(++hhdr->hb_n_marks) #endif #ifdef ENABLE_TRACE @@ -238,6 +221,20 @@ exit_label: ; \ # define TRACE_TARGET(source, cmd) #endif +#if defined(I386) && defined(__GNUC__) +# define LONG_MULT(hprod, lprod, x, y) { \ + __asm__ __volatile__("mull %2" : "=a"(lprod), "=d"(hprod) \ + : "g"(y), "0"(x)); \ + } +#else +# define LONG_MULT(hprod, lprod, x, y) { \ + unsigned long long prod = (unsigned long long)(x) \ + * (unsigned long long)(y); \ + hprod = prod >> 32; \ + lprod = (unsigned32)prod; \ + } +#endif /* !I386 */ + /* If the mark bit corresponding to current is not set, set it, and */ /* push the contents of the object on the mark stack. Current points */ /* to the beginning of the object. We rely on the fact that the */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 7168c147..ad6699e9 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -172,6 +172,8 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # include "gc_locks.h" #endif +#define ONES ((word)(signed_word)(-1)) + # ifdef STACK_GROWS_DOWN # define COOLER_THAN > # define HOTTER_THAN < @@ -579,7 +581,6 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; #define WORDSZ ((word)CPP_WORDSZ) #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 */ #if GRANULE_BYTES == 8 @@ -768,17 +769,6 @@ typedef word page_hash_table[PHT_SIZE]; /* initial group of mark bits, and it is safe */ /* to allocate smaller header for large objects. */ -# ifdef USE_MARK_BYTES -# define MARK_BITS_SZ (MARK_BITS_PER_HBLK + 1) - /* Unlike the other case, this is in units of bytes. */ - /* Since we force doubleword alignment, we need at most one */ - /* mark bit per 2 words. But we do allocate and set one */ - /* extra mark bit to avoid an explicit check for the */ - /* partial object at the end of each block. */ -# else -# define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ + 1) -# endif - #ifdef PARALLEL_MARK # include "atomic_ops.h" typedef AO_t counter_t; @@ -860,6 +850,12 @@ struct hblkhdr { /* Without parallel marking, the count */ /* is accurate. */ # ifdef USE_MARK_BYTES +# define MARK_BITS_SZ (MARK_BITS_PER_HBLK + 1) + /* Unlike the other case, this is in units of bytes. */ + /* Since we force doubleword alignment, we need at most one */ + /* mark bit per 2 words. But we do allocate and set one */ + /* extra mark bit to avoid an explicit check for the */ + /* partial object at the end of each block. */ union { char _hb_marks[MARK_BITS_SZ]; /* The i'th byte is 1 if the object */ @@ -872,6 +868,7 @@ struct hblkhdr { } _mark_byte_union; # define hb_marks _mark_byte_union._hb_marks # else +# define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ + 1) word hb_marks[MARK_BITS_SZ]; # endif /* !USE_MARK_BYTES */ }; @@ -1335,14 +1332,6 @@ struct GC_traced_stack_sect_s { /* with it. Only those corresponding to the beginning of an */ /* object are used. */ -/* Set mark bit correctly, even if mark bits may be concurrently */ -/* accessed. */ -#ifdef PARALLEL_MARK -# define OR_WORD(addr, bits) AO_or((volatile AO_t *)(addr), (AO_t)(bits)) -#else -# define OR_WORD(addr, bits) (void)(*(addr) |= (bits)) -#endif - /* Mark bit operations */ /* @@ -1357,6 +1346,14 @@ struct GC_traced_stack_sect_s { # define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 1) # define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n] = 0) #else +/* Set mark bit correctly, even if mark bits may be concurrently */ +/* accessed. */ +# ifdef PARALLEL_MARK + /* This is used only if we explicitly set USE_MARK_BITS. */ +# define OR_WORD(addr, bits) AO_or((volatile AO_t *)(addr), (AO_t)(bits)) +# else +# define OR_WORD(addr, bits) (void)(*(addr) |= (bits)) +# endif # define mark_bit_from_hdr(hhdr,n) \ (((hhdr)->hb_marks[divWORDSZ(n)] >> modWORDSZ(n)) & (word)1) # define set_mark_bit_from_hdr(hhdr,n) \ diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index ec5e96ed..894f31d6 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -1576,15 +1576,8 @@ # define ALIGNMENT 4 # endif # if !defined(GC_HPUX_THREADS) && !defined(GC_LINUX_THREADS) \ - && !defined(OPENBSD) -# ifndef LINUX /* For now. */ -# define MPROTECT_VDB -# endif -# else -# ifdef PARALLEL_MARK -# define USE_MARK_BYTES - /* Minimize compare-and-swap usage. */ -# endif + && !defined(OPENBSD) && !defined(LINUX) /* For now. */ +# define MPROTECT_VDB # endif # define STACK_GROWS_UP # ifdef HPUX @@ -2515,12 +2508,10 @@ # define IF_CANCEL(x) /* empty */ #endif -#if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) -# if defined(THREADS) && defined(PARALLEL_MARK) -# define USE_MARK_BYTES -# else -# define USE_MARK_BITS -# endif +#if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) \ + && defined(PARALLEL_MARK) + /* Minimize compare-and-swap usage. */ +# define USE_MARK_BYTES #endif #if defined(MSWINCE) && !defined(__CEGCC__) && !defined(NO_GETENV) diff --git a/mark.c b/mark.c index deb3cdf7..99fa4327 100644 --- a/mark.c +++ b/mark.c @@ -144,14 +144,8 @@ GC_INNER GC_bool GC_collection_in_progress(void) GC_INNER void GC_clear_hdr_marks(hdr *hhdr) { size_t last_bit = FINAL_MARK_BIT(hhdr -> hb_sz); - -# ifdef USE_MARK_BYTES - BZERO(hhdr -> hb_marks, MARK_BITS_SZ); - hhdr -> hb_marks[last_bit] = 1; -# else - BZERO(hhdr -> hb_marks, MARK_BITS_SZ*sizeof(word)); - set_mark_bit_from_hdr(hhdr, last_bit); -# endif + BZERO(hhdr -> hb_marks, sizeof(hhdr->hb_marks)); + set_mark_bit_from_hdr(hhdr, last_bit); hhdr -> hb_n_marks = 0; } @@ -1570,7 +1564,7 @@ GC_INNER void GC_push_all_stack(ptr_t bottom, ptr_t top) qcontents = (q)[3]; \ GC_PUSH_ONE_HEAP(qcontents, (q)+3); } # endif -#endif +#endif /* !USE_MARK_BYTES && MARK_BIT_PER_GRANULE */ #ifdef USE_PUSH_MARKED_ACCELERATORS /* Push all objects reachable from marked objects in the given block */ -- cgit v1.2.1 From 6e093e43923d38b9f6a228da3a2c7db11304966c Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 23 Apr 2011 10:03:59 +0000 Subject: 2011-04-23 Ivan Maidanski * include/private/gc_locks.h (WIN32_LEAN_AND_MEAN, NOSERVICE): Define before including windows.h. * include/private/gc_priv.h (WIN32_LEAN_AND_MEAN, NOSERVICE): Ditto. * include/private/thread_local_alloc.h (WIN32_LEAN_AND_MEAN, NOSERVICE): Ditto. * include/private/gc_priv.h (CLOCKS_PER_SEC): Reformat the comment. * include/private/gc_priv.h (MS_TIME_DIFF): Avoid floating-point arithmetics; add a comment. --HG-- branch : bdwgc --- ChangeLog | 13 +++++ include/private/gc_locks.h | 4 ++ include/private/gc_priv.h | 95 +++++++++++++++++++----------------- include/private/thread_local_alloc.h | 4 ++ 4 files changed, 70 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8fa4db2c..2d240fb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-04-23 Ivan Maidanski + + * include/private/gc_locks.h (WIN32_LEAN_AND_MEAN, NOSERVICE): + Define before including windows.h. + * include/private/gc_priv.h (WIN32_LEAN_AND_MEAN, NOSERVICE): + Ditto. + * include/private/thread_local_alloc.h (WIN32_LEAN_AND_MEAN, + NOSERVICE): Ditto. + * include/private/gc_priv.h (CLOCKS_PER_SEC): Reformat the + comment. + * include/private/gc_priv.h (MS_TIME_DIFF): Avoid floating-point + arithmetics; add a comment. + 2011-04-23 Ivan Maidanski * mark.c (GC_clear_hdr_marks): Don't test USE_MARK_BYTES. diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h index f5119b89..b38384cf 100644 --- a/include/private/gc_locks.h +++ b/include/private/gc_locks.h @@ -52,6 +52,10 @@ # endif # if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# define NOSERVICE # include # define NO_THREAD (DWORD)(-1) GC_EXTERN DWORD GC_lock_holder; diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index ad6699e9..79bb0084 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -312,51 +312,54 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /*********************************/ #ifdef BSD_TIME -# undef CLOCK_TYPE -# undef GET_TIME -# undef MS_TIME_DIFF -# define CLOCK_TYPE struct timeval -# define GET_TIME(x) { struct rusage rusage; \ - getrusage (RUSAGE_SELF, &rusage); \ - x = rusage.ru_utime; } -# define MS_TIME_DIFF(a,b) \ - ((unsigned long)((double) (a.tv_sec - b.tv_sec) * 1000.0 \ - + (double) (a.tv_usec - b.tv_usec) / 1000.0)) -#else /* !BSD_TIME */ -# if defined(MSWIN32) || defined(MSWINCE) -# include -# include -# define CLOCK_TYPE DWORD -# define GET_TIME(x) x = GetTickCount() -# define MS_TIME_DIFF(a,b) ((long)((a)-(b))) -# else /* !MSWIN32, !MSWINCE, !BSD_TIME */ -# include -# if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) - clock_t clock(void); /* Not in time.h, where it belongs */ -# endif -# if defined(FREEBSD) && !defined(CLOCKS_PER_SEC) -# include -# define CLOCKS_PER_SEC CLK_TCK -# endif -# if !defined(CLOCKS_PER_SEC) -# define CLOCKS_PER_SEC 1000000 -/* - * This is technically a bug in the implementation. ANSI requires that - * CLOCKS_PER_SEC be defined. But at least under SunOS4.1.1, it isn't. - * Also note that the combination of ANSI C and POSIX is incredibly gross - * here. The type clock_t is used by both clock() and times(). But on - * some machines these use different notions of a clock tick, CLOCKS_PER_SEC - * seems to apply only to clock. Hence we use it here. On many machines, - * including SunOS, clock actually uses units of microseconds (which are - * not really clock ticks). - */ -# endif -# define CLOCK_TYPE clock_t -# define GET_TIME(x) x = clock() -# define MS_TIME_DIFF(a,b) ((unsigned long) \ - (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC)) -# endif /* !MSWIN32 */ -#endif /* !BSD_TIME */ +# undef CLOCK_TYPE +# undef GET_TIME +# undef MS_TIME_DIFF +# define CLOCK_TYPE struct timeval +# define GET_TIME(x) { struct rusage rusage; \ + getrusage (RUSAGE_SELF, &rusage); \ + x = rusage.ru_utime; } +# define MS_TIME_DIFF(a,b) ((unsigned long)(a.tv_sec - b.tv_sec) * 1000 \ + + (unsigned long)(a.tv_usec - b.tv_usec) / 1000) +#elif defined(MSWIN32) || defined(MSWINCE) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# define NOSERVICE +# include +# include +# define CLOCK_TYPE DWORD +# define GET_TIME(x) x = GetTickCount() +# define MS_TIME_DIFF(a,b) ((long)((a)-(b))) +#else /* !MSWIN32, !MSWINCE, !BSD_TIME */ +# include +# if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) + clock_t clock(void); /* Not in time.h, where it belongs */ +# endif +# if defined(FREEBSD) && !defined(CLOCKS_PER_SEC) +# include +# define CLOCKS_PER_SEC CLK_TCK +# endif +# if !defined(CLOCKS_PER_SEC) +# define CLOCKS_PER_SEC 1000000 + /* This is technically a bug in the implementation. */ + /* ANSI requires that CLOCKS_PER_SEC be defined. But at least */ + /* under SunOS 4.1.1, it isn't. Also note that the combination of */ + /* ANSI C and POSIX is incredibly gross here. The type clock_t */ + /* is used by both clock() and times(). But on some machines */ + /* these use different notions of a clock tick, CLOCKS_PER_SEC */ + /* seems to apply only to clock. Hence we use it here. On many */ + /* machines, including SunOS, clock actually uses units of */ + /* microseconds (which are not really clock ticks). */ +# endif +# define CLOCK_TYPE clock_t +# define GET_TIME(x) x = clock() +# define MS_TIME_DIFF(a,b) (CLOCKS_PER_SEC % 1000 == 0 ? \ + (unsigned long)((a) - (b)) / (unsigned long)(CLOCKS_PER_SEC / 1000) \ + : ((unsigned long)((a) - (b)) * 1000) / (unsigned long)CLOCKS_PER_SEC) + /* Avoid using double type since some targets (like ARM) might */ + /* require -lm option for double-to-long conversion. */ +#endif /* !BSD_TIME && !MSWIN32 */ /* We use bzero and bcopy internally. They may not be available. */ # if defined(SPARC) && defined(SUNOS4) @@ -852,7 +855,7 @@ struct hblkhdr { # ifdef USE_MARK_BYTES # define MARK_BITS_SZ (MARK_BITS_PER_HBLK + 1) /* Unlike the other case, this is in units of bytes. */ - /* Since we force doubleword alignment, we need at most one */ + /* Since we force double-word alignment, we need at most one */ /* mark bit per 2 words. But we do allocate and set one */ /* extra mark bit to avoid an explicit check for the */ /* partial object at the end of each block. */ diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index ab14fdbf..20995a8c 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -106,6 +106,10 @@ typedef struct thread_local_freelists { # define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef void * GC_key_t; # elif defined(USE_WIN32_SPECIFIC) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# define NOSERVICE # include # define GC_getspecific TlsGetValue # define GC_setspecific(key, v) !TlsSetValue(key, v) -- cgit v1.2.1 From 4d6b3f0b5fc48649d6c9c02775078964df11f2f6 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 24 Apr 2011 06:37:23 +0000 Subject: 2011-04-24 Ivan Maidanski * mach_dep.c (NO_GETCONTEXT): Move to gcconfig.h. * os_dep.c (GC_write_fault_handler): Don't include ucontext.h if NO_GETCONTEXT. * include/private/gcconfig.h (GETPAGESIZE): Define as a sysconf call for Android. --HG-- branch : bdwgc --- ChangeLog | 8 ++++++++ include/private/gcconfig.h | 10 +++++++++- mach_dep.c | 8 -------- os_dep.c | 5 ++++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d240fb5..d2acb1c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-04-24 Ivan Maidanski + + * mach_dep.c (NO_GETCONTEXT): Move to gcconfig.h. + * os_dep.c (GC_write_fault_handler): Don't include ucontext.h if + NO_GETCONTEXT. + * include/private/gcconfig.h (GETPAGESIZE): Define as a sysconf + call for Android. + 2011-04-23 Ivan Maidanski * include/private/gc_locks.h (WIN32_LEAN_AND_MEAN, NOSERVICE): diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 894f31d6..1428d5b7 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2293,7 +2293,7 @@ # define DATAEND (ptr_t)(end) #endif -#if defined(SVR4) && !defined(GETPAGESIZE) +#if (defined(SVR4) || defined(PLATFORM_ANDROID)) && !defined(GETPAGESIZE) # include # define GETPAGESIZE() sysconf(_SC_PAGESIZE) #endif @@ -2404,6 +2404,14 @@ # define DEFAULT_VDB #endif +#if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ + || defined(OPENBSD) || defined(ARM32) \ + || defined(MIPS) || defined(AVR32))) \ + || (defined(LINUX) && defined(SPARC)) \ + || (defined(RTEMS) && defined(I386))) && !defined(NO_GETCONTEXT) +# define NO_GETCONTEXT +#endif + #ifndef PREFETCH # define PREFETCH(x) # define NO_PREFETCH diff --git a/mach_dep.c b/mach_dep.c index 416dec8a..19e688dd 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -171,14 +171,6 @@ asm static void PushMacRegisters() # undef HAVE_PUSH_REGS #endif -#if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ - || defined(OPENBSD) || defined(ARM32) \ - || defined(MIPS) || defined(AVR32))) \ - || (defined(LINUX) && defined(SPARC)) \ - || (defined(RTEMS) && defined(I386))) && !defined(NO_GETCONTEXT) -# define NO_GETCONTEXT -#endif - #if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE) # include # ifndef NO_GETCONTEXT diff --git a/os_dep.c b/os_dep.c index db3fd2b3..17ba79db 100644 --- a/os_dep.c +++ b/os_dep.c @@ -801,6 +801,7 @@ GC_INNER word GC_page_size = 0; { # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP) GC_page_size = GETPAGESIZE(); + if (!GC_page_size) ABORT("getpagesize() failed"); # else /* It's acceptable to fake it. */ GC_page_size = HBLKSIZE; @@ -3114,7 +3115,9 @@ STATIC void GC_default_push_other_roots(void) # elif defined(SUNOS5SIGS) # define CODE_OK (si -> si_code == SEGV_ACCERR) # endif -# include +# ifndef NO_GETCONTEXT +# include +# endif /*ARGSUSED*/ STATIC void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc) # else -- cgit v1.2.1 From 76f0d632970c9b27e3110beed188e618fe0afc52 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 24 Apr 2011 13:09:21 +0000 Subject: 2011-04-24 Ivan Maidanski * pthread_support.c (GC_get_nprocs): Don't define for Android. * pthread_support.c (GC_dummy_thread_local): Don't test GC_LINUX_THREADS. * include/gc_config_macros.h (GC_ADD_CALLER, GC_RETURN_ADDR): Define for Android. --HG-- branch : bdwgc --- ChangeLog | 8 ++++++++ include/gc_config_macros.h | 4 ++-- pthread_support.c | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2acb1c4..bfbf9de7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-04-24 Ivan Maidanski + + * pthread_support.c (GC_get_nprocs): Don't define for Android. + * pthread_support.c (GC_dummy_thread_local): Don't test + GC_LINUX_THREADS. + * include/gc_config_macros.h (GC_ADD_CALLER, GC_RETURN_ADDR): + Define for Android. + 2011-04-24 Ivan Maidanski * mach_dep.c (NO_GETCONTEXT): Move to gcconfig.h. diff --git a/include/gc_config_macros.h b/include/gc_config_macros.h index 030218e4..a27f8dd7 100644 --- a/include/gc_config_macros.h +++ b/include/gc_config_macros.h @@ -273,8 +273,8 @@ /* This may also be desirable if it is possible but expensive to */ /* retrieve the call chain. */ #if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) \ - || defined(__FreeBSD__) || defined(__DragonFly__)) \ - && !defined(GC_CAN_SAVE_CALL_STACKS) + || defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(PLATFORM_ANDROID)) && !defined(GC_CAN_SAVE_CALL_STACKS) # define GC_ADD_CALLER # if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) /* gcc knows how to retrieve return address, but we don't know */ diff --git a/pthread_support.c b/pthread_support.c index d9c3792c..2feeac3e 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -707,7 +707,7 @@ STATIC void GC_remove_all_threads_but_me(void) } #endif /* IA64 */ -#if defined(GC_LINUX_THREADS) && !defined(NACL) +#if defined(GC_LINUX_THREADS) && !defined(PLATFORM_ANDROID) && !defined(NACL) /* Return the number of processors. */ STATIC int GC_get_nprocs(void) { @@ -883,7 +883,7 @@ STATIC void GC_fork_child_proc(void) } #endif /* GC_DARWIN_THREADS || ... */ -#if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR) +#ifdef INCLUDE_LINUX_THREAD_DESCR __thread int GC_dummy_thread_local; #endif -- cgit v1.2.1 From 70053710843e46d78018d85aa5e586678c755c7c Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 26 Apr 2011 10:47:03 +0000 Subject: 2011-04-26 Ivan Maidanski * alloc.c: Don't include sys/types.h for ArmCC. * dyn_load.c: Ditto. * os_dep.c: Ditto. * mach_dep.c (_setjmp, _longjmp): Redirect to setjmp/longjmp for ArmCC. * mark.c (GC_noop): Define specially for ArmCC. * include/private/gc_priv.h (GC_noop): Ditto. * misc.c (GC_init): Don't test pointers comparison for ArmCC. * misc.c: Don't include unistd.h for ArmCC. * os_dep.c (pages_executable): Rename to GC_pages_executable; make STATIC. * os_dep.c (GC_unix_mmap_get_mem): Don't define for ArmCC. * ptr_chck.c (GC_is_visible): Explicitly cast (GC_DS_PER_OBJECT-GC_INDIR_PER_OBJ_BIAS) to word (to suppress a compiler warning). * include/private/gcconfig.h: Recognize __arm. * include/private/gcconfig.h (HBLKPTR): Define for ArmCC. * include/private/gcconfig.h (HBLKPTR): Add parentheses for "bytes" argument. --HG-- branch : bdwgc --- ChangeLog | 22 +++++++++++++++++ alloc.c | 4 ++- dyn_load.c | 2 +- include/private/gc_priv.h | 2 +- include/private/gcconfig.h | 43 +++++++++++++++----------------- mach_dep.c | 2 +- mark.c | 2 +- misc.c | 8 +++--- os_dep.c | 61 +++++++++++++++++++++++----------------------- ptr_chck.c | 2 +- 10 files changed, 85 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index bfbf9de7..a8b064c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-04-26 Ivan Maidanski + + * alloc.c: Don't include sys/types.h for ArmCC. + * dyn_load.c: Ditto. + * os_dep.c: Ditto. + * mach_dep.c (_setjmp, _longjmp): Redirect to setjmp/longjmp for + ArmCC. + * mark.c (GC_noop): Define specially for ArmCC. + * include/private/gc_priv.h (GC_noop): Ditto. + * misc.c (GC_init): Don't test pointers comparison for ArmCC. + * misc.c: Don't include unistd.h for ArmCC. + * os_dep.c (pages_executable): Rename to GC_pages_executable; + make STATIC. + * os_dep.c (GC_unix_mmap_get_mem): Don't define for ArmCC. + * ptr_chck.c (GC_is_visible): Explicitly cast + (GC_DS_PER_OBJECT-GC_INDIR_PER_OBJ_BIAS) to word (to suppress + a compiler warning). + * include/private/gcconfig.h: Recognize __arm. + * include/private/gcconfig.h (HBLKPTR): Define for ArmCC. + * include/private/gcconfig.h (HBLKPTR): Add parentheses for + "bytes" argument. + 2011-04-24 Ivan Maidanski * pthread_support.c (GC_get_nprocs): Don't define for Android. diff --git a/alloc.c b/alloc.c index 79fce2a2..df77781f 100644 --- a/alloc.c +++ b/alloc.c @@ -20,7 +20,9 @@ #include #if !defined(MACOS) && !defined(MSWINCE) # include -# include +# if !defined(__CC_ARM) +# include +# endif #endif /* diff --git a/dyn_load.c b/dyn_load.c index 50ab3ca2..9cc854db 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -29,7 +29,7 @@ * But then not much of anything is safe in the presence of dlclose. */ -#if !defined(MACOS) && !defined(_WIN32_WCE) +#if !defined(MACOS) && !defined(_WIN32_WCE) && !defined(__CC_ARM) # include #endif diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 79bb0084..9e34c769 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1920,7 +1920,7 @@ void GC_print_static_roots(void); #endif /* Make arguments appear live to compiler */ -#if defined(__BORLANDC__) || defined(__WATCOMC__) +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__CC_ARM) void GC_noop(void*, ...); #else # ifdef __DMC__ diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 1428d5b7..f541d7a7 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -70,7 +70,7 @@ # define I386 # define mach_type_known # endif -# if defined(__arm__) || defined(__thumb__) +# if defined(__arm) || defined(__arm__) || defined(__thumb__) # define ARM32 # if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) \ && !defined(DARWIN) && !defined(_WIN32) && !defined(__CEGCC__) @@ -186,8 +186,8 @@ # define mach_type_known # endif # if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \ - && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__) \ - && !defined(__DragonFly__) + && !defined(__OpenBSD__) && !defined(__NetBSD__) \ + && !defined(__FreeBSD__) && !defined(__DragonFly__) # define SPARC # define DRSNX # define mach_type_known @@ -250,7 +250,7 @@ # define IA64 # define mach_type_known # endif -# if defined(LINUX) && defined(__arm__) +# if defined(LINUX) && (defined(__arm) || defined(__arm__)) # define ARM32 # define mach_type_known # endif @@ -265,10 +265,6 @@ # define POWERPC # define mach_type_known # endif -# if defined(FREEBSD) && (defined(powerpc) || defined(__powerpc__)) -# define POWERPC -# define mach_type_known -# endif # if defined(LINUX) && defined(__mc68000__) # define M68K # define mach_type_known @@ -277,10 +273,6 @@ # define SPARC # define mach_type_known # endif -# if defined(LINUX) && defined(__arm__) -# define ARM32 -# define mach_type_known -# endif # if defined(LINUX) && defined(__sh__) # define SH # define mach_type_known @@ -293,9 +285,14 @@ # define M32R # define mach_type_known # endif +# if defined(FREEBSD) && (defined(powerpc) || defined(__powerpc__)) +# define POWERPC +# define mach_type_known +# endif # if defined(__alpha) || defined(__alpha__) # define ALPHA -# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) && !defined(FREEBSD) +# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) \ + && !defined(FREEBSD) # define OSF1 /* a.k.a Digital Unix */ # endif # define mach_type_known @@ -2652,18 +2649,18 @@ struct hblk; /* See gc_priv.h. */ # if defined(PCR) char * real_malloc(size_t bytes); -# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ +# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)(bytes) + GC_page_size) \ + GC_page_size-1) # elif defined(OS2) void * os2_alloc(size_t bytes); -# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \ - + GC_page_size) \ - + GC_page_size-1) +# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)(bytes) \ + + GC_page_size) + GC_page_size-1) # elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) \ || (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) \ - || (defined(SOLARIS) && !defined(USE_MMAP)) || defined(RTEMS) + || (defined(SOLARIS) && !defined(USE_MMAP)) || defined(RTEMS) \ + || defined(__CC_ARM) # define GET_MEM(bytes) HBLKPTR((size_t)calloc(1, \ - (size_t)bytes + GC_page_size) \ + (size_t)(bytes) + GC_page_size) \ + GC_page_size - 1) # elif defined(MSWIN32) || defined(CYGWIN32) ptr_t GC_win32_get_mem(GC_word bytes); @@ -2672,10 +2669,10 @@ # if defined(USE_TEMPORARY_MEMORY) Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory); # define GET_MEM(bytes) HBLKPTR( \ - GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \ - + GC_page_size-1) + GC_MacTemporaryNewPtr((bytes) + GC_page_size, true) \ + + GC_page_size-1) # else -# define GET_MEM(bytes) HBLKPTR(NewPtrClear(bytes + GC_page_size) \ +# define GET_MEM(bytes) HBLKPTR(NewPtrClear((bytes) + GC_page_size) \ + GC_page_size-1) # endif # elif defined(MSWINCE) @@ -2684,7 +2681,7 @@ # elif defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) void *GC_amiga_get_mem(size_t size); # define GET_MEM(bytes) HBLKPTR((size_t) \ - GC_amiga_get_mem((size_t)bytes + GC_page_size) \ + GC_amiga_get_mem((size_t)(bytes) + GC_page_size) \ + GC_page_size-1) # elif defined(SN_TARGET_PS3) void *ps3_get_mem(size_t size); diff --git a/mach_dep.c b/mach_dep.c index 19e688dd..969947c2 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -17,7 +17,7 @@ #include #include -#if defined(OS2) || defined(CX_UX) +#if defined(OS2) || defined(CX_UX) || defined(__CC_ARM) # define _setjmp(b) setjmp(b) # define _longjmp(b,v) longjmp(b,v) #endif diff --git a/mark.c b/mark.c index 99fa4327..8a3610dc 100644 --- a/mark.c +++ b/mark.c @@ -24,7 +24,7 @@ /* We put this here to minimize the risk of inlining. */ /*VARARGS*/ -#if defined(__BORLANDC__) || defined(__WATCOMC__) +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__CC_ARM) /*ARGSUSED*/ void GC_noop(void *p, ...) {} #else diff --git a/misc.c b/misc.c index ee6fa963..bd8730f0 100644 --- a/misc.c +++ b/misc.c @@ -951,9 +951,9 @@ GC_API void GC_CALL GC_init(void) GC_STATIC_ASSERT((word)(-1) > (word)0); /* word should be unsigned */ # endif -# if !defined(__BORLANDC__) /* Workaround for Borland C */ - GC_STATIC_ASSERT((ptr_t)(word)(-1) > (ptr_t)0); - /* Ptr_t comparisons should behave as unsigned comparisons. */ +# if !defined(__BORLANDC__) && !defined(__CC_ARM) /* Workaround */ + GC_STATIC_ASSERT((ptr_t)(word)(-1) > (ptr_t)0); + /* Ptr_t comparisons should behave as unsigned comparisons. */ # endif GC_STATIC_ASSERT((signed_word)(-1) < (signed_word)0); # ifndef GC_DISABLE_INCREMENTAL @@ -1245,7 +1245,7 @@ GC_API void GC_CALL GC_enable_incremental(void) # define WRITE(f, buf, len) (GC_set_files(), GC_write(f, buf, len)) #else -# if !defined(AMIGA) +# if !defined(AMIGA) && !defined(__CC_ARM) # include # endif diff --git a/os_dep.c b/os_dep.c index 17ba79db..a3e7a28e 100644 --- a/os_dep.c +++ b/os_dep.c @@ -47,7 +47,7 @@ #endif #if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \ - && !defined(MSWINCE) + && !defined(MSWINCE) && !defined(__CC_ARM) # include # if !defined(MSWIN32) # include @@ -131,12 +131,12 @@ #endif #if !defined(NO_EXECUTE_PERMISSION) - static GC_bool pages_executable = TRUE; + STATIC GC_bool GC_pages_executable = TRUE; #else - static GC_bool pages_executable = FALSE; + STATIC GC_bool GC_pages_executable = FALSE; #endif #define IGNORE_PAGES_EXECUTABLE 1 - /* Undefined on pages_executable real use. */ + /* Undefined on GC_pages_executable real use. */ #if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \ || !defined(SMALL_CONFIG)) @@ -2014,7 +2014,8 @@ void GC_register_data_segments(void) # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \ && !defined(MSWINCE) && !defined(MACOS) && !defined(DOS4GW) \ - && !defined(NONSTOP) && !defined(SN_TARGET_PS3) && !defined(RTEMS) + && !defined(NONSTOP) && !defined(SN_TARGET_PS3) && !defined(RTEMS) \ + && !defined(__CC_ARM) # define SBRK_ARG_T ptrdiff_t @@ -2061,7 +2062,7 @@ STATIC ptr_t GC_unix_mmap_get_mem(word bytes) if (bytes & (GC_page_size - 1)) ABORT("Bad GET_MEM arg"); result = mmap(last_addr, bytes, (PROT_READ | PROT_WRITE) - | (pages_executable ? PROT_EXEC : 0), + | (GC_pages_executable ? PROT_EXEC : 0), GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */); # undef IGNORE_PAGES_EXECUTABLE @@ -2166,7 +2167,7 @@ void * os2_alloc(size_t bytes) void * result; if (DosAllocMem(&result, bytes, (PAG_READ | PAG_WRITE | PAG_COMMIT) - | (pages_executable ? PAG_EXECUTE : 0)) + | (GC_pages_executable ? PAG_EXECUTE : 0)) != NO_ERROR) { return(0); } @@ -2245,8 +2246,8 @@ void * os2_alloc(size_t bytes) GetWriteWatch_alloc_flag | (MEM_COMMIT | MEM_RESERVE) | GC_mem_top_down, - pages_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE); + GC_pages_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE); # undef IGNORE_PAGES_EXECUTABLE } # endif /* !CYGWIN32 */ @@ -2312,8 +2313,8 @@ void * os2_alloc(size_t bytes) /* argument to span regions, so we should be OK for now. */ result = (ptr_t) VirtualAlloc(NULL, res_bytes, MEM_RESERVE | MEM_TOP_DOWN, - pages_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE); + GC_pages_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE); if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result"); /* If I read the documentation correctly, this can */ /* only happen if HBLKSIZE > 64k or not a power of 2. */ @@ -2326,8 +2327,8 @@ void * os2_alloc(size_t bytes) /* Commit pages */ result = (ptr_t) VirtualAlloc(result, bytes, MEM_COMMIT, - pages_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE); + GC_pages_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE); # undef IGNORE_PAGES_EXECUTABLE if (result != NULL) { @@ -2438,8 +2439,8 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) ABORT("Weird VirtualQuery result"); alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize; result = VirtualAlloc(start_addr, alloc_len, MEM_COMMIT, - pages_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE); + GC_pages_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE); if (result != start_addr) { if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY || GetLastError() == ERROR_OUTOFMEMORY) { @@ -2459,12 +2460,12 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) # ifndef NACL result = mprotect(start_addr, len, (PROT_READ | PROT_WRITE) - | (pages_executable ? PROT_EXEC : 0)); + | (GC_pages_executable ? PROT_EXEC : 0)); # else { /* NaCl does not expose mprotect, but mmap should work fine. */ void *mmap_result = mmap(start_addr, len, (PROT_READ | PROT_WRITE) - | (pages_executable ? PROT_EXEC : 0), + | (GC_pages_executable ? PROT_EXEC : 0), MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, zero_fd, 0 /* offset */); if (mmap_result != (void *)start_addr) @@ -2932,14 +2933,14 @@ STATIC void GC_default_push_other_roots(void) # define PROTECT(addr,len) \ if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ FALSE, VM_PROT_READ \ - | (pages_executable ? VM_PROT_EXECUTE : 0)) \ + | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \ != KERN_SUCCESS) { \ ABORT("vm_protect(PROTECT) failed"); \ } # define UNPROTECT(addr,len) \ if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ FALSE, (VM_PROT_READ | VM_PROT_WRITE) \ - | (pages_executable ? VM_PROT_EXECUTE : 0)) \ + | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \ != KERN_SUCCESS) { \ ABORT("vm_protect(UNPROTECT) failed"); \ } @@ -2952,15 +2953,15 @@ STATIC void GC_default_push_other_roots(void) # define PROTECT(addr, len) \ if (mprotect((caddr_t)(addr), (size_t)(len), \ PROT_READ \ - | (pages_executable ? PROT_EXEC : 0)) < 0) { \ + | (GC_pages_executable ? PROT_EXEC : 0)) < 0) { \ ABORT("mprotect failed"); \ } # define UNPROTECT(addr, len) \ if (mprotect((caddr_t)(addr), (size_t)(len), \ (PROT_READ | PROT_WRITE) \ - | (pages_executable ? PROT_EXEC : 0)) < 0) { \ - ABORT(pages_executable ? "un-mprotect executable page" \ - " failed (probably disabled by OS)" : \ + | (GC_pages_executable ? PROT_EXEC : 0)) < 0) { \ + ABORT(GC_pages_executable ? "un-mprotect executable page" \ + " failed (probably disabled by OS)" : \ "un-mprotect failed"); \ } # undef IGNORE_PAGES_EXECUTABLE @@ -2973,8 +2974,8 @@ STATIC void GC_default_push_other_roots(void) static DWORD protect_junk; # define PROTECT(addr, len) \ if (!VirtualProtect((addr), (len), \ - pages_executable ? PAGE_EXECUTE_READ : \ - PAGE_READONLY, \ + GC_pages_executable ? PAGE_EXECUTE_READ : \ + PAGE_READONLY, \ &protect_junk)) { \ if (GC_print_stats) \ GC_log_printf("Last error code: 0x%lx\n", (long)GetLastError()); \ @@ -2982,8 +2983,8 @@ STATIC void GC_default_push_other_roots(void) } # define UNPROTECT(addr, len) \ if (!VirtualProtect((addr), (len), \ - pages_executable ? PAGE_EXECUTE_READWRITE : \ - PAGE_READWRITE, \ + GC_pages_executable ? PAGE_EXECUTE_READWRITE : \ + PAGE_READWRITE, \ &protect_junk)) { \ ABORT("un-VirtualProtect failed"); \ } @@ -4413,9 +4414,9 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, GC_API void GC_CALL GC_set_pages_executable(int value) { GC_ASSERT(!GC_is_initialized); - /* Even if IGNORE_PAGES_EXECUTABLE is defined, pages_executable is */ + /* Even if IGNORE_PAGES_EXECUTABLE is defined, GC_pages_executable is */ /* touched here to prevent a compiler warning. */ - pages_executable = (GC_bool)(value != 0); + GC_pages_executable = (GC_bool)(value != 0); } /* Returns non-zero if the GC-allocated memory is executable. */ @@ -4426,7 +4427,7 @@ GC_API int GC_CALL GC_get_pages_executable(void) # ifdef IGNORE_PAGES_EXECUTABLE return 1; /* Always allocate executable memory. */ # else - return (int)pages_executable; + return (int)GC_pages_executable; # endif } diff --git a/ptr_chck.c b/ptr_chck.c index 9b0da0c1..d8076e84 100644 --- a/ptr_chck.c +++ b/ptr_chck.c @@ -242,7 +242,7 @@ GC_API void * GC_CALL GC_is_visible(void *p) } else { ptr_t type_descr = *(ptr_t *)base; descr = *(word *)(type_descr - - (descr - (GC_DS_PER_OBJECT + - (descr - (word)(GC_DS_PER_OBJECT - GC_INDIR_PER_OBJ_BIAS))); } goto retry; -- cgit v1.2.1 From 9ef08d8c493a0301f1fb01a6dab915628271a30d Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 26 Apr 2011 21:09:42 +0000 Subject: 2011-04-26 Ivan Maidanski * .cvsignore (initsecondarythread, test_cpp): Add. * os_dep.c (GC_linux_stack_base): Rename to GC_linux_main_stack_base. * os_dep.c (GC_freebsd_stack_base): Rename to GC_freebsd_main_stack_base; adjust error message. * pthread_stop_world.c (GC_stop_init): Use GC_SEM_INIT_PSHARED as an argument for sem_init(). * pthread_support.c (pthread_create): Ditto. * pthread_support.c (pthread_create): Abort in case sem_init() fails. * include/private/gc_priv.h (GC_SEM_INIT_PSHARED): Define. * tests/initsecondarythread.c: Include gcconfig.h; call GC_INIT from main() if it should be done from the primordial thread only. --HG-- branch : bdwgc --- .cvsignore | 2 ++ ChangeLog | 16 ++++++++++++++++ include/private/gc_priv.h | 4 ++++ os_dep.c | 12 +++++------- pthread_stop_world.c | 7 ++++--- pthread_support.c | 4 +++- tests/initsecondarythread.c | 28 ++++++++++++++++++++-------- 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/.cvsignore b/.cvsignore index d1ce9d22..c064b43a 100644 --- a/.cvsignore +++ b/.cvsignore @@ -6,6 +6,7 @@ config.log config.status gctest hugetest +initsecondarythread leaktest libcord.la libgc.la @@ -15,3 +16,4 @@ middletest smashtest staticrootstest threadleaktest +test_cpp diff --git a/ChangeLog b/ChangeLog index a8b064c4..250bc368 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-04-26 Ivan Maidanski + + * .cvsignore (initsecondarythread, test_cpp): Add. + * os_dep.c (GC_linux_stack_base): Rename to + GC_linux_main_stack_base. + * os_dep.c (GC_freebsd_stack_base): Rename to + GC_freebsd_main_stack_base; adjust error message. + * pthread_stop_world.c (GC_stop_init): Use GC_SEM_INIT_PSHARED + as an argument for sem_init(). + * pthread_support.c (pthread_create): Ditto. + * pthread_support.c (pthread_create): Abort in case sem_init() + fails. + * include/private/gc_priv.h (GC_SEM_INIT_PSHARED): Define. + * tests/initsecondarythread.c: Include gcconfig.h; call GC_INIT + from main() if it should be done from the primordial thread only. + 2011-04-26 Ivan Maidanski * alloc.c: Don't include sys/types.h for ArmCC. diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 9e34c769..2b7113ef 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -2097,6 +2097,10 @@ GC_EXTERN signed_word GC_bytes_found; # endif #endif /* GC_PTHREADS && !SIG_SUSPEND */ +#if defined(GC_PTHREADS) && !defined(GC_SEM_INIT_PSHARED) +# define GC_SEM_INIT_PSHARED 0 +#endif + /* Some macros for setjmp that works across signal handlers */ /* were possible, and a couple of routines to facilitate */ /* catching accesses to bad addresses when that's */ diff --git a/os_dep.c b/os_dep.c index a3e7a28e..39ca4384 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1038,7 +1038,7 @@ GC_INNER word GC_page_size = 0; } # endif /* IA64 */ - STATIC ptr_t GC_linux_stack_base(void) + STATIC ptr_t GC_linux_main_stack_base(void) { /* We read the stack base value from /proc/self/stat. We do this */ /* using direct I/O system calls in order to avoid calling malloc */ @@ -1124,15 +1124,13 @@ GC_INNER word GC_page_size = 0; # include # include - STATIC ptr_t GC_freebsd_stack_base(void) + STATIC ptr_t GC_freebsd_main_stack_base(void) { int nm[2] = {CTL_KERN, KERN_USRSTACK}; ptr_t base; size_t len = sizeof(ptr_t); int r = sysctl(nm, 2, &base, &len, NULL, 0); - - if (r) ABORT("Error getting stack base"); - + if (r) ABORT("Error getting main stack base"); return base; } #endif /* FREEBSD_STACKBOTTOM */ @@ -1192,10 +1190,10 @@ GC_INNER word GC_page_size = 0; # endif # endif /* HEURISTIC1 */ # ifdef LINUX_STACKBOTTOM - result = GC_linux_stack_base(); + result = GC_linux_main_stack_base(); # endif # ifdef FREEBSD_STACKBOTTOM - result = GC_freebsd_stack_base(); + result = GC_freebsd_main_stack_base(); # endif # ifdef HEURISTIC2 # ifdef STACK_GROWS_DOWN diff --git a/pthread_stop_world.c b/pthread_stop_world.c index af0c62e5..d7680e42 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -129,7 +129,8 @@ STATIC volatile AO_t GC_world_is_stopped = FALSE; */ #ifndef SIG_THR_RESTART -# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || defined(GC_NETBSD_THREADS) +# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) \ + || defined(GC_NETBSD_THREADS) # ifdef _SIGRTMIN # define SIG_THR_RESTART _SIGRTMIN + 5 # else @@ -794,10 +795,10 @@ GC_INNER void GC_stop_init(void) # if !defined(GC_OPENBSD_THREADS) && !defined(NACL) struct sigaction act; - if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0) + if (sem_init(&GC_suspend_ack_sem, GC_SEM_INIT_PSHARED, 0) != 0) ABORT("sem_init failed"); # ifdef GC_NETBSD_THREADS_WORKAROUND - if (sem_init(&GC_restart_ack_sem, 0, 0) != 0) + if (sem_init(&GC_restart_ack_sem, GC_SEM_INIT_PSHARED, 0) != 0) ABORT("sem_init failed"); # endif diff --git a/pthread_support.c b/pthread_support.c index 2feeac3e..575ac9d3 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1482,7 +1482,9 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread, (si = (struct start_info *) (*GC_get_oom_fn())(sizeof(struct start_info))) == 0) return(ENOMEM); - sem_init(&(si -> registered), 0, 0); + if (sem_init(&(si -> registered), GC_SEM_INIT_PSHARED, 0) != 0) + ABORT("sem_init failed"); + si -> start_routine = start_routine; si -> arg = arg; LOCK(); diff --git a/tests/initsecondarythread.c b/tests/initsecondarythread.c index feed5604..f89252e2 100755 --- a/tests/initsecondarythread.c +++ b/tests/initsecondarythread.c @@ -28,16 +28,28 @@ static void *thread(void *arg) { - GC_INIT (); - GC_MALLOC (123); - GC_MALLOC (12345); - return NULL; + GC_INIT(); + GC_MALLOC(123); + GC_MALLOC(12345); + return NULL; } +#include "private/gcconfig.h" + int main(void) { - pthread_t t; - pthread_create (&t, NULL, thread, NULL); - pthread_join (t, NULL); - return 0; + pthread_t t; +# if !(defined(BEOS) || defined(MSWIN32) || defined(MSWINCE) \ + || defined(CYGWIN32) || defined(GC_OPENBSD_THREADS) \ + || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)) \ + || (defined(LINUX) && !defined(NACL)) \ + || (defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC)) \ + || (!defined(STACKBOTTOM) && (defined(HEURISTIC1) \ + || (!defined(LINUX_STACKBOTTOM) && !defined(FREEBSD_STACKBOTTOM))))) + /* GC_INIT() must be called from main thread only. */ + GC_INIT(); +# endif + pthread_create (&t, NULL, thread, NULL); + pthread_join (t, NULL); + return 0; } -- cgit v1.2.1 From 274b8efc65a9258781bc82018c83cfbe8772231c Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 3 May 2011 07:21:16 +0000 Subject: 2011-05-03 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner, GC_store_debug_info): Rename "integer" argument to "linenum"; change the type of the argument to int. * gcj_mlc.c (GC_store_debug_info): Ditto. * dbg_mlc.c (GET_OH_LINENUM): New macro. * dbg_mlc.c (GC_print_obj, GC_print_smashed_obj): Use GET_OH_LINENUM; adjust print format specifier. * dbg_mlc.c (GC_debug_malloc, GC_debug_malloc_ignore_off_page, GC_debug_malloc_atomic_ignore_off_page, GC_debug_generic_malloc_inner, GC_debug_generic_malloc_inner_ignore_off_page, GC_debug_malloc_stubborn, GC_debug_malloc_atomic, GC_debug_malloc_uncollectable, GC_debug_malloc_atomic_uncollectable): Remove unnecessary cast of "i". * gcj_mlc.c (GC_debug_gcj_malloc): Ditto. --HG-- branch : bdwgc --- ChangeLog | 19 +++++++++++++++++++ dbg_mlc.c | 39 ++++++++++++++++++++------------------- gcj_mlc.c | 4 ++-- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 250bc368..f35aaa09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-05-03 Ivan Maidanski + + * dbg_mlc.c (GC_store_debug_info_inner, GC_store_debug_info): + Rename "integer" argument to "linenum"; change the type of the + argument to int. + * gcj_mlc.c (GC_store_debug_info): Ditto. + * dbg_mlc.c (GET_OH_LINENUM): New macro. + * dbg_mlc.c (GC_print_obj, GC_print_smashed_obj): Use + GET_OH_LINENUM; adjust print format specifier. + * dbg_mlc.c (GC_debug_malloc, GC_debug_malloc_ignore_off_page, + GC_debug_malloc_atomic_ignore_off_page, + GC_debug_generic_malloc_inner, + GC_debug_generic_malloc_inner_ignore_off_page, + GC_debug_malloc_stubborn, GC_debug_malloc_atomic, + GC_debug_malloc_uncollectable, + GC_debug_malloc_atomic_uncollectable): Remove unnecessary cast of + "i". + * gcj_mlc.c (GC_debug_gcj_malloc): Ditto. + 2011-04-26 Ivan Maidanski * .cvsignore (initsecondarythread, test_cpp): Add. diff --git a/dbg_mlc.c b/dbg_mlc.c index 4ab78f97..6e6ab699 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -255,7 +255,7 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); /* Store debugging info into p. Return displaced pointer. */ /* This version assumes we do hold the allocation lock. */ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, const char *string, - word integer) + int linenum) { word * result = (word *)((oh *)p + 1); @@ -268,7 +268,7 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, const char *string, ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0); # endif ((oh *)p) -> oh_string = string; - ((oh *)p) -> oh_int = integer; + ((oh *)p) -> oh_int = linenum; # ifndef SHORT_DBG_HDRS ((oh *)p) -> oh_sz = sz; ((oh *)p) -> oh_sf = START_FLAG ^ (word)result; @@ -279,13 +279,13 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, const char *string, } GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, - word integer) + int linenum) { ptr_t result; DCL_LOCK_STATE; LOCK(); - result = GC_store_debug_info_inner(p, sz, string, integer); + result = GC_store_debug_info_inner(p, sz, string, linenum); UNLOCK(); return result; } @@ -364,6 +364,8 @@ STATIC void GC_print_type(ptr_t p) } } +#define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int) + /* 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) @@ -377,10 +379,10 @@ STATIC void GC_print_obj(ptr_t p) GC_err_printf("%p (", ((ptr_t)ohdr + sizeof(oh))); GC_err_puts(ohdr -> oh_string); # ifdef SHORT_DBG_HDRS - GC_err_printf(":%ld, ", (unsigned long)(ohdr -> oh_int)); + GC_err_printf(":%d, ", GET_OH_LINENUM(ohdr)); # else - GC_err_printf(":%ld, sz=%ld, ", (unsigned long)(ohdr -> oh_int), - (unsigned long)(ohdr -> oh_sz)); + GC_err_printf(":%d, sz=%lu, ", + GET_OH_LINENUM(ohdr), (unsigned long)(ohdr -> oh_sz)); # endif GC_print_type((ptr_t)(ohdr + 1)); GC_err_puts(")\n"); @@ -416,13 +418,12 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) clobbered_addr, p, (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES)); } else { - GC_err_printf("%p in or near object at %p(%s:%lu, sz=%lu)\n", + GC_err_printf("%p in or near object at %p (%s:%d, sz=%lu)\n", clobbered_addr, p, (word)(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" : ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" : ohdr -> oh_string, - (unsigned long)(ohdr -> oh_int), - (unsigned long)(ohdr -> oh_sz)); + GET_OH_LINENUM(ohdr), (unsigned long)(ohdr -> oh_sz)); PRINT_CALL_CHAIN(ohdr); } } @@ -476,7 +477,7 @@ GC_API void * GC_CALL GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS) GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } GC_API void * GC_CALL GC_debug_malloc_ignore_off_page(size_t lb, @@ -495,7 +496,7 @@ GC_API void * GC_CALL GC_debug_malloc_ignore_off_page(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, @@ -514,7 +515,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } #ifdef DBG_HDRS_ALL @@ -533,7 +534,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, return(0); } ADD_CALL_CHAIN(result, GC_RETURN_ADDR); - return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); + return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0)); } GC_INNER void * GC_debug_generic_malloc_inner_ignore_off_page(size_t lb, @@ -548,7 +549,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, return(0); } ADD_CALL_CHAIN(result, GC_RETURN_ADDR); - return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); + return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0)); } #endif /* DBG_HDRS_ALL */ @@ -568,7 +569,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } GC_API void GC_CALL GC_debug_change_stubborn(void *p) @@ -634,7 +635,7 @@ GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS) GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS) @@ -717,7 +718,7 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } #ifdef ATOMIC_UNCOLLECTABLE @@ -739,7 +740,7 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } #endif /* ATOMIC_UNCOLLECTABLE */ diff --git a/gcj_mlc.c b/gcj_mlc.c index a3d9358f..3c54974c 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -209,7 +209,7 @@ GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */ /* Store debugging info into p. Return displaced pointer. */ /* Assumes we don't hold allocation lock. */ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, - word integer); + int linenum); /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ /* with GC_gcj_debug_kind. */ @@ -239,7 +239,7 @@ GC_API void * GC_CALL GC_debug_gcj_malloc(size_t lb, GC_start_debugging(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, (word)i)); + return (GC_store_debug_info(result, (word)lb, s, i)); } /* There is no THREAD_LOCAL_ALLOC for GC_gcj_malloc_ignore_off_page(). */ -- cgit v1.2.1 From 866b00ab8f07dedeaaf9c17aabeb5e6c6cc8314f Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 3 May 2011 10:33:59 +0000 Subject: 2011-05-03 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner): Cast "linenum". * dbg_mlc.c (GC_check_annotated_obj): Fix punctuation in the comment. * dbg_mlc.c (GC_print_smashed_obj): Add (and print) "msg" argument. * dbg_mlc.c (GC_debug_free, GC_print_all_smashed_proc): Pass message to GC_print_smashed_obj. * dbg_mlc.c (GC_debug_free): Call GC_size once. * dbg_mlc.c (GC_debug_realloc): Calculate old_sz only if allocation succeeded; remove unnecessary check for object is smashed (since this is done in GC_debug_free); remove "clobbered" local variable. --HG-- branch : bdwgc --- ChangeLog | 15 +++++++++++ dbg_mlc.c | 89 ++++++++++++++++++++++++++++----------------------------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index f35aaa09..e067b2ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-05-03 Ivan Maidanski + + * dbg_mlc.c (GC_store_debug_info_inner): Cast "linenum". + * dbg_mlc.c (GC_check_annotated_obj): Fix punctuation in the + comment. + * dbg_mlc.c (GC_print_smashed_obj): Add (and print) "msg" + argument. + * dbg_mlc.c (GC_debug_free, GC_print_all_smashed_proc): Pass + message to GC_print_smashed_obj. + * dbg_mlc.c (GC_debug_free): Call GC_size once. + * dbg_mlc.c (GC_debug_realloc): Calculate old_sz only if + allocation succeeded; remove unnecessary check for object is + smashed (since this is done in GC_debug_free); remove "clobbered" + local variable. + 2011-05-03 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner, GC_store_debug_info): diff --git a/dbg_mlc.c b/dbg_mlc.c index 6e6ab699..72b5f177 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -268,7 +268,7 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, const char *string, ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0); # endif ((oh *)p) -> oh_string = string; - ((oh *)p) -> oh_int = linenum; + ((oh *)p) -> oh_int = (word)linenum; # ifndef SHORT_DBG_HDRS ((oh *)p) -> oh_sz = sz; ((oh *)p) -> oh_sf = START_FLAG ^ (word)result; @@ -291,8 +291,8 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, } #ifndef SHORT_DBG_HDRS - /* Check the object with debugging info at ohdr */ - /* return NULL if it's OK. Else return clobbered */ + /* Check the object with debugging info at ohdr. */ + /* Return NULL if it's OK. Else return clobbered */ /* address. */ STATIC ptr_t GC_check_annotated_obj(oh *ohdr) { @@ -403,7 +403,8 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) /* 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) + STATIC void GC_print_smashed_obj(const char *msg, ptr_t p, + ptr_t clobbered_addr) { oh * ohdr = (oh *)GC_base(p); @@ -414,12 +415,12 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz)) || ohdr -> oh_string == 0) { GC_err_printf( - "%p in or near object at %p(, appr. sz = %lu)\n", - clobbered_addr, p, + "%s %p in or near object at %p(, appr. sz = %lu)\n", + msg, clobbered_addr, p, (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES)); } else { - GC_err_printf("%p in or near object at %p (%s:%d, sz=%lu)\n", - clobbered_addr, p, + GC_err_printf("%s %p in or near object at %p (%s:%d, sz=%lu)\n", + msg, clobbered_addr, p, (word)(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" : ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" : ohdr -> oh_string, @@ -751,46 +752,44 @@ GC_API void GC_CALL GC_debug_free(void * p) base = GC_base(p); if (base == 0) { - GC_err_printf("Attempt to free invalid pointer %p\n", p); - ABORT("Invalid pointer passed to free()"); + GC_err_printf("Attempt to free invalid pointer %p\n", p); + ABORT("Invalid pointer passed to free()"); } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { - GC_err_printf( + GC_err_printf( "GC_debug_free called on pointer %p w/o debugging info\n", p); } else { # ifndef SHORT_DBG_HDRS ptr_t clobbered = GC_check_annotated_obj((oh *)base); + word sz = GC_size(base); if (clobbered != 0) { - if (((oh *)base) -> oh_sz == GC_size(base)) { - GC_err_printf( - "GC_debug_free: found previously deallocated (?) object at "); - } else { - GC_err_printf("GC_debug_free: found smashed location at "); - } - GC_print_smashed_obj(p, clobbered); + GC_print_smashed_obj(((oh *)base) -> oh_sz == sz ? + "GC_debug_free: found previously deallocated (?) object at" : + "GC_debug_free: found smashed location at", + p, clobbered); GC_have_errors = TRUE; } /* Invalidate size */ - ((oh *)base) -> oh_sz = GC_size(base); + ((oh *)base) -> oh_sz = sz; # endif /* SHORT_DBG_HDRS */ } if (GC_find_leak) { - GC_free(base); + GC_free(base); } else { - hdr * hhdr = HDR(p); - if (hhdr -> hb_obj_kind == UNCOLLECTABLE -# ifdef ATOMIC_UNCOLLECTABLE - || hhdr -> hb_obj_kind == AUNCOLLECTABLE -# endif - ) { - GC_free(base); - } else { - size_t i; - size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh)); + hdr * hhdr = HDR(p); + if (hhdr -> hb_obj_kind == UNCOLLECTABLE +# ifdef ATOMIC_UNCOLLECTABLE + || hhdr -> hb_obj_kind == AUNCOLLECTABLE +# endif + ) { + GC_free(base); + } else { + size_t i; + size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh)); - for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef; - GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz)); - } + for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef; + GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz)); + } } /* !GC_find_leak */ } @@ -814,11 +813,7 @@ GC_API void GC_CALL GC_debug_free(void * p) GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) { void * base; -# ifndef SHORT_DBG_HDRS - ptr_t clobbered; -# endif void * result; - size_t old_sz; hdr * hhdr; if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i)); @@ -860,19 +855,13 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) ABORT("Bad kind"); } -# ifdef SHORT_DBG_HDRS - old_sz = GC_size(base) - sizeof(oh); -# else - clobbered = GC_check_annotated_obj((oh *)base); - if (clobbered != 0) { - GC_err_printf("GC_debug_realloc: found smashed location at "); - GC_print_smashed_obj(p, clobbered); - GC_have_errors = TRUE; - } - old_sz = ((oh *)base) -> oh_sz; -# endif - if (result != NULL) { + size_t old_sz; +# ifdef SHORT_DBG_HDRS + old_sz = GC_size(base) - sizeof(oh); +# else + old_sz = ((oh *)base) -> oh_sz; +# endif BCOPY(p, result, old_sz < lb ? old_sz : lb); GC_debug_free(p); } @@ -911,7 +900,7 @@ STATIC void GC_print_all_smashed_proc(void) if (GC_n_smashed == 0) return; GC_err_printf("GC_check_heap_block: found smashed heap objects:\n"); for (i = 0; i < GC_n_smashed; ++i) { - GC_print_smashed_obj((ptr_t)GC_base(GC_smashed[i]) + sizeof(oh), + GC_print_smashed_obj("", (ptr_t)GC_base(GC_smashed[i]) + sizeof(oh), GC_smashed[i]); GC_smashed[i] = 0; } -- cgit v1.2.1 From 84669fdf7bcf9c8d41d83e9bc7467bc75f6b64cd Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 5 May 2011 05:24:48 +0000 Subject: 2011-05-05 Ivan Maidanski * dbg_mlc.c (GC_has_other_debug_info): Fix punctuation in the comment. * dbg_mlc.c (GC_FREED_MEM_MARKER): New macro. * dbg_mlc.c (GC_debug_free): Use GC_FREED_MEM_MARKER. * dbg_mlc.c (GC_smashed): Refine documentation. * mark.c (GC_push_selected): Change dirty_fn return type to GC_bool. * os_dep.c (GC_page_was_ever_dirty): Make GC_INNER. * reclaim.c (GC_reclaim_small_nonempty_block): Remove "kind" local variable. * reclaim.c (GC_reclaim_block): Pass true constant to GC_reclaim_small_nonempty_block (instead of report_if_found). * doc/README.autoconf: Update; fix a typo. * include/private/gcconfig.h (GC_WORD_C): New macro. --HG-- branch : bdwgc --- ChangeLog | 17 +++++++++++++++++ dbg_mlc.c | 21 +++++++++++++++------ doc/README.autoconf | 6 +++--- include/private/gcconfig.h | 12 +++++++++++- mark.c | 2 +- os_dep.c | 2 +- reclaim.c | 8 +++----- 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index e067b2ce..d6278469 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-05-05 Ivan Maidanski + + * dbg_mlc.c (GC_has_other_debug_info): Fix punctuation in the + comment. + * dbg_mlc.c (GC_FREED_MEM_MARKER): New macro. + * dbg_mlc.c (GC_debug_free): Use GC_FREED_MEM_MARKER. + * dbg_mlc.c (GC_smashed): Refine documentation. + * mark.c (GC_push_selected): Change dirty_fn return type to + GC_bool. + * os_dep.c (GC_page_was_ever_dirty): Make GC_INNER. + * reclaim.c (GC_reclaim_small_nonempty_block): Remove "kind" + local variable. + * reclaim.c (GC_reclaim_block): Pass true constant to + GC_reclaim_small_nonempty_block (instead of report_if_found). + * doc/README.autoconf: Update; fix a typo. + * include/private/gcconfig.h (GC_WORD_C): New macro. + 2011-05-03 Ivan Maidanski * dbg_mlc.c (GC_store_debug_info_inner): Cast "linenum". diff --git a/dbg_mlc.c b/dbg_mlc.c index 72b5f177..b2671c1c 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -25,7 +25,7 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); #ifndef SHORT_DBG_HDRS - /* Check whether object with base pointer p has debugging info */ + /* 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 */ @@ -745,6 +745,14 @@ GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, } #endif /* ATOMIC_UNCOLLECTABLE */ +#ifndef GC_FREED_MEM_MARKER +# if CPP_WORDSZ == 32 +# define GC_FREED_MEM_MARKER 0xdeadbeef +# else +# define GC_FREED_MEM_MARKER GC_WORD_C(0xEFBEADDEdeadbeef) +# endif +#endif + GC_API void GC_CALL GC_debug_free(void * p) { ptr_t base; @@ -787,7 +795,8 @@ GC_API void GC_CALL GC_debug_free(void * p) size_t i; size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh)); - for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef; + for (i = 0; i < obj_sz; ++i) + ((word *)p)[i] = GC_FREED_MEM_MARKER; GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz)); } } /* !GC_find_leak */ @@ -870,10 +879,10 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) #ifndef SHORT_DBG_HDRS -/* List of smashed objects. We defer printing these, since we can't */ -/* always print them nicely with the allocation lock held. */ -/* We put them here instead of in GC_arrays, since it may be useful to */ -/* be able to look at them with the debugger. */ +/* List of smashed (clobbered) locations. We defer printing these, */ +/* since we can't always print them nicely with the allocation lock */ +/* held. We put them here instead of in GC_arrays, since it may be */ +/* useful to be able to look at them with the debugger. */ #ifndef MAX_SMASHED # define MAX_SMASHED 20 #endif diff --git a/doc/README.autoconf b/doc/README.autoconf index f8640bec..94833f65 100644 --- a/doc/README.autoconf +++ b/doc/README.autoconf @@ -1,4 +1,4 @@ -As of GC6.0alpha8, we attempt to support GNU-style builds based on automake, +Starting from GC v6.0, we support GNU-style builds based on automake, autoconf and libtool. This is based almost entirely on Tom Tromey's work with gcj. @@ -36,7 +36,7 @@ as well as the sources needed to regenerate the derived files. (If I missed some, please let me know.) Note that the distribution comes with a "Makefile" which will be overwritten -by "configure" with one that is not at all equiavelent to the original. The +by "configure" with one that is not at all equivalent to the original. The distribution contains a copy of the original "Makefile" in "Makefile.direct". Important options to configure: @@ -48,7 +48,7 @@ Important options to configure: --enable-threads=TYPE choose threading package --enable-parallel-mark parallelize marking and free list construction --enable-gc-debug (--enable-full-debug before about 7.0) - include full support for pointer backtracing etc. + include full support for pointer back-tracing etc. Unless --prefix is set (or --exec-prefix or one of the more obscure options), diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index f541d7a7..301b200e 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2536,7 +2536,17 @@ /* strtoul() fits since sizeof(long) >= sizeof(word). */ # define STRTOULL strtoul # endif -#endif +#endif /* !STRTOULL */ + +#ifndef GC_WORD_C +# if defined(_WIN64) && !defined(__GNUC__) +# define GC_WORD_C(val) val##ui64 +# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64) +# define GC_WORD_C(val) val##ULL +# else +# define GC_WORD_C(val) ((word)val##UL) +# endif +#endif /* !GC_WORD_C */ #if defined(SPARC) # define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ diff --git a/mark.c b/mark.c index 8a3610dc..5fd37aef 100644 --- a/mark.c +++ b/mark.c @@ -1292,7 +1292,7 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) * in the event of a stack overflow.) */ STATIC void GC_push_selected(ptr_t bottom, ptr_t top, - int (*dirty_fn)(struct hblk *), + GC_bool (*dirty_fn)(struct hblk *), void (*push_fn)(ptr_t, ptr_t)) { struct hblk * h; diff --git a/os_dep.c b/os_dep.c index 39ca4384..1192ebd5 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2894,7 +2894,7 @@ STATIC void GC_default_push_other_roots(void) # ifdef CHECKSUMS /* Could any valid GC heap pointer ever have been written to this page? */ /*ARGSUSED*/ - GC_bool GC_page_was_ever_dirty(struct hblk *h) + GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h) { /* FIXME - implement me. */ return(TRUE); diff --git a/reclaim.c b/reclaim.c index 6a204f71..f9bfd851 100644 --- a/reclaim.c +++ b/reclaim.c @@ -254,8 +254,7 @@ STATIC void GC_reclaim_small_nonempty_block(struct hblk *hbp, { hdr *hhdr = HDR(hbp); size_t sz = hhdr -> hb_sz; - int kind = hhdr -> hb_obj_kind; - struct obj_kind * ok = &GC_obj_kinds[kind]; + struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; void **flh = &(ok -> ok_freelist[BYTES_TO_GRANULES(sz)]); hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no; @@ -263,8 +262,7 @@ STATIC void GC_reclaim_small_nonempty_block(struct hblk *hbp, if (report_if_found) { GC_reclaim_check(hbp, hhdr, sz); } else { - *flh = GC_reclaim_generic(hbp, hhdr, sz, - ok -> ok_init, + *flh = GC_reclaim_generic(hbp, hhdr, sz, ok -> ok_init, *flh, &GC_bytes_found); } } @@ -322,7 +320,7 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) GC_atomic_in_use += sz * hhdr -> hb_n_marks; } if (report_if_found) { - GC_reclaim_small_nonempty_block(hbp, (GC_bool)report_if_found); + GC_reclaim_small_nonempty_block(hbp, TRUE /* report_if_found */); } else if (empty) { GC_bytes_found += HBLKSIZE; GC_freehblk(hbp); -- cgit v1.2.1 From 8ca0d1e0a0f5cbc70d609e81294c82bdf36c327d Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 6 May 2011 04:43:49 +0000 Subject: 2011-05-06 Ivan Maidanski * dbg_mlc.c (GC_has_other_debug_info): Change return type to int; return -1 if the object has (or had) debugging info but was marked deallocated. * include/private/dbg_mlc.h (GC_has_other_debug_info): Ditto. * dbg_mlc.c (GC_has_other_debug_info): Update documentation; remove "ohdr" local variable. * dbg_mlc.c (GC_debug_free): Don't call GC_free if the object has probably been deallocated. * dbg_mlc.c (GC_debug_free): Don't actually free the object even in the leak-finding mode if GC_findleak_delay_free. * dbg_mlc.c (GC_print_all_smashed_proc): Print a trailing blank line. * dbg_mlc.c (GC_check_leaked): New function (only unless SHORT_DBG_HDRS). * doc/README.environment (GC_FINDLEAK_DELAY_FREE): Document. * doc/README.macros (GC_FINDLEAK_DELAY_FREE): Ditto. * include/private/dbg_mlc.h (START_FLAG, END_FLAG): Use GC_WORD_C on 64-bit architectures. * include/private/dbg_mlc.h (NOT_MARKED): Remove redundant parentheses. * include/private/dbg_mlc.h (GC_HAS_DEBUG_INFO): Update (due to GC_has_other_debug_info change). * include/private/gc_priv.h (GC_findleak_delay_free): New global variable declaration (unless SHORT_DBG_HDRS). * misc.c (GC_findleak_delay_free): New global variable; recognize GC_FINDLEAK_DELAY_FREE. * misc.c (GC_init): Recognize GC_FINDLEAK_DELAY_FREE environment variable (unless SHORT_DBG_HDRS). * reclaim.c (GC_check_leaked): Declare (unless SHORT_DBG_HDRS). * reclaim.c (GC_add_leaked): Don't add the object to leaked list if marked as deallocated. --HG-- branch : bdwgc --- ChangeLog | 34 +++++++++ dbg_mlc.c | 78 +++++++++++++------ doc/README.environment | 4 + doc/README.macros | 5 ++ include/private/dbg_mlc.h | 187 +++++++++++++++++++++++----------------------- include/private/gc_priv.h | 7 ++ misc.c | 13 ++++ reclaim.c | 9 +++ 8 files changed, 224 insertions(+), 113 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6278469..91d1afd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2011-05-06 Ivan Maidanski + + * dbg_mlc.c (GC_has_other_debug_info): Change return type to int; + return -1 if the object has (or had) debugging info but was + marked deallocated. + * include/private/dbg_mlc.h (GC_has_other_debug_info): Ditto. + * dbg_mlc.c (GC_has_other_debug_info): Update documentation; + remove "ohdr" local variable. + * dbg_mlc.c (GC_debug_free): Don't call GC_free if the object has + probably been deallocated. + * dbg_mlc.c (GC_debug_free): Don't actually free the object even + in the leak-finding mode if GC_findleak_delay_free. + * dbg_mlc.c (GC_print_all_smashed_proc): Print a trailing blank + line. + * dbg_mlc.c (GC_check_leaked): New function (only unless + SHORT_DBG_HDRS). + * doc/README.environment (GC_FINDLEAK_DELAY_FREE): Document. + * doc/README.macros (GC_FINDLEAK_DELAY_FREE): Ditto. + * include/private/dbg_mlc.h (START_FLAG, END_FLAG): Use GC_WORD_C + on 64-bit architectures. + * include/private/dbg_mlc.h (NOT_MARKED): Remove redundant + parentheses. + * include/private/dbg_mlc.h (GC_HAS_DEBUG_INFO): Update (due to + GC_has_other_debug_info change). + * include/private/gc_priv.h (GC_findleak_delay_free): New global + variable declaration (unless SHORT_DBG_HDRS). + * misc.c (GC_findleak_delay_free): New global variable; recognize + GC_FINDLEAK_DELAY_FREE. + * misc.c (GC_init): Recognize GC_FINDLEAK_DELAY_FREE environment + variable (unless SHORT_DBG_HDRS). + * reclaim.c (GC_check_leaked): Declare (unless SHORT_DBG_HDRS). + * reclaim.c (GC_add_leaked): Don't add the object to leaked list + if marked as deallocated. + 2011-05-05 Ivan Maidanski * dbg_mlc.c (GC_has_other_debug_info): Fix punctuation in the diff --git a/dbg_mlc.c b/dbg_mlc.c index b2671c1c..c3d9e77f 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -32,27 +32,27 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); /* 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_INNER GC_bool GC_has_other_debug_info(ptr_t p) + /* not always safe to return TRUE (1), even if the client does */ + /* its part. Return -1 if the object with debug info has been */ + /* marked as deallocated. */ + GC_INNER int 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); + ptr_t body = (ptr_t)((oh *)p + 1); + word sz = GC_size(p); - if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body) + if (HBLKPTR(p) != HBLKPTR((ptr_t)body) || sz < DEBUG_BYTES + EXTRA_BYTES) { - return(FALSE); + return 0; } - if (ohdr -> oh_sz == sz) { - /* Object may have had debug info, but has been deallocated */ - return(FALSE); + if (((oh *)p) -> oh_sf != (START_FLAG ^ (word)body) + && ((word *)p)[BYTES_TO_WORDS(sz)-1] != (END_FLAG ^ (word)body)) { + return 0; } - if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE); - if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) { - return(TRUE); + if (((oh *)p)->oh_sz == sz) { + /* Object may have had debug info, but has been deallocated */ + return -1; } - return(FALSE); + return 1; } #endif /* !SHORT_DBG_HDRS */ @@ -771,17 +771,26 @@ GC_API void GC_CALL GC_debug_free(void * p) ptr_t clobbered = GC_check_annotated_obj((oh *)base); word sz = GC_size(base); if (clobbered != 0) { - GC_print_smashed_obj(((oh *)base) -> oh_sz == sz ? - "GC_debug_free: found previously deallocated (?) object at" : - "GC_debug_free: found smashed location at", - p, clobbered); GC_have_errors = TRUE; + if (((oh *)base) -> oh_sz == sz) { + GC_print_smashed_obj( + "GC_debug_free: found previously deallocated (?) object at", + p, clobbered); + return; /* ignore double free */ + } else { + GC_print_smashed_obj("GC_debug_free: found smashed location at", + p, clobbered); + } } - /* Invalidate size */ + /* Invalidate size (mark the object as deallocated) */ ((oh *)base) -> oh_sz = sz; # endif /* SHORT_DBG_HDRS */ } - if (GC_find_leak) { + if (GC_find_leak +# ifndef SHORT_DBG_HDRS + && ((ptr_t)p - (ptr_t)base != sizeof(oh) || !GC_findleak_delay_free) +# endif + ) { GC_free(base); } else { hdr * hhdr = HDR(p); @@ -914,6 +923,7 @@ STATIC void GC_print_all_smashed_proc(void) GC_smashed[i] = 0; } GC_n_smashed = 0; + GC_err_printf("\n"); } /* Check all marked objects in the given block for validity */ @@ -951,6 +961,32 @@ STATIC void GC_check_heap_proc(void) GC_apply_to_all_blocks(GC_check_heap_block, 0); } +GC_INNER GC_bool GC_check_leaked(ptr_t base) +{ + size_t i; + size_t obj_sz; + word *p; + + if ( +# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) + (*(word *)base & 1) != 0 && +# endif + GC_has_other_debug_info(base) >= 0) + return TRUE; /* object has leaked */ + + /* Validate freed object's content. */ + p = (word *)(base + sizeof(oh)); + obj_sz = BYTES_TO_WORDS(HDR(base)->hb_sz - sizeof(oh)); + for (i = 0; i < obj_sz; ++i) + if (p[i] != GC_FREED_MEM_MARKER) { + GC_set_mark_bit(base); /* do not reclaim it in this cycle */ + GC_add_smashed((ptr_t)(&p[i])); /* alter-after-free detected */ + break; /* don't report any other smashed locations in the object */ + } + + return FALSE; /* GC_debug_free() has been called */ +} + #endif /* !SHORT_DBG_HDRS */ struct closure { diff --git a/doc/README.environment b/doc/README.environment index d9995f59..866e9055 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -160,6 +160,10 @@ GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. Forces a collection at program termination to detect leaks that would otherwise occur after the last GC. +GC_FINDLEAK_DELAY_FREE - Turns on deferred freeing of objects in the + leak-finding mode (see the corresponding macro + description for more information). + GC_ABORT_ON_LEAK - Causes the application to be terminated once leaked or smashed objects are found. diff --git a/doc/README.macros b/doc/README.macros index c4a33c4c..4fd5c840 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -87,6 +87,11 @@ FIND_LEAK Causes GC_find_leak to be initially set. This causes the explicitly deallocated, and reports exceptions. Finalization and the test program are not usable in this mode. +GC_FINDLEAK_DELAY_FREE Turns on deferred freeing of objects in the + leak-finding mode letting the collector to detect alter-object-after-free + errors as well as detect leaked objects sooner (instead of only when program + terminates). Has no effect if SHORT_DBG_HDRS. + GC_ABORT_ON_LEAK Causes the application to be terminated once leaked or smashed (corrupted on use-after-free) objects are found (after printing the information about that objects). diff --git a/include/private/dbg_mlc.h b/include/private/dbg_mlc.h index a6f2ef6a..7b2969d2 100644 --- a/include/private/dbg_mlc.h +++ b/include/private/dbg_mlc.h @@ -25,92 +25,96 @@ #ifndef _DBG_MLC_H #define _DBG_MLC_H -# include "gc_priv.h" -# ifdef KEEP_BACK_PTRS -# include "gc_backptr.h" -# endif +#include "gc_priv.h" +#ifdef KEEP_BACK_PTRS +# include "gc_backptr.h" +#endif -# define START_FLAG ((word)0xfedcedcb) -# define END_FLAG ((word)0xbcdecdef) +#if CPP_WORDSZ == 32 +# define START_FLAG (word)0xfedcedcb +# define END_FLAG (word)0xbcdecdef +#else +# define START_FLAG GC_WORD_C(0xFEDCEDCBfedcedcb) +# define END_FLAG GC_WORD_C(0xBCDECDEFbcdecdef) +#endif /* Stored both one past the end of user object, and one before */ /* the end of the object as seen by the allocator. */ -# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) \ - || defined(MAKE_BACK_GRAPH) - /* Pointer "source"s that aren't real locations. */ - /* Used in oh_back_ptr fields and as "source" */ - /* argument to some marking functions. */ -# define NOT_MARKED (ptr_t)(0) -# define MARKED_FOR_FINALIZATION ((ptr_t)(word)2) - /* Object was marked because it is finalizable. */ -# define MARKED_FROM_REGISTER ((ptr_t)(word)4) - /* Object was marked from a register. Hence the */ - /* source of the reference doesn't have an address. */ -# endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */ +#if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) \ + || defined(MAKE_BACK_GRAPH) + /* Pointer "source"s that aren't real locations. */ + /* Used in oh_back_ptr fields and as "source" */ + /* argument to some marking functions. */ +# define NOT_MARKED (ptr_t)0 +# define MARKED_FOR_FINALIZATION ((ptr_t)(word)2) + /* Object was marked because it is finalizable. */ +# define MARKED_FROM_REGISTER ((ptr_t)(word)4) + /* Object was marked from a register. Hence the */ + /* source of the reference doesn't have an address. */ +#endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */ /* Object header */ typedef struct { -# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) - /* We potentially keep two different kinds of back */ - /* pointers. KEEP_BACK_PTRS stores a single back */ - /* pointer in each reachable object to allow reporting */ - /* of why an object was retained. MAKE_BACK_GRAPH */ - /* builds a graph containing the inverse of all */ - /* "points-to" edges including those involving */ - /* objects that have just become unreachable. This */ - /* allows detection of growing chains of unreachable */ - /* objects. It may be possible to eventually combine */ - /* both, but for now we keep them separate. Both */ - /* kinds of back pointers are hidden using the */ - /* following macros. In both cases, the plain version */ - /* is constrained to have an least significant bit of 1,*/ - /* to allow it to be distinguished from a free list */ - /* link. This means the plain version must have an */ - /* lsb of 0. */ - /* Note that blocks dropped by black-listing will */ - /* also have the lsb clear once debugging has */ - /* started. */ - /* We're careful never to overwrite a value with lsb 0. */ -# if ALIGNMENT == 1 - /* Fudge back pointer to be even. */ -# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(~1 & (GC_word)(p)) -# else -# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p) -# endif - -# ifdef KEEP_BACK_PTRS - GC_hidden_pointer oh_back_ptr; -# endif -# ifdef MAKE_BACK_GRAPH - GC_hidden_pointer oh_bg_ptr; -# endif -# if defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH) - /* Keep double-pointer-sized alignment. */ - word oh_dummy; -# endif +# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) + /* We potentially keep two different kinds of back */ + /* pointers. KEEP_BACK_PTRS stores a single back */ + /* pointer in each reachable object to allow reporting */ + /* of why an object was retained. MAKE_BACK_GRAPH */ + /* builds a graph containing the inverse of all */ + /* "points-to" edges including those involving */ + /* objects that have just become unreachable. This */ + /* allows detection of growing chains of unreachable */ + /* objects. It may be possible to eventually combine */ + /* both, but for now we keep them separate. Both */ + /* kinds of back pointers are hidden using the */ + /* following macros. In both cases, the plain version */ + /* is constrained to have an least significant bit of 1, */ + /* to allow it to be distinguished from a free list */ + /* link. This means the plain version must have an */ + /* lsb of 0. */ + /* Note that blocks dropped by black-listing will */ + /* also have the lsb clear once debugging has */ + /* started. */ + /* We're careful never to overwrite a value with lsb 0. */ +# if ALIGNMENT == 1 + /* Fudge back pointer to be even. */ +# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(~1 & (GC_word)(p)) +# else +# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p) +# endif +# ifdef KEEP_BACK_PTRS + GC_hidden_pointer oh_back_ptr; +# endif +# ifdef MAKE_BACK_GRAPH + GC_hidden_pointer oh_bg_ptr; # endif - const char * oh_string; /* object descriptor string */ - word oh_int; /* object descriptor integers */ -# ifdef NEED_CALLINFO - struct callinfo oh_ci[NFRAMES]; +# if defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH) + /* Keep double-pointer-sized alignment. */ + word oh_dummy; # endif -# ifndef SHORT_DBG_HDRS - word oh_sz; /* Original malloc arg. */ - word oh_sf; /* start flag */ -# endif /* SHORT_DBG_HDRS */ +# endif + const char * oh_string; /* object descriptor string */ + word oh_int; /* object descriptor integers */ +# ifdef NEED_CALLINFO + struct callinfo oh_ci[NFRAMES]; +# endif +# ifndef SHORT_DBG_HDRS + word oh_sz; /* Original malloc arg. */ + word oh_sf; /* start flag */ +# endif /* SHORT_DBG_HDRS */ } oh; /* The size of the above structure is assumed not to de-align things, */ /* and to be a multiple of the word length. */ #ifdef SHORT_DBG_HDRS -# define DEBUG_BYTES (sizeof (oh)) -# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES +# define DEBUG_BYTES (sizeof (oh)) +# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES #else - /* Add space for END_FLAG, but use any extra space that was already */ - /* added to catch off-the-end pointers. */ - /* For uncollectable objects, the extra byte is not added. */ -# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word)) -# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES) + /* Add space for END_FLAG, but use any extra space that was already */ + /* added to catch off-the-end pointers. */ + /* For uncollectable objects, the extra byte is not added. */ +# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word)) +# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES) #endif /* Round bytes to words without adding extra byte at end. */ @@ -122,42 +126,41 @@ typedef struct { /* PRINT_CALL_CHAIN prints the call chain stored in an object */ /* to stderr. It requires that we do not hold the lock. */ #if defined(SAVE_CALL_CHAIN) - struct callinfo; - GC_INNER void GC_save_callers(struct callinfo info[NFRAMES]); - GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]); -# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) -# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) + struct callinfo; + GC_INNER void GC_save_callers(struct callinfo info[NFRAMES]); + GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]); +# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) +# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) #elif defined(GC_ADD_CALLER) - struct callinfo; - GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]); -# define ADD_CALL_CHAIN(base, ra) ((oh *)(base)) -> oh_ci[0].ci_pc = (ra) -# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) + struct callinfo; + GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]); +# define ADD_CALL_CHAIN(base, ra) ((oh *)(base)) -> oh_ci[0].ci_pc = (ra) +# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) #else -# define ADD_CALL_CHAIN(base, ra) -# define PRINT_CALL_CHAIN(base) +# define ADD_CALL_CHAIN(base, ra) +# define PRINT_CALL_CHAIN(base) #endif -# ifdef GC_ADD_CALLER -# define OPT_RA ra, -# else -# define OPT_RA -# endif - +#ifdef GC_ADD_CALLER +# define OPT_RA ra, +#else +# define OPT_RA +#endif /* 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. */ #ifdef SHORT_DBG_HDRS -# define GC_has_other_debug_info(p) TRUE +# define GC_has_other_debug_info(p) 1 #else - GC_INNER GC_bool GC_has_other_debug_info(ptr_t p); + GC_INNER int GC_has_other_debug_info(ptr_t p); #endif #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) # define GC_HAS_DEBUG_INFO(p) \ - ((*((word *)p) & 1) && GC_has_other_debug_info(p)) + ((*((word *)p) & 1) && GC_has_other_debug_info(p) > 0) #else -# define GC_HAS_DEBUG_INFO(p) GC_has_other_debug_info(p) +# define GC_HAS_DEBUG_INFO(p) (GC_has_other_debug_info(p) > 0) #endif #endif /* _DBG_MLC_H */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 2b7113ef..c02def1b 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1790,6 +1790,13 @@ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); /* Print an address map of the process. */ #endif +#ifndef SHORT_DBG_HDRS + GC_EXTERN GC_bool GC_findleak_delay_free; + /* Do not immediately deallocate object on */ + /* free() in the leak-finding mode, just mark */ + /* it as freed (and deallocate it after GC). */ +#endif + GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ /* Call error printing routine */ /* occasionally. It is ok to read it */ diff --git a/misc.c b/misc.c index bd8730f0..50d55e04 100644 --- a/misc.c +++ b/misc.c @@ -114,6 +114,14 @@ GC_bool GC_quiet = 0; /* used also in pcr_interface.c */ int GC_find_leak = 0; #endif +#ifndef SHORT_DBG_HDRS +# ifdef GC_FINDLEAK_DELAY_FREE + GC_INNER GC_bool GC_findleak_delay_free = TRUE; +# else + GC_INNER GC_bool GC_findleak_delay_free = FALSE; +# endif +#endif /* !SHORT_DBG_HDRS */ + #ifdef ALL_INTERIOR_POINTERS int GC_all_interior_pointers = 1; #else @@ -789,6 +797,11 @@ GC_API void GC_CALL GC_init(void) if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1; } +# ifndef SHORT_DBG_HDRS + if (0 != GETENV("GC_FINDLEAK_DELAY_FREE")) { + GC_findleak_delay_free = TRUE; + } +# endif if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; } diff --git a/reclaim.c b/reclaim.c index f9bfd851..c9e8e530 100644 --- a/reclaim.c +++ b/reclaim.c @@ -41,8 +41,17 @@ STATIC unsigned GC_n_leaked = 0; GC_INNER GC_bool GC_have_errors = FALSE; +#ifndef SHORT_DBG_HDRS + GC_INNER GC_bool GC_check_leaked(ptr_t base); /* from dbg_mlc.c */ +#endif + GC_INLINE void GC_add_leaked(ptr_t leaked) { +# ifndef SHORT_DBG_HDRS + if (GC_findleak_delay_free && !GC_check_leaked(leaked)) + return; +# endif + GC_have_errors = TRUE; /* FIXME: Prevent adding an object while printing leaked ones. */ if (GC_n_leaked < MAX_LEAKED) { -- cgit v1.2.1 From 51141d71811dd690369485fbef53e919a67dcb0a Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 6 May 2011 05:35:44 +0000 Subject: 2011-05-06 Ivan Maidanski * os_dep.c (GC_write_fault_handler): Break when in_allocd_block is set to true. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ os_dep.c | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 91d1afd2..250b0cbd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-06 Ivan Maidanski + + * os_dep.c (GC_write_fault_handler): Break when in_allocd_block + is set to true. + 2011-05-06 Ivan Maidanski * dbg_mlc.c (GC_has_other_debug_info): Change return type to int; diff --git a/os_dep.c b/os_dep.c index 1192ebd5..eb69a7ec 100644 --- a/os_dep.c +++ b/os_dep.c @@ -3150,6 +3150,7 @@ STATIC void GC_default_push_other_roots(void) for (i = 0; i < divHBLKSZ(GC_page_size); i++) { if (HDR(h+i) != 0) { in_allocd_block = TRUE; + break; } } # else -- cgit v1.2.1 From cb32c7a90b8af473bac1902fef6278a8523beab7 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 6 May 2011 07:46:35 +0000 Subject: 2011-05-06 Ivan Maidanski * cord/cordxtra.c (CORD_from_file_lazy_inner): Suppress "unused result" compiler warning for fread(). * cord/cordxtra.c: Expand all tabs to spaces. --HG-- branch : bdwgc --- ChangeLog | 6 ++ cord/cordxtra.c | 243 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 129 insertions(+), 120 deletions(-) diff --git a/ChangeLog b/ChangeLog index 250b0cbd..6131fa4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-06 Ivan Maidanski + + * cord/cordxtra.c (CORD_from_file_lazy_inner): Suppress + "unused result" compiler warning for fread(). + * cord/cordxtra.c: Expand all tabs to spaces. + 2011-05-06 Ivan Maidanski * os_dep.c (GC_write_fault_handler): Break when in_allocd_block diff --git a/cord/cordxtra.c b/cord/cordxtra.c index b0a74622..d5394dba 100644 --- a/cord/cordxtra.c +++ b/cord/cordxtra.c @@ -24,17 +24,17 @@ # include # include "cord.h" # include "ec.h" -# define I_HIDE_POINTERS /* So we get access to allocation lock. */ - /* We use this for lazy file reading, */ - /* so that we remain independent */ - /* of the threads primitives. */ +# define I_HIDE_POINTERS /* So we get access to allocation lock. */ + /* We use this for lazy file reading, */ + /* so that we remain independent */ + /* of the threads primitives. */ # include "gc.h" -/* For now we assume that pointer reads and writes are atomic, */ -/* i.e. another thread always sees the state before or after */ -/* a write. This might be false on a Motorola M68K with */ -/* pointers that are not 32-bit aligned. But there probably */ -/* aren't too many threads packages running on those. */ +/* For now we assume that pointer reads and writes are atomic, */ +/* i.e. another thread always sees the state before or after */ +/* a write. This might be false on a Motorola M68K with */ +/* pointers that are not 32-bit aligned. But there probably */ +/* aren't too many threads packages running on those. */ # define ATOMIC_WRITE(x,y) (x) = (y) # define ATOMIC_READ(x) (*(x)) @@ -46,19 +46,19 @@ # define SEEK_END 2 # endif -# define BUFSZ 2048 /* Size of stack allocated buffers when */ - /* we want large buffers. */ +# define BUFSZ 2048 /* Size of stack allocated buffers when */ + /* we want large buffers. */ typedef void (* oom_fn)(void); # define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \ - ABORT("Out of memory\n"); } + ABORT("Out of memory\n"); } # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); } CORD CORD_cat_char(CORD x, char c) { register char * string; - + if (c == '\0') return(CORD_cat(x, CORD_nul(1))); string = GC_MALLOC_ATOMIC(2); if (string == 0) OUT_OF_MEMORY; @@ -83,22 +83,22 @@ CORD CORD_catn(int nargs, ...) } typedef struct { - size_t len; - size_t count; - char * buf; + size_t len; + size_t count; + char * buf; } CORD_fill_data; int CORD_fill_proc(char c, void * client_data) { register CORD_fill_data * d = (CORD_fill_data *)client_data; register size_t count = d -> count; - + (d -> buf)[count] = c; d -> count = ++count; if (count >= d -> len) { - return(1); + return(1); } else { - return(0); + return(0); } } @@ -109,7 +109,7 @@ int CORD_batched_fill_proc(const char * s, void * client_data) register size_t max = d -> len; register char * buf = d -> buf; register const char * t = s; - + while((buf[count] = *t++) != '\0') { count++; if (count >= max) { @@ -121,12 +121,12 @@ int CORD_batched_fill_proc(const char * s, void * client_data) return(0); } -/* Fill buf with len characters starting at i. */ -/* Assumes len characters are available. */ +/* Fill buf with len characters starting at i. */ +/* Assumes len characters are available. */ void CORD_fill_buf(CORD x, size_t i, size_t len, char * buf) { CORD_fill_data fd; - + fd.len = len; fd.buf = buf; fd.count = 0; @@ -138,7 +138,7 @@ int CORD_cmp(CORD x, CORD y) CORD_pos xpos; CORD_pos ypos; register size_t avail, yavail; - + if (y == CORD_EMPTY) return(x != CORD_EMPTY); if (x == CORD_EMPTY) return(-1); if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y)); @@ -147,7 +147,7 @@ int CORD_cmp(CORD x, CORD y) for(;;) { if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { - return(-1); + return(-1); } else { return(0); } @@ -163,12 +163,12 @@ int CORD_cmp(CORD x, CORD y) CORD_next(xpos); CORD_next(ypos); } else { - /* process as many characters as we can */ + /* process as many characters as we can */ register int result; - + if (avail > yavail) avail = yavail; result = strncmp(CORD_pos_cur_char_addr(xpos), - CORD_pos_cur_char_addr(ypos), avail); + CORD_pos_cur_char_addr(ypos), avail); if (result != 0) return(result); CORD_pos_advance(xpos, avail); CORD_pos_advance(ypos, avail); @@ -182,13 +182,13 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len) CORD_pos ypos; register size_t count; register long avail, yavail; - + CORD_set_pos(xpos, x, x_start); CORD_set_pos(ypos, y, y_start); for(count = 0; count < len;) { if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { - return(-1); + return(-1); } else { return(0); } @@ -205,14 +205,14 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len) CORD_next(ypos); count++; } else { - /* process as many characters as we can */ + /* process as many characters as we can */ register int result; - + if (avail > yavail) avail = yavail; count += avail; if (count > len) avail -= (count - len); result = strncmp(CORD_pos_cur_char_addr(xpos), - CORD_pos_cur_char_addr(ypos), (size_t)avail); + CORD_pos_cur_char_addr(ypos), (size_t)avail); if (result != 0) return(result); CORD_pos_advance(xpos, (size_t)avail); CORD_pos_advance(ypos, (size_t)avail); @@ -225,7 +225,7 @@ char * CORD_to_char_star(CORD x) { register size_t len = CORD_len(x); char * result = GC_MALLOC_ATOMIC(len + 1); - + if (result == 0) OUT_OF_MEMORY; CORD_fill_buf(x, 0, len, result); result[len] = '\0'; @@ -254,7 +254,7 @@ const char * CORD_to_const_char_star(CORD x) char CORD_fetch(CORD x, size_t i) { CORD_pos xpos; - + CORD_set_pos(xpos, x, i); if (!CORD_pos_valid(xpos)) ABORT("bad index?"); return(CORD_pos_fetch(xpos)); @@ -264,36 +264,36 @@ char CORD_fetch(CORD x, size_t i) int CORD_put_proc(char c, void * client_data) { register FILE * f = (FILE *)client_data; - + return(putc(c, f) == EOF); } int CORD_batched_put_proc(const char * s, void * client_data) { register FILE * f = (FILE *)client_data; - + return(fputs(s, f) == EOF); } - + int CORD_put(CORD x, FILE * f) { if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f)) { return(EOF); } else { - return(1); + return(1); } } typedef struct { - size_t pos; /* Current position in the cord */ - char target; /* Character we're looking for */ + size_t pos; /* Current position in the cord */ + char target; /* Character we're looking for */ } chr_data; int CORD_chr_proc(char c, void * client_data) { register chr_data * d = (chr_data *)client_data; - + if (c == d -> target) return(1); (d -> pos) ++; return(0); @@ -302,7 +302,7 @@ int CORD_chr_proc(char c, void * client_data) int CORD_rchr_proc(char c, void * client_data) { register chr_data * d = (chr_data *)client_data; - + if (c == d -> target) return(1); (d -> pos) --; return(0); @@ -312,48 +312,48 @@ int CORD_batched_chr_proc(const char *s, void * client_data) { register chr_data * d = (chr_data *)client_data; register char * occ = strchr(s, d -> target); - + if (occ == 0) { - d -> pos += strlen(s); - return(0); + d -> pos += strlen(s); + return(0); } else { - d -> pos += occ - s; - return(1); + d -> pos += occ - s; + return(1); } } size_t CORD_chr(CORD x, size_t i, int c) { chr_data d; - + d.pos = i; d.target = c; if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) { return(d.pos); } else { - return(CORD_NOT_FOUND); + return(CORD_NOT_FOUND); } } size_t CORD_rchr(CORD x, size_t i, int c) { chr_data d; - + d.pos = i; d.target = c; if (CORD_riter4(x, i, CORD_rchr_proc, &d)) { return(d.pos); } else { - return(CORD_NOT_FOUND); + return(CORD_NOT_FOUND); } } -/* Find the first occurrence of s in x at position start or later. */ -/* This uses an asymptotically poor algorithm, which should typically */ -/* perform acceptably. We compare the first few characters directly, */ -/* and call CORD_ncmp whenever there is a partial match. */ -/* This has the advantage that we allocate very little, or not at all. */ -/* It's very fast if there are few close misses. */ +/* Find the first occurrence of s in x at position start or later. */ +/* This uses an asymptotically poor algorithm, which should typically */ +/* perform acceptably. We compare the first few characters directly, */ +/* and call CORD_ncmp whenever there is a partial match. */ +/* This has the advantage that we allocate very little, or not at all. */ +/* It's very fast if there are few close misses. */ size_t CORD_str(CORD x, size_t start, CORD s) { CORD_pos xpos; @@ -361,14 +361,14 @@ size_t CORD_str(CORD x, size_t start, CORD s) size_t slen; register size_t start_len; const char * s_start; - unsigned long s_buf = 0; /* The first few characters of s */ - unsigned long x_buf = 0; /* Start of candidate substring. */ - /* Initialized only to make compilers */ - /* happy. */ + unsigned long s_buf = 0; /* The first few characters of s */ + unsigned long x_buf = 0; /* Start of candidate substring. */ + /* Initialized only to make compilers */ + /* happy. */ unsigned long mask = 0; register size_t i; register size_t match_pos; - + if (s == CORD_EMPTY) return(start); if (CORD_IS_STRING(s)) { s_start = s; @@ -391,17 +391,17 @@ size_t CORD_str(CORD x, size_t start, CORD s) CORD_next(xpos); } for (match_pos = start; ; match_pos++) { - if ((x_buf & mask) == s_buf) { - if (slen == start_len || - CORD_ncmp(x, match_pos + start_len, - s, start_len, slen - start_len) == 0) { - return(match_pos); - } - } - if ( match_pos == xlen - slen ) { - return(CORD_NOT_FOUND); - } - x_buf <<= 8; + if ((x_buf & mask) == s_buf) { + if (slen == start_len || + CORD_ncmp(x, match_pos + start_len, + s, start_len, slen - start_len) == 0) { + return(match_pos); + } + } + if ( match_pos == xlen - slen ) { + return(CORD_NOT_FOUND); + } + x_buf <<= 8; x_buf |= (unsigned char)CORD_pos_fetch(xpos); CORD_next(xpos); } @@ -442,16 +442,16 @@ CORD CORD_from_file_eager(FILE * f) { register int c; CORD_ec ecord; - + CORD_ec_init(ecord); for(;;) { c = getc(f); if (c == 0) { - /* Append the right number of NULs */ - /* Note that any string of NULs is rpresented in 4 words, */ - /* independent of its length. */ + /* Append the right number of NULs */ + /* Note that any string of NULs is rpresented in 4 words, */ + /* independent of its length. */ register size_t count = 1; - + CORD_ec_flush_buf(ecord); while ((c = getc(f)) == 0) count++; ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count)); @@ -463,18 +463,18 @@ CORD CORD_from_file_eager(FILE * f) return(CORD_balance(CORD_ec_to_cord(ecord))); } -/* The state maintained for a lazily read file consists primarily */ -/* of a large direct-mapped cache of previously read values. */ -/* We could rely more on stdio buffering. That would have 2 */ -/* disadvantages: */ -/* 1) Empirically, not all fseek implementations preserve the */ -/* buffer whenever they could. */ -/* 2) It would fail if 2 different sections of a long cord */ -/* were being read alternately. */ -/* We do use the stdio buffer for read ahead. */ -/* To guarantee thread safety in the presence of atomic pointer */ -/* writes, cache lines are always replaced, and never modified in */ -/* place. */ +/* The state maintained for a lazily read file consists primarily */ +/* of a large direct-mapped cache of previously read values. */ +/* We could rely more on stdio buffering. That would have 2 */ +/* disadvantages: */ +/* 1) Empirically, not all fseek implementations preserve the */ +/* buffer whenever they could. */ +/* 2) It would fail if 2 different sections of a long cord */ +/* were being read alternately. */ +/* We do use the stdio buffer for read ahead. */ +/* To guarantee thread safety in the presence of atomic pointer */ +/* writes, cache lines are always replaced, and never modified in */ +/* place. */ # define LOG_CACHE_SZ 14 # define CACHE_SZ (1 << LOG_CACHE_SZ) @@ -484,12 +484,12 @@ CORD CORD_from_file_eager(FILE * f) typedef struct { size_t tag; char data[LINE_SZ]; - /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ */ + /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ */ } cache_line; typedef struct { FILE * lf_file; - size_t lf_current; /* Current file pointer value */ + size_t lf_current; /* Current file pointer value */ cache_line * volatile lf_cache[CACHE_SZ/LINE_SZ]; } lf_state; @@ -501,7 +501,7 @@ typedef struct { typedef struct { lf_state * state; - size_t file_pos; /* Position of needed character. */ + size_t file_pos; /* Position of needed character. */ cache_line * new_cache; } refill_data; @@ -515,14 +515,14 @@ refill_data * client_data; size_t line_start = LINE_START(file_pos); size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos)); cache_line * new_cache = client_data -> new_cache; - + if (line_start != state -> lf_current && fseek(f, line_start, SEEK_SET) != 0) { - ABORT("fseek failed"); + ABORT("fseek failed"); } if (fread(new_cache -> data, sizeof(char), LINE_SZ, f) - <= file_pos - line_start) { - ABORT("fread failed"); + <= file_pos - line_start) { + ABORT("fread failed"); } new_cache -> tag = DIV_LINE_SZ(file_pos); /* Store barrier goes here. */ @@ -535,47 +535,50 @@ char CORD_lf_func(size_t i, void * client_data) { register lf_state * state = (lf_state *)client_data; register cache_line * volatile * cl_addr = - &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]); + &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]); register cache_line * cl = (cache_line *)ATOMIC_READ(cl_addr); - + if (cl == 0 || cl -> tag != DIV_LINE_SZ(i)) { - /* Cache miss */ - refill_data rd; - + /* Cache miss */ + refill_data rd; + rd.state = state; rd.file_pos = i; rd.new_cache = GC_NEW_ATOMIC(cache_line); if (rd.new_cache == 0) OUT_OF_MEMORY; return((char)(GC_word) - GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd)); + GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd)); } return(cl -> data[MOD_LINE_SZ(i)]); -} +} /*ARGSUSED*/ -void CORD_lf_close_proc(void * obj, void * client_data) +void CORD_lf_close_proc(void * obj, void * client_data) { if (fclose(((lf_state *)obj) -> lf_file) != 0) { - ABORT("CORD_lf_close_proc: fclose failed"); + ABORT("CORD_lf_close_proc: fclose failed"); } -} +} CORD CORD_from_file_lazy_inner(FILE * f, size_t len) { register lf_state * state = GC_NEW(lf_state); register int i; - + if (state == 0) OUT_OF_MEMORY; if (len != 0) { - /* Dummy read to force buffer allocation. */ - /* This greatly increases the probability */ - /* of avoiding deadlock if buffer allocation */ - /* is redirected to GC_malloc and the */ - /* world is multithreaded. */ - char buf[1]; - - (void) fread(buf, 1, 1, f); - rewind(f); + /* Dummy read to force buffer allocation. */ + /* This greatly increases the probability */ + /* of avoiding deadlock if buffer allocation */ + /* is redirected to GC_malloc and the */ + /* world is multithreaded. */ + char buf[1]; + + if (fread(buf, 1, 1, f) > 1) { + /* Just to suppress "unused result" compiler warning. */ + ABORT("fread unexpected result"); + } + rewind(f); } state -> lf_file = f; for (i = 0; i < CACHE_SZ/LINE_SZ; i++) { @@ -589,7 +592,7 @@ CORD CORD_from_file_lazy_inner(FILE * f, size_t len) CORD CORD_from_file_lazy(FILE * f) { register long len; - + if (fseek(f, 0l, SEEK_END) != 0) { ABORT("Bad fd argument - fseek failed"); } @@ -605,7 +608,7 @@ CORD CORD_from_file_lazy(FILE * f) CORD CORD_from_file(FILE * f) { register long len; - + if (fseek(f, 0l, SEEK_END) != 0) { ABORT("Bad fd argument - fseek failed"); } -- cgit v1.2.1 From eea8b2cb1fe9e32a4b6ab92f56c8ea08eda499a4 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 7 May 2011 19:04:25 +0000 Subject: 2011-05-07 Ivan Maidanski * alloc.c (GC_clear_a_few_frames): Use BZERO(). * mark_rts.c (GC_clear_roots, GC_rebuild_root_index): Ditto. * reclaim.c (GC_start_reclaim): Ditto. * blacklst.c (total_stack_black_listed): Remove "len" local variable. * dbg_mlc.c (GC_generate_random_valid_address): Replace "for" statement with "do-while" one. * dyn_load.c (GC_register_dynamic_libraries, GC_register_dynlib_callback): Remove redundant parentheses. --HG-- branch : bdwgc --- ChangeLog | 12 ++++++++++++ alloc.c | 4 +--- blacklst.c | 3 +-- dbg_mlc.c | 12 +++++------- dyn_load.c | 20 +++++++------------- mark_rts.c | 8 ++------ reclaim.c | 7 +------ 7 files changed, 29 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6131fa4d..d3a23113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-07 Ivan Maidanski + + * alloc.c (GC_clear_a_few_frames): Use BZERO(). + * mark_rts.c (GC_clear_roots, GC_rebuild_root_index): Ditto. + * reclaim.c (GC_start_reclaim): Ditto. + * blacklst.c (total_stack_black_listed): Remove "len" local + variable. + * dbg_mlc.c (GC_generate_random_valid_address): Replace "for" + statement with "do-while" one. + * dyn_load.c (GC_register_dynamic_libraries, + GC_register_dynlib_callback): Remove redundant parentheses. + 2011-05-06 Ivan Maidanski * cord/cordxtra.c (CORD_from_file_lazy_inner): Suppress diff --git a/alloc.c b/alloc.c index df77781f..59253521 100644 --- a/alloc.c +++ b/alloc.c @@ -285,9 +285,7 @@ STATIC void GC_clear_a_few_frames(void) # define CLEAR_NWORDS 64 # endif volatile word frames[CLEAR_NWORDS]; - int i; - - for (i = 0; i < CLEAR_NWORDS; i++) frames[i] = 0; + BZERO((word *)frames, CLEAR_NWORDS * sizeof(word)); } /* Heap size at which we need a collection to avoid expanding past */ diff --git a/blacklst.c b/blacklst.c index a6df6933..9fd00167 100644 --- a/blacklst.c +++ b/blacklst.c @@ -281,8 +281,7 @@ static word total_stack_black_listed(void) for (i = 0; i < GC_n_heap_sects; i++) { struct hblk * start = (struct hblk *) GC_heap_sects[i].hs_start; - size_t len = (word) GC_heap_sects[i].hs_bytes; - struct hblk * endp1 = start + len/HBLKSIZE; + struct hblk * endp1 = start + GC_heap_sects[i].hs_bytes/HBLKSIZE; total += GC_number_stack_black_listed(start, endp1); } diff --git a/dbg_mlc.c b/dbg_mlc.c index c3d9e77f..c2820602 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -171,13 +171,11 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); { ptr_t result; ptr_t base; - for (;;) { - result = GC_generate_random_heap_address(); - base = GC_base(result); - if (0 == base) continue; - if (!GC_is_marked(base)) continue; - return result; - } + do { + result = GC_generate_random_heap_address(); + base = GC_base(result); + } while (base == 0 || !GC_is_marked(base)); + return result; } /* Print back trace for p */ diff --git a/dyn_load.c b/dyn_load.c index 9cc854db..a00e0102 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -189,9 +189,7 @@ GC_INNER void GC_register_dynamic_libraries(void) struct link_map *lm = GC_FirstDLOpenedLinkMap(); - for (lm = GC_FirstDLOpenedLinkMap(); - lm != (struct link_map *) 0; lm = lm->l_next) - { + for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) { ElfW(Ehdr) * e; ElfW(Phdr) * p; unsigned long offset; @@ -205,7 +203,7 @@ GC_INNER void GC_register_dynamic_libraries(void) # endif p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff)); offset = ((unsigned long)(lm->l_addr)); - for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) { + for( i = 0; i < (int)e->e_phnum; i++, p++ ) { switch( p->p_type ) { case PT_LOAD: { @@ -454,7 +452,7 @@ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, return -1; p = info->dlpi_phdr; - for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) { + for( i = 0; i < (int)info->dlpi_phnum; i++, p++ ) { switch( p->p_type ) { # ifdef PT_GNU_RELRO case PT_GNU_RELRO: @@ -681,8 +679,7 @@ GC_INNER void GC_register_dynamic_libraries(void) } # endif lm = GC_FirstDLOpenedLinkMap(); - for (lm = GC_FirstDLOpenedLinkMap(); - lm != (struct link_map *) 0; lm = lm->l_next) + for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) { ElfW(Ehdr) * e; ElfW(Phdr) * p; @@ -697,7 +694,7 @@ GC_INNER void GC_register_dynamic_libraries(void) # endif p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff)); offset = ((unsigned long)(lm->l_addr)); - for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) { + for( i = 0; i < (int)e->e_phnum; i++, p++ ) { switch( p->p_type ) { case PT_LOAD: { @@ -1066,7 +1063,6 @@ GC_INNER void GC_register_dynamic_libraries(void) /* For each region in this module */ for (region = 0; region < moduleinfo.lmi_nregion; region++) { - /* Get the region information */ status = ldr_inq_region(mypid, moduleid, region, ®ioninfo, regioninfosize, ®ionreturnsize); @@ -1471,10 +1467,8 @@ GC_INNER GC_bool GC_register_main_static_data(void) for (q = p -> lf_ls; q != NIL; q = q -> ls_next) { if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK) == PCR_IL_SegFlags_Traced_on) { - GC_add_roots_inner - ((char *)(q -> ls_addr), - (char *)(q -> ls_addr) + q -> ls_bytes, - TRUE); + GC_add_roots_inner((char *)(q -> ls_addr), + (char *)(q -> ls_addr) + q -> ls_bytes, TRUE); } } } diff --git a/mark_rts.c b/mark_rts.c index 3ae8e614..02acf3bd 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -251,10 +251,7 @@ GC_API void GC_CALL GC_clear_roots(void) n_root_sets = 0; GC_root_size = 0; # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) - { - int i; - for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; - } + BZERO(GC_root_index, RT_SIZE * sizeof(void *)); # endif UNLOCK(); } @@ -273,8 +270,7 @@ STATIC void GC_remove_root_at_pos(int i) STATIC void GC_rebuild_root_index(void) { int i; - - for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; + BZERO(GC_root_index, RT_SIZE * sizeof(void *)); for (i = 0; i < n_root_sets; i++) add_roots_to_index(GC_static_roots + i); } diff --git a/reclaim.c b/reclaim.c index c9e8e530..68dd1b98 100644 --- a/reclaim.c +++ b/reclaim.c @@ -511,8 +511,6 @@ GC_INNER void GC_start_reclaim(GC_bool report_if_found) for (kind = 0; kind < GC_n_kinds; kind++) { void **fop; void **lim; - struct hblk ** rlp; - struct hblk ** rlim; struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list; GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0); @@ -530,10 +528,7 @@ GC_INNER void GC_start_reclaim(GC_bool report_if_found) } } /* otherwise free list objects are marked, */ /* and its safe to leave them */ - rlim = rlist + MAXOBJGRANULES+1; - for( rlp = rlist; rlp < rlim; rlp++ ) { - *rlp = 0; - } + BZERO(rlist, (MAXOBJGRANULES + 1) * sizeof(void *)); } -- cgit v1.2.1 From 9ec80de00c291b5734a13c1a4ffdeaf4108fbf4b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 7 May 2011 19:10:05 +0000 Subject: 2011-05-07 Ivan Maidanski (really Thorsten Glaser) * include/private/gcconfig.h (NO_GETCONTEXT): Do not use getcontext(2) on m68k because it is not implemented there. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ include/private/gcconfig.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d3a23113..b3c83a1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-07 Ivan Maidanski (really Thorsten Glaser) + + * include/private/gcconfig.h (NO_GETCONTEXT): Do not use + getcontext(2) on m68k because it is not implemented there. + 2011-05-07 Ivan Maidanski * alloc.c (GC_clear_a_few_frames): Use BZERO(). diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 301b200e..6984c720 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2404,7 +2404,7 @@ #if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ || defined(OPENBSD) || defined(ARM32) \ || defined(MIPS) || defined(AVR32))) \ - || (defined(LINUX) && defined(SPARC)) \ + || (defined(LINUX) && (defined(SPARC) || defined(M68K)) \ || (defined(RTEMS) && defined(I386))) && !defined(NO_GETCONTEXT) # define NO_GETCONTEXT #endif -- cgit v1.2.1 From 51a047f6a133fe2783c9edf0ff6c513836f6efa4 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 7 May 2011 19:15:21 +0000 Subject: 2011-05-07 Ivan Maidanski * include/private/gcconfig.h (NO_GETCONTEXT): Add missing ')'. --HG-- branch : bdwgc --- ChangeLog | 4 ++++ include/private/gcconfig.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b3c83a1d..796c6d1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-07 Ivan Maidanski + + * include/private/gcconfig.h (NO_GETCONTEXT): Add missing ')'. + 2011-05-07 Ivan Maidanski (really Thorsten Glaser) * include/private/gcconfig.h (NO_GETCONTEXT): Do not use diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 6984c720..22ce8a28 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2404,7 +2404,7 @@ #if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ || defined(OPENBSD) || defined(ARM32) \ || defined(MIPS) || defined(AVR32))) \ - || (defined(LINUX) && (defined(SPARC) || defined(M68K)) \ + || (defined(LINUX) && (defined(SPARC) || defined(M68K))) \ || (defined(RTEMS) && defined(I386))) && !defined(NO_GETCONTEXT) # define NO_GETCONTEXT #endif -- cgit v1.2.1 From 52cedad8d4a64136d87e85b50f52428265a87c7f Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 8 May 2011 21:21:44 +0000 Subject: 2011-05-08 Ivan Maidanski * include/gc_inline.h (GC_MALLOC_WORDS, GC_CONS): Add missing parentheses. * include/gc_typed.h (GC_get_bit, GC_set_bit, GC_CALLOC_EXPLICITLY_TYPED): Ditto. --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ include/gc_inline.h | 4 ++-- include/gc_typed.h | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 796c6d1f..b044d661 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-08 Ivan Maidanski + + * include/gc_inline.h (GC_MALLOC_WORDS, GC_CONS): Add missing + parentheses. + * include/gc_typed.h (GC_get_bit, GC_set_bit, + GC_CALLOC_EXPLICITLY_TYPED): Ditto. + 2011-05-07 Ivan Maidanski * include/private/gcconfig.h (NO_GETCONTEXT): Add missing ')'. diff --git a/include/gc_inline.h b/include/gc_inline.h index 312ed61b..e2bb881e 100644 --- a/include/gc_inline.h +++ b/include/gc_inline.h @@ -122,7 +122,7 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ - *(void **)result = 0); \ + *(void **)(result) = 0); \ } # define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \ @@ -139,7 +139,7 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ - *(void **)result = (void *)(first)); \ + *(void **)(result) = (void *)(first)); \ ((void **)(result))[1] = (void *)(second); \ } diff --git a/include/gc_typed.h b/include/gc_typed.h index 10111cdb..a794fbbe 100644 --- a/include/gc_typed.h +++ b/include/gc_typed.h @@ -39,9 +39,9 @@ typedef GC_word * GC_bitmap; #define GC_WORDSZ (8 * sizeof(GC_word)) #define GC_get_bit(bm, index) \ - (((bm)[index / GC_WORDSZ] >> (index % GC_WORDSZ)) & 1) + (((bm)[(index) / GC_WORDSZ] >> ((index) % GC_WORDSZ)) & 1) #define GC_set_bit(bm, index) \ - (bm)[index / GC_WORDSZ] |= ((GC_word)1 << (index % GC_WORDSZ)) + ((bm)[(index) / GC_WORDSZ] |= (GC_word)1 << ((index) % GC_WORDSZ)) #define GC_WORD_OFFSET(t, f) (offsetof(t,f) / sizeof(GC_word)) #define GC_WORD_LEN(t) (sizeof(t) / sizeof(GC_word)) #define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ - 1) / GC_WORDSZ) @@ -99,7 +99,7 @@ GC_API void * GC_CALL GC_calloc_explicitly_typed(size_t /* nelements */, #ifdef GC_DEBUG # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes) -# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n * bytes) +# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC((n) * (bytes)) #else # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \ GC_malloc_explicitly_typed(bytes, d) -- cgit v1.2.1 From 62cdf397582f7d171992d0ddb87f049f288875d5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 10 May 2011 09:58:24 +0000 Subject: 2011-05-10 Ivan Maidanski * include/gc.h (GC_register_my_thread): Refine the comment. --HG-- branch : bdwgc --- ChangeLog | 4 ++++ include/gc.h | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index b044d661..49036fd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-10 Ivan Maidanski + + * include/gc.h (GC_register_my_thread): Refine the comment. + 2011-05-08 Ivan Maidanski * include/gc_inline.h (GC_MALLOC_WORDS, GC_CONS): Add missing diff --git a/include/gc.h b/include/gc.h index e702fd25..ae80fd95 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1051,6 +1051,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */, /* GC_use_threads_discovery() is called at start-up. Except for the */ /* latter case, the explicit call is normally required for threads */ /* created by third-party libraries. */ + /* A manually registered thread requires manual unregistering. */ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *); /* Unregister the current thread. Only an explicitly registered */ -- cgit v1.2.1 From e794bd6d1b431cad0ca62e1f702918a337d50457 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 10 May 2011 11:07:13 +0000 Subject: 2011-05-10 Ivan Maidanski * include/gc.h (GC_HIDE_POINTER, GC_REVEAL_POINTER): Define unconditionally (do not test GC_I_HIDE_POINTERS); update the comment. * include/gc.h (HIDE_POINTER, REVEAL_POINTER): Define as alias to GC_HIDE/REVEAL_POINTER, respectively. * include/private/gc_pmark.h (GC_I_HIDE_POINTERS): Do not define. * include/private/gc_priv.h (GC_I_HIDE_POINTERS): Ditto. --HG-- branch : bdwgc --- ChangeLog | 10 ++++++++++ include/gc.h | 26 ++++++++++++-------------- include/private/gc_pmark.h | 3 --- include/private/gc_priv.h | 1 - 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49036fd5..e2108958 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-05-10 Ivan Maidanski + + * include/gc.h (GC_HIDE_POINTER, GC_REVEAL_POINTER): Define + unconditionally (do not test GC_I_HIDE_POINTERS); update the + comment. + * include/gc.h (HIDE_POINTER, REVEAL_POINTER): Define as alias to + GC_HIDE/REVEAL_POINTER, respectively. + * include/private/gc_pmark.h (GC_I_HIDE_POINTERS): Do not define. + * include/private/gc_priv.h (GC_I_HIDE_POINTERS): Ditto. + 2011-05-10 Ivan Maidanski * include/gc.h (GC_register_my_thread): Refine the comment. diff --git a/include/gc.h b/include/gc.h index ae80fd95..e94a943e 100644 --- a/include/gc.h +++ b/include/gc.h @@ -958,20 +958,18 @@ GC_API void GC_CALLBACK GC_ignore_warn_proc(char *, GC_word); /* Note that putting pointers in atomic objects or in */ /* non-pointer slots of "typed" objects is equivalent to */ /* disguising them in this way, and may have other advantages. */ -#if defined(I_HIDE_POINTERS) || defined(GC_I_HIDE_POINTERS) - typedef GC_word GC_hidden_pointer; -# define HIDE_POINTER(p) (~(GC_hidden_pointer)(p)) -# define REVEAL_POINTER(p) ((void *)HIDE_POINTER(p)) - /* Converting a hidden pointer to a real pointer requires verifying */ - /* that the object still exists. This involves acquiring the */ - /* allocator lock to avoid a race with the collector. */ -#endif /* I_HIDE_POINTERS */ - -/* The GC-prefixed symbols are preferred for new code (I_HIDE_POINTERS, */ -/* HIDE_POINTER and REVEAL_POINTER remain for compatibility). */ -#ifdef GC_I_HIDE_POINTERS -# define GC_HIDE_POINTER(p) HIDE_POINTER(p) -# define GC_REVEAL_POINTER(p) REVEAL_POINTER(p) +typedef GC_word GC_hidden_pointer; +#define GC_HIDE_POINTER(p) (~(GC_hidden_pointer)(p)) +/* Converting a hidden pointer to a real pointer requires verifying */ +/* that the object still exists. This involves acquiring the */ +/* allocator lock to avoid a race with the collector. */ +#define GC_REVEAL_POINTER(p) ((void *)GC_HIDE_POINTER(p)) + +#ifdef I_HIDE_POINTERS + /* This exists only for compatibility (the GC-prefixed symbols are */ + /* preferred for new code). */ +# define HIDE_POINTER(p) GC_HIDE_POINTER(p) +# define REVEAL_POINTER(p) GC_REVEAL_POINTER(p) #endif typedef void * (GC_CALLBACK * GC_fn_type)(void * /* client_data */); diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index d99e0b7f..30640505 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -35,9 +35,6 @@ #endif #ifndef GC_MARK_H -# ifndef GC_H -# define GC_I_HIDE_POINTERS /* to get GC_HIDE_POINTER() and friends */ -# endif # include "../gc_mark.h" #endif diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index c02def1b..84d40f54 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -43,7 +43,6 @@ # endif #ifndef GC_H -# define GC_I_HIDE_POINTERS /* to get GC_HIDE_POINTER() and friends */ # include "../gc.h" #endif -- cgit v1.2.1 From ae1866e11a9c87539f6764b785bebb158835cf2b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 10 May 2011 12:53:40 +0000 Subject: 2011-05-10 Ivan Maidanski * pthread_support.c (GC_unregister_my_thread): Call pthread_self only once. * win32_threads.c (GC_pthread_start_inner): Ditto. * pthread_support.c (GC_unregister_my_thread): Add debug output. * win32_threads.c (GC_unregister_my_thread): Ditto. * pthread_support.c (GC_register_my_thread, GC_start_rtn_prepare_thread): Rename "my_pthread" local variable to "self". --HG-- branch : bdwgc --- ChangeLog | 11 +++++++++++ pthread_support.c | 21 ++++++++++++--------- win32_threads.c | 9 ++++++--- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index e2108958..283dc2b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-10 Ivan Maidanski + + * pthread_support.c (GC_unregister_my_thread): Call pthread_self + only once. + * win32_threads.c (GC_pthread_start_inner): Ditto. + * pthread_support.c (GC_unregister_my_thread): Add debug output. + * win32_threads.c (GC_unregister_my_thread): Ditto. + * pthread_support.c (GC_register_my_thread, + GC_start_rtn_prepare_thread): Rename "my_pthread" local variable + to "self". + 2011-05-10 Ivan Maidanski * include/gc.h (GC_HIDE_POINTER, GC_REVEAL_POINTER): Define diff --git a/pthread_support.c b/pthread_support.c index 575ac9d3..34793248 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1164,16 +1164,20 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, GC_API int GC_CALL GC_unregister_my_thread(void) { + pthread_t self = pthread_self(); GC_thread me; IF_CANCEL(int cancel_state;) DCL_LOCK_STATE; +# ifdef DEBUG_THREADS + GC_log_printf("Unregistering thread 0x%x\n", (unsigned)self); +# endif LOCK(); DISABLE_CANCEL(cancel_state); /* Wait for any GC that may be marking from our stack to */ /* complete before we remove this thread. */ GC_wait_for_gc_completion(FALSE); - me = GC_lookup_thread(pthread_self()); + me = GC_lookup_thread(self); GC_ASSERT(!(me -> flags & FINISHED)); # if defined(THREAD_LOCAL_ALLOC) GC_destroy_thread_local(&(me->tlfs)); @@ -1186,7 +1190,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) } # endif if (me -> flags & DETACHED) { - GC_delete_thread(pthread_self()); + GC_delete_thread(self); } else { me -> flags |= FINISHED; } @@ -1363,7 +1367,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) { - pthread_t my_pthread = pthread_self(); + pthread_t self = pthread_self(); GC_thread me; DCL_LOCK_STATE; @@ -1371,9 +1375,9 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) ABORT("Threads explicit registering is not previously enabled"); LOCK(); - me = GC_lookup_thread(my_pthread); + me = GC_lookup_thread(self); if (0 == me) { - me = GC_register_my_thread_inner(sb, my_pthread); + me = GC_register_my_thread_inner(sb, self); me -> flags |= DETACHED; /* Treat as detached, since we do not need to worry about */ /* pointer results. */ @@ -1404,17 +1408,16 @@ GC_INNER void * GC_start_rtn_prepare_thread(void *(**pstart)(void *), struct GC_stack_base *sb, void *arg) { struct start_info * si = arg; + pthread_t self = pthread_self(); GC_thread me; - pthread_t my_pthread; DCL_LOCK_STATE; - my_pthread = pthread_self(); # ifdef DEBUG_THREADS GC_log_printf("Starting thread 0x%x, pid = %ld, sp = %p\n", - (unsigned)my_pthread, (long)getpid(), &arg); + (unsigned)self, (long)getpid(), &arg); # endif LOCK(); - me = GC_register_my_thread_inner(sb, my_pthread); + me = GC_register_my_thread_inner(sb, self); me -> flags = si -> flags; # if defined(THREAD_LOCAL_ALLOC) GC_init_thread_local(&(me->tlfs)); diff --git a/win32_threads.c b/win32_threads.c index 026f1629..33227cae 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -729,6 +729,10 @@ GC_API int GC_CALL GC_unregister_my_thread(void) { DCL_LOCK_STATE; +# ifdef DEBUG_THREADS + GC_log_printf("Unregistering thread 0x%lx\n", (long)GetCurrentThreadId()); +# endif + /* FIXME: is GC_wait_for_gc_completion(FALSE) needed here? */ if (GC_win32_dll_threads) { # if defined(THREAD_LOCAL_ALLOC) @@ -2448,9 +2452,8 @@ GC_INNER void GC_thr_init(void) pthread_cleanup_pop(1); # ifdef DEBUG_THREADS - GC_log_printf("thread %p(0x%lx) returned from start routine\n", - GC_PTHREAD_PTRVAL(pthread_self()), - (long)GetCurrentThreadId()); + GC_log_printf("thread %p(0x%x) returned from start routine\n", + GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); # endif return(result); } -- cgit v1.2.1 From 3646e1bfbcff575e3a1304b14ec0b3fed493107c Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 10 May 2011 14:15:58 +0000 Subject: 2011-05-10 Ivan Maidanski * pthread_start.c (GC_start_rtn_prepare_thread): Change return type to GC_thread. * pthread_start.c (GC_inner_start_routine): Pass the current thread descriptor to pthread_cleanup_push (same as in win32_threads.c). * pthread_stop_world.c (GC_push_all_stacks): Rename "me" local variable to "self". * win32_threads.c (GC_push_all_stacks): Ditto. * pthread_stop_world.c (GC_suspend_all, GC_start_world): Rename "my_thread" local variable to "self". * pthread_support.c (GC_unregister_my_thread_inner): New static function. * pthread_support.c (GC_unregister_my_thread, GC_thread_exit_proc): Use GC_unregister_my_thread_inner. * win32_threads.c (GC_register_my_thread, GC_unregister_my_thread, GC_do_blocking_inner): Rename "t" local variable to "thread_id". * win32_threads.c (GC_wait_marker, GC_notify_all_marker): Rename "id" local variable to "thread_id". --HG-- branch : bdwgc --- ChangeLog | 21 +++++++++++++++++++++ pthread_start.c | 4 ++-- pthread_stop_world.c | 22 +++++++++++----------- pthread_support.c | 43 +++++++++++++++++++++++++++---------------- win32_threads.c | 37 ++++++++++++++++++------------------- 5 files changed, 79 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 283dc2b2..be0b4b45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-05-10 Ivan Maidanski + + * pthread_start.c (GC_start_rtn_prepare_thread): Change return + type to GC_thread. + * pthread_start.c (GC_inner_start_routine): Pass the current + thread descriptor to pthread_cleanup_push (same as in + win32_threads.c). + * pthread_stop_world.c (GC_push_all_stacks): Rename "me" local + variable to "self". + * win32_threads.c (GC_push_all_stacks): Ditto. + * pthread_stop_world.c (GC_suspend_all, GC_start_world): Rename + "my_thread" local variable to "self". + * pthread_support.c (GC_unregister_my_thread_inner): New static + function. + * pthread_support.c (GC_unregister_my_thread, + GC_thread_exit_proc): Use GC_unregister_my_thread_inner. + * win32_threads.c (GC_register_my_thread, GC_unregister_my_thread, + GC_do_blocking_inner): Rename "t" local variable to "thread_id". + * win32_threads.c (GC_wait_marker, GC_notify_all_marker): Rename + "id" local variable to "thread_id". + 2011-05-10 Ivan Maidanski * pthread_support.c (GC_unregister_my_thread): Call pthread_self diff --git a/pthread_start.c b/pthread_start.c index 48c2d95a..c3a01c41 100644 --- a/pthread_start.c +++ b/pthread_start.c @@ -41,7 +41,7 @@ #include #include -GC_INNER void * GC_start_rtn_prepare_thread(void *(**pstart)(void *), +GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *), void **pstart_arg, struct GC_stack_base *sb, void *arg); GC_INNER void GC_thread_exit_proc(void *arg); @@ -56,7 +56,7 @@ void * GC_CALLBACK GC_inner_start_routine(struct GC_stack_base *sb, void *arg) GC_thread me = GC_start_rtn_prepare_thread(&start, &start_arg, sb, arg); # ifndef NACL - pthread_cleanup_push(GC_thread_exit_proc, 0); + pthread_cleanup_push(GC_thread_exit_proc, me); # endif result = (*start)(start_arg); # ifdef DEBUG_THREADS diff --git a/pthread_stop_world.c b/pthread_stop_world.c index d7680e42..feb70a3b 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -297,18 +297,18 @@ GC_INNER void GC_push_all_stacks(void) ptr_t lo, hi; /* On IA64, we also need to scan the register backing store. */ IF_IA64(ptr_t bs_lo; ptr_t bs_hi;) - pthread_t me = pthread_self(); + pthread_t self = pthread_self(); word total_size = 0; if (!GC_thr_initialized) GC_thr_init(); # ifdef DEBUG_THREADS - GC_log_printf("Pushing stacks from thread 0x%x\n", (unsigned)me); + GC_log_printf("Pushing stacks from thread 0x%x\n", (unsigned)self); # endif for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { if (p -> flags & FINISHED) continue; ++nthreads; - if (THREAD_EQUAL(p -> id, me)) { + if (THREAD_EQUAL(p -> id, self)) { GC_ASSERT(!p->thread_blocked); # ifdef SPARC lo = (ptr_t)GC_save_regs_in_stack(); @@ -351,10 +351,10 @@ GC_INNER void GC_push_all_stacks(void) GC_log_printf("Reg stack for thread 0x%x = [%p,%p)\n", (unsigned)p -> id, bs_lo, bs_hi); # endif - /* FIXME: This (if p->id==me) may add an unbounded number of */ - /* entries, and hence overflow the mark stack, which is bad. */ + /* FIXME: This (if p->id==self) may add an unbounded number of */ + /* entries, and hence overflow the mark stack, which is bad. */ GC_push_all_register_sections(bs_lo, bs_hi, - THREAD_EQUAL(p -> id, me), + THREAD_EQUAL(p -> id, self), p -> traced_stack_sect); total_size += bs_hi - bs_lo; /* bs_lo <= bs_hi */ # endif @@ -406,15 +406,15 @@ STATIC int GC_suspend_all(void) # ifndef GC_OPENBSD_THREADS int result; # endif - pthread_t my_thread = pthread_self(); + pthread_t self = pthread_self(); # ifdef DEBUG_THREADS - GC_stopping_thread = my_thread; + GC_stopping_thread = self; GC_stopping_pid = getpid(); # endif for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { - if (!THREAD_EQUAL(p -> id, my_thread)) { + if (!THREAD_EQUAL(p -> id, self)) { if (p -> flags & FINISHED) continue; if (p -> thread_blocked) /* Will wait */ continue; # ifndef GC_OPENBSD_THREADS @@ -716,7 +716,7 @@ GC_INNER void GC_stop_world(void) GC_INNER void GC_start_world(void) { # ifndef NACL - pthread_t my_thread = pthread_self(); + pthread_t self = pthread_self(); register int i; register GC_thread p; # ifndef GC_OPENBSD_THREADS @@ -736,7 +736,7 @@ GC_INNER void GC_start_world(void) # endif for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { - if (!THREAD_EQUAL(p -> id, my_thread)) { + if (!THREAD_EQUAL(p -> id, self)) { if (p -> flags & FINISHED) continue; if (p -> thread_blocked) continue; # ifndef GC_OPENBSD_THREADS diff --git a/pthread_support.c b/pthread_support.c index 34793248..a6a5a5a3 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1162,22 +1162,11 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, return client_data; /* result */ } -GC_API int GC_CALL GC_unregister_my_thread(void) +STATIC void GC_unregister_my_thread_inner(GC_thread me) { - pthread_t self = pthread_self(); - GC_thread me; - IF_CANCEL(int cancel_state;) - DCL_LOCK_STATE; - # ifdef DEBUG_THREADS - GC_log_printf("Unregistering thread 0x%x\n", (unsigned)self); + GC_log_printf("Unregistering thread 0x%x\n", (unsigned)pthread_self()); # endif - LOCK(); - DISABLE_CANCEL(cancel_state); - /* Wait for any GC that may be marking from our stack to */ - /* complete before we remove this thread. */ - GC_wait_for_gc_completion(FALSE); - me = GC_lookup_thread(self); GC_ASSERT(!(me -> flags & FINISHED)); # if defined(THREAD_LOCAL_ALLOC) GC_destroy_thread_local(&(me->tlfs)); @@ -1190,13 +1179,27 @@ GC_API int GC_CALL GC_unregister_my_thread(void) } # endif if (me -> flags & DETACHED) { - GC_delete_thread(self); + GC_delete_thread(pthread_self()); } else { me -> flags |= FINISHED; } # if defined(THREAD_LOCAL_ALLOC) GC_remove_specific(GC_thread_key); # endif +} + +GC_API int GC_CALL GC_unregister_my_thread(void) +{ + pthread_t self = pthread_self(); + IF_CANCEL(int cancel_state;) + DCL_LOCK_STATE; + + LOCK(); + DISABLE_CANCEL(cancel_state); + /* Wait for any GC that may be marking from our stack to */ + /* complete before we remove this thread. */ + GC_wait_for_gc_completion(FALSE); + GC_unregister_my_thread_inner(GC_lookup_thread(self)); RESTORE_CANCEL(cancel_state); UNLOCK(); return GC_SUCCESS; @@ -1209,7 +1212,15 @@ GC_API int GC_CALL GC_unregister_my_thread(void) /* resources or id anyway. */ GC_INNER void GC_thread_exit_proc(void *arg) { - GC_unregister_my_thread(); + IF_CANCEL(int cancel_state;) + DCL_LOCK_STATE; + + LOCK(); + DISABLE_CANCEL(cancel_state); + GC_wait_for_gc_completion(FALSE); + GC_unregister_my_thread_inner((GC_thread)arg); + RESTORE_CANCEL(cancel_state); + UNLOCK(); } GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) @@ -1403,7 +1414,7 @@ struct start_info { /* Called from GC_inner_start_routine(). Defined in this file to */ /* minimize the number of include files in pthread_start.c (because */ /* sem_t and sem_post() are not used that file directly). */ -GC_INNER void * GC_start_rtn_prepare_thread(void *(**pstart)(void *), +GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *), void **pstart_arg, struct GC_stack_base *sb, void *arg) { diff --git a/win32_threads.c b/win32_threads.c index 33227cae..a9b406ab 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -707,7 +707,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) { - DWORD t = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); DCL_LOCK_STATE; if (GC_need_to_lock == FALSE) @@ -715,8 +715,8 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) /* We lock here, since we want to wait for an ongoing GC. */ LOCK(); - if (0 == GC_lookup_thread_inner(t)) { - GC_register_my_thread_inner(sb, t); + if (0 == GC_lookup_thread_inner(thread_id)) { + GC_register_my_thread_inner(sb, thread_id); UNLOCK(); return GC_SUCCESS; } else { @@ -743,15 +743,15 @@ GC_API int GC_CALL GC_unregister_my_thread(void) GC_delete_thread(GetCurrentThreadId()); # endif } else { - DWORD t = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); LOCK(); # if defined(THREAD_LOCAL_ALLOC) { - GC_thread me = GC_lookup_thread_inner(t); + GC_thread me = GC_lookup_thread_inner(thread_id); GC_destroy_thread_local(&(me->tlfs)); } # endif - GC_delete_thread(t); + GC_delete_thread(thread_id); UNLOCK(); } return GC_SUCCESS; @@ -765,7 +765,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) { struct blocking_data * d = (struct blocking_data *) data; - DWORD t = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); GC_thread me; # ifdef IA64 ptr_t stack_ptr = GC_save_regs_in_stack(); @@ -773,7 +773,7 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) DCL_LOCK_STATE; LOCK(); - me = GC_lookup_thread_inner(t); + me = GC_lookup_thread_inner(thread_id); GC_ASSERT(me -> thread_blocked_sp == NULL); # ifdef IA64 me -> backing_store_ptr = stack_ptr; @@ -1300,7 +1300,7 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) GC_INNER void GC_push_all_stacks(void) { - DWORD me = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); GC_bool found_me = FALSE; # ifndef SMALL_CONFIG unsigned nthreads = 0; @@ -1317,8 +1317,8 @@ GC_INNER void GC_push_all_stacks(void) # ifndef SMALL_CONFIG ++nthreads; # endif - total_size += GC_push_stack_for(t, me); - if (t -> id == me) found_me = TRUE; + total_size += GC_push_stack_for(t, thread_id); + if (t -> id == thread_id) found_me = TRUE; } } } else @@ -1332,8 +1332,8 @@ GC_INNER void GC_push_all_stacks(void) # ifndef SMALL_CONFIG ++nthreads; # endif - total_size += GC_push_stack_for(t, me); - if (t -> id == me) found_me = TRUE; + total_size += GC_push_stack_for(t, thread_id); + if (t -> id == thread_id) found_me = TRUE; } } } @@ -1854,10 +1854,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_INNER void GC_wait_marker(void) { HANDLE event = mark_cv; - DWORD id = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); int i = (int)GC_markers - 1; while (i-- > 0) { - if (GC_marker_Id[i] == id) { + if (GC_marker_Id[i] == thread_id) { event = GC_marker_cv[i]; break; } @@ -1873,11 +1873,11 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_INNER void GC_notify_all_marker(void) { - DWORD id = GetCurrentThreadId(); + DWORD thread_id = GetCurrentThreadId(); int i = (int)GC_markers - 1; while (i-- > 0) { /* Notify every marker ignoring self (for efficiency). */ - if (SetEvent(GC_marker_Id[i] != id ? GC_marker_cv[i] : + if (SetEvent(GC_marker_Id[i] != thread_id ? GC_marker_cv[i] : mark_cv) == FALSE) ABORT("SetEvent() failed"); } @@ -1985,8 +1985,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_register_my_thread(sb); /* This waits for an in-progress GC. */ # ifdef DEBUG_THREADS - GC_log_printf("thread 0x%lx starting...\n", - (long)GetCurrentThreadId()); + GC_log_printf("thread 0x%lx starting...\n", (long)GetCurrentThreadId()); # endif GC_free(arg); -- cgit v1.2.1 From 8ee04ef1a4f84c5a7e9e6c94e9e8261a218ff4f0 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 10 May 2011 15:39:29 +0000 Subject: 2011-05-10 Ivan Maidanski * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join adjacent "#ifdef". * thread_local_alloc.c (GC_malloc_atomic): Call GC_core_malloc_atomic (instead of GC_core_malloc). --HG-- branch : bdwgc --- ChangeLog | 9 ++++++++- thread_local_alloc.c | 8 ++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index be0b4b45..457a1d76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-10 Ivan Maidanski + + * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join + adjacent "#ifdef". + * thread_local_alloc.c (GC_malloc_atomic): Call + GC_core_malloc_atomic (instead of GC_core_malloc). + 2011-05-10 Ivan Maidanski * pthread_start.c (GC_start_rtn_prepare_thread): Change return @@ -1236,7 +1243,7 @@ type). * os_dep.c (GC_dirty_init): Print a message about SIG_IGN detected (for SIGSEGV/BUS) only if GC_print_stats. - * os_dep.c (catch_exception_raise): Join 2 adjucent GC_err_printf + * os_dep.c (catch_exception_raise): Join 2 adjacent GC_err_printf calls. 2010-11-25 Ivan Maidanski diff --git a/thread_local_alloc.c b/thread_local_alloc.c index 2e27331d..1540f9ff 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -147,8 +147,6 @@ GC_API void * GC_CALL GC_malloc(size_t bytes) tsd = GC_getspecific(k); # else tsd = GC_getspecific(GC_thread_key); -# endif -# if defined(USE_PTHREAD_SPECIFIC) || defined(USE_WIN32_SPECIFIC) if (EXPECT(0 == tsd, FALSE)) { return GC_core_malloc(bytes); } @@ -179,15 +177,13 @@ GC_API void * GC_CALL GC_malloc_atomic(size_t bytes) if (EXPECT(0 == k, FALSE)) { /* We haven't yet run GC_init_parallel. That means */ /* we also aren't locking, so this is fairly cheap. */ - return GC_core_malloc(bytes); + return GC_core_malloc_atomic(bytes); } tsd = GC_getspecific(k); # else tsd = GC_getspecific(GC_thread_key); -# endif -# if defined(USE_PTHREAD_SPECIFIC) || defined(USE_WIN32_SPECIFIC) if (EXPECT(0 == tsd, FALSE)) { - return GC_core_malloc(bytes); + return GC_core_malloc_atomic(bytes); } # endif GC_ASSERT(GC_is_initialized); -- cgit v1.2.1 From fbe834c1d22fb303d802eb2569d87f6ff6696f20 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 11 May 2011 07:19:47 +0000 Subject: 2011-05-11 Ivan Maidanski * pthread_support.c (GC_unregister_my_thread_inner): Don't call GC_remove_specific. * include/private/thread_local_alloc.h (GC_remove_specific): Remove (since it is empty for all targets). * pthread_support.c (GC_record_stack_base): New inline function. * win32_threads.c (GC_record_stack_base): Ditto. * pthread_support.c (GC_register_my_thread_inner): Invoke GC_record_stack_base. * win32_threads.c (GC_register_my_thread_inner): Ditto. * pthread_support.c (GC_register_my_thread): If thread is FINISHED then call GC_record_stack_base, clear FINISHED, initialize thread-local list and return success. * win32_threads.c (GC_register_my_thread): Ditto. * include/gc.h (GC_register_my_thread): Update documentation. * include/private/thread_local_alloc.h (GC_thread_key): Ditto. --HG-- branch : bdwgc --- ChangeLog | 18 +++++++++++++++++ include/gc.h | 5 ++++- include/private/thread_local_alloc.h | 12 +++-------- pthread_support.c | 35 ++++++++++++++++++++------------ win32_threads.c | 39 ++++++++++++++++++++++++++++-------- 5 files changed, 78 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 457a1d76..8820d38d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-05-11 Ivan Maidanski + + * pthread_support.c (GC_unregister_my_thread_inner): Don't call + GC_remove_specific. + * include/private/thread_local_alloc.h (GC_remove_specific): + Remove (since it is empty for all targets). + * pthread_support.c (GC_record_stack_base): New inline function. + * win32_threads.c (GC_record_stack_base): Ditto. + * pthread_support.c (GC_register_my_thread_inner): Invoke + GC_record_stack_base. + * win32_threads.c (GC_register_my_thread_inner): Ditto. + * pthread_support.c (GC_register_my_thread): If thread is FINISHED + then call GC_record_stack_base, clear FINISHED, initialize + thread-local list and return success. + * win32_threads.c (GC_register_my_thread): Ditto. + * include/gc.h (GC_register_my_thread): Update documentation. + * include/private/thread_local_alloc.h (GC_thread_key): Ditto. + 2011-05-10 Ivan Maidanski * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join diff --git a/include/gc.h b/include/gc.h index e94a943e..8c996cbc 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1044,7 +1044,10 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */, /* always done implicitly. This is normally done implicitly if GC_ */ /* functions are called to create the thread, e.g. by including gc.h */ /* (which redefines some system functions) before calling the system */ - /* thread creation function. */ + /* thread creation function. Nonetheless, thread cleanup routines */ + /* (eg., pthread key destructor) typically require manual thread */ + /* registering (and unregistering) if pointers to GC-allocated */ + /* objects are manipulated inside. */ /* It is also always done implicitly on some platforms if */ /* GC_use_threads_discovery() is called at start-up. Except for the */ /* latter case, the explicit call is normally required for threads */ diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 20995a8c..93f943d2 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -97,13 +97,11 @@ typedef struct thread_local_freelists { # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific # define GC_key_create pthread_key_create -# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef pthread_key_t GC_key_t; # elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) # define GC_setspecific(key, v) ((key) = (v), 0) # define GC_key_create(key, d) 0 -# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef void * GC_key_t; # elif defined(USE_WIN32_SPECIFIC) # ifndef WIN32_LEAN_AND_MEAN @@ -120,7 +118,6 @@ typedef struct thread_local_freelists { # endif # define GC_key_create(key, d) \ ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) -# define GC_remove_specific(key) /* No need for cleanup on thread exit. */ /* Need TlsFree on process exit/detach ? */ typedef DWORD GC_key_t; # elif defined(USE_CUSTOM_SPECIFIC) @@ -152,12 +149,9 @@ extern __declspec(thread) #endif GC_key_t GC_thread_key; - -/* This is set up by the thread_local_alloc implementation. But the */ -/* thread support layer calls GC_remove_specific(GC_thread_key) */ -/* before a thread exits. */ -/* And the thread support layer makes sure that GC_thread_key is traced,*/ -/* if necessary. */ +/* This is set up by the thread_local_alloc implementation. No need */ +/* for cleanup on thread exit. But the thread support layer makes sure */ +/* that GC_thread_key is traced, if necessary. */ #endif /* THREAD_LOCAL_ALLOC */ diff --git a/pthread_support.c b/pthread_support.c index a6a5a5a3..af16a57d 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1183,9 +1183,6 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) } else { me -> flags |= FINISHED; } -# if defined(THREAD_LOCAL_ALLOC) - GC_remove_specific(GC_thread_key); -# endif } GC_API int GC_CALL GC_unregister_my_thread(void) @@ -1344,6 +1341,20 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) GC_INNER GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ +GC_INLINE void GC_record_stack_base(GC_thread me, + const struct GC_stack_base *sb) +{ +# ifndef GC_DARWIN_THREADS + me -> stop_info.stack_ptr = sb -> mem_base; +# endif + me -> stack_end = sb -> mem_base; + if (me -> stack_end == NULL) + ABORT("Bad stack base in GC_register_my_thread"); +# ifdef IA64 + me -> backing_store_end = sb -> reg_base; +# endif +} + STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, pthread_t my_pthread) { @@ -1356,15 +1367,8 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, ABORT("Failed to allocate memory for thread registering"); # ifdef GC_DARWIN_THREADS me -> stop_info.mach_thread = mach_thread_self(); -# else - me -> stop_info.stack_ptr = sb -> mem_base; # endif - me -> stack_end = sb -> mem_base; - if (me -> stack_end == NULL) - ABORT("Bad stack base in GC_register_my_thread"); -# ifdef IA64 - me -> backing_store_end = sb -> reg_base; -# endif /* IA64 */ + GC_record_stack_base(me, sb); return me; } @@ -1387,8 +1391,13 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) LOCK(); me = GC_lookup_thread(self); - if (0 == me) { - me = GC_register_my_thread_inner(sb, self); + if (0 == me || (me -> flags & FINISHED) != 0) { + if (me == 0) { + me = GC_register_my_thread_inner(sb, self); + } else { + GC_record_stack_base(me, sb); + me -> flags &= ~FINISHED; + } me -> flags |= DETACHED; /* Treat as detached, since we do not need to worry about */ /* pointer results. */ diff --git a/win32_threads.c b/win32_threads.c index a9b406ab..8e0bcc53 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -364,6 +364,17 @@ STATIC GC_thread GC_new_thread(DWORD id) STATIC GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ +GC_INLINE void GC_record_stack_base(GC_vthread me, + const struct GC_stack_base *sb) +{ + me -> stack_base = sb -> mem_base; +# ifdef IA64 + me -> backing_store_end = sb -> reg_base; +# endif + if (me -> stack_base == NULL) + ABORT("Bad stack base in GC_register_my_thread"); +} + /* This may be called from DllMain, and hence operates under unusual */ /* constraints. In particular, it must be lock-free if */ /* GC_win32_dll_threads is set. Always called from the thread being */ @@ -456,10 +467,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, } # endif me -> last_stack_min = ADDR_LIMIT; - me -> stack_base = sb -> mem_base; -# ifdef IA64 - me -> backing_store_end = sb -> reg_base; -# endif + GC_record_stack_base(me, sb); /* Up until this point, GC_push_all_stacks considers this thread */ /* invalid. */ /* Up until this point, this entry is viewed as reserved but invalid */ @@ -468,8 +476,6 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, # if defined(THREAD_LOCAL_ALLOC) GC_init_thread_local((GC_tlfs)(&(me->tlfs))); # endif - if (me -> stack_base == NULL) - ABORT("Bad stack base in GC_register_my_thread_inner"); # ifndef GC_NO_THREADS_DISCOVERY if (GC_win32_dll_threads) { if (GC_please_stop) { @@ -707,6 +713,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) { + GC_thread me; DWORD thread_id = GetCurrentThreadId(); DCL_LOCK_STATE; @@ -715,11 +722,27 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) /* We lock here, since we want to wait for an ongoing GC. */ LOCK(); - if (0 == GC_lookup_thread_inner(thread_id)) { + me = GC_lookup_thread_inner(thread_id); + if (me == 0) { GC_register_my_thread_inner(sb, thread_id); +# ifdef GC_PTHREADS + me -> flags |= DETACHED; +# endif UNLOCK(); return GC_SUCCESS; - } else { + } else +# ifdef GC_PTHREADS + /* else */ if ((me -> flags & FINISHED) != 0) { + GC_record_stack_base(me, sb); + me -> flags = (me -> flags & ~FINISHED) | DETACHED; +# ifdef THREAD_LOCAL_ALLOC + GC_init_thread_local((GC_tlfs)(&me->tlfs)); +# endif + UNLOCK(); + return GC_SUCCESS; + } else +# endif + /* else */ { UNLOCK(); return GC_DUPLICATE; } -- cgit v1.2.1 From 903d2838fe06db9ed4fbe8387908e9ff584c7eca Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 11 May 2011 07:41:49 +0000 Subject: 2011-05-11 Ivan Maidanski (mostly really Ludovic Courtes) * tests/threadkey_test.c: New file. * .cvsignore (threadkey_test): Add. * tests/tests.am (TESTS, check_PROGRAMS): Add 'threadkey_test'. * tests/tests.am (threadkey_test_SOURCES, threadkey_test_LDADD): New variable. * Makefile.in: Regenerate. --HG-- branch : bdwgc --- .cvsignore | 1 + ChangeLog | 9 ++++++++ Makefile.in | 33 +++++++++++++++++++++++++-- tests/tests.am | 5 +++++ tests/threadkey_test.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100755 tests/threadkey_test.c diff --git a/.cvsignore b/.cvsignore index c064b43a..3692f0bb 100644 --- a/.cvsignore +++ b/.cvsignore @@ -15,5 +15,6 @@ libtool middletest smashtest staticrootstest +threadkey_test threadleaktest test_cpp diff --git a/ChangeLog b/ChangeLog index 8820d38d..0e45f4a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-11 Ivan Maidanski (mostly really Ludovic Courtes) + + * tests/threadkey_test.c: New file. + * .cvsignore (threadkey_test): Add. + * tests/tests.am (TESTS, check_PROGRAMS): Add 'threadkey_test'. + * tests/tests.am (threadkey_test_SOURCES, threadkey_test_LDADD): + New variable. + * Makefile.in: Regenerate. + 2011-05-11 Ivan Maidanski * pthread_support.c (GC_unregister_my_thread_inner): Don't call diff --git a/Makefile.in b/Makefile.in index d043c3b0..179a67b0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -122,8 +122,10 @@ DIST_COMMON = $(am__configure_deps) $(am__pkginclude_HEADERS_DIST) \ @KEEP_BACK_PTRS_TRUE@am__append_7 = tracetest$(EXEEXT) @KEEP_BACK_PTRS_TRUE@am__append_8 = tracetest @THREADS_TRUE@am__append_9 = threadleaktest$(EXEEXT) \ +@THREADS_TRUE@ threadkey_test$(EXEEXT) \ @THREADS_TRUE@ initsecondarythread$(EXEEXT) -@THREADS_TRUE@am__append_10 = threadleaktest initsecondarythread +@THREADS_TRUE@am__append_10 = threadleaktest threadkey_test \ +@THREADS_TRUE@ initsecondarythread @CPLUSPLUS_TRUE@am__append_11 = test_cpp$(EXEEXT) @CPLUSPLUS_TRUE@am__append_12 = test_cpp subdir = . @@ -215,6 +217,7 @@ libstaticrootslib_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(libstaticrootslib_la_LDFLAGS) $(LDFLAGS) -o $@ @KEEP_BACK_PTRS_TRUE@am__EXEEXT_1 = tracetest$(EXEEXT) @THREADS_TRUE@am__EXEEXT_2 = threadleaktest$(EXEEXT) \ +@THREADS_TRUE@ threadkey_test$(EXEEXT) \ @THREADS_TRUE@ initsecondarythread$(EXEEXT) @CPLUSPLUS_TRUE@am__EXEEXT_3 = test_cpp$(EXEEXT) am_gctest_OBJECTS = test.$(OBJEXT) @@ -249,6 +252,10 @@ test_cpp_OBJECTS = $(am_test_cpp_OBJECTS) @AVOID_CPP_LIB_FALSE@@CPLUSPLUS_TRUE@ $(am__DEPENDENCIES_2) @AVOID_CPP_LIB_TRUE@@CPLUSPLUS_TRUE@test_cpp_DEPENDENCIES = gc_cpp.o \ @AVOID_CPP_LIB_TRUE@@CPLUSPLUS_TRUE@ $(am__DEPENDENCIES_2) +am__threadkey_test_SOURCES_DIST = tests/threadkey_test.c +@THREADS_TRUE@am_threadkey_test_OBJECTS = threadkey_test.$(OBJEXT) +threadkey_test_OBJECTS = $(am_threadkey_test_OBJECTS) +@THREADS_TRUE@threadkey_test_DEPENDENCIES = $(am__DEPENDENCIES_2) am__threadleaktest_SOURCES_DIST = tests/thread_leak_test.c @THREADS_TRUE@am_threadleaktest_OBJECTS = thread_leak_test.$(OBJEXT) threadleaktest_OBJECTS = $(am_threadleaktest_OBJECTS) @@ -295,13 +302,15 @@ SOURCES = $(libcord_la_SOURCES) $(libgc_la_SOURCES) \ $(initsecondarythread_SOURCES) $(leaktest_SOURCES) \ $(middletest_SOURCES) $(smashtest_SOURCES) \ $(staticrootstest_SOURCES) $(test_cpp_SOURCES) \ - $(threadleaktest_SOURCES) $(tracetest_SOURCES) + $(threadkey_test_SOURCES) $(threadleaktest_SOURCES) \ + $(tracetest_SOURCES) DIST_SOURCES = $(libcord_la_SOURCES) $(am__libgc_la_SOURCES_DIST) \ $(EXTRA_libgc_la_SOURCES) $(am__libgccpp_la_SOURCES_DIST) \ $(libstaticrootslib_la_SOURCES) $(gctest_SOURCES) \ $(hugetest_SOURCES) $(am__initsecondarythread_SOURCES_DIST) \ $(leaktest_SOURCES) $(middletest_SOURCES) $(smashtest_SOURCES) \ $(staticrootstest_SOURCES) $(am__test_cpp_SOURCES_DIST) \ + $(am__threadkey_test_SOURCES_DIST) \ $(am__threadleaktest_SOURCES_DIST) \ $(am__tracetest_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -671,6 +680,8 @@ libstaticrootslib_la_DEPENDENCIES = $(top_builddir)/libgc.la @KEEP_BACK_PTRS_TRUE@tracetest_LDADD = $(test_ldadd) @THREADS_TRUE@threadleaktest_SOURCES = tests/thread_leak_test.c @THREADS_TRUE@threadleaktest_LDADD = $(test_ldadd) +@THREADS_TRUE@threadkey_test_SOURCES = tests/threadkey_test.c +@THREADS_TRUE@threadkey_test_LDADD = $(test_ldadd) @THREADS_TRUE@initsecondarythread_SOURCES = tests/initsecondarythread.c @THREADS_TRUE@initsecondarythread_LDADD = $(test_ldadd) @CPLUSPLUS_TRUE@test_cpp_SOURCES = tests/test_cpp.cc @@ -855,6 +866,9 @@ staticrootstest$(EXEEXT): $(staticrootstest_OBJECTS) $(staticrootstest_DEPENDENC test_cpp$(EXEEXT): $(test_cpp_OBJECTS) $(test_cpp_DEPENDENCIES) @rm -f test_cpp$(EXEEXT) $(CXXLINK) $(test_cpp_OBJECTS) $(test_cpp_LDADD) $(LIBS) +threadkey_test$(EXEEXT): $(threadkey_test_OBJECTS) $(threadkey_test_DEPENDENCIES) + @rm -f threadkey_test$(EXEEXT) + $(LINK) $(threadkey_test_OBJECTS) $(threadkey_test_LDADD) $(LIBS) threadleaktest$(EXEEXT): $(threadleaktest_OBJECTS) $(threadleaktest_DEPENDENCIES) @rm -f threadleaktest$(EXEEXT) $(LINK) $(threadleaktest_OBJECTS) $(threadleaktest_LDADD) $(LIBS) @@ -917,6 +931,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cpp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_leak_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_local_alloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadkey_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/typd_mlc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32_threads.Plo@am__quote@ @@ -1103,6 +1118,20 @@ staticrootstest.obj: tests/staticrootstest.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o staticrootstest.obj `if test -f 'tests/staticrootstest.c'; then $(CYGPATH_W) 'tests/staticrootstest.c'; else $(CYGPATH_W) '$(srcdir)/tests/staticrootstest.c'; fi` +threadkey_test.o: tests/threadkey_test.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT threadkey_test.o -MD -MP -MF $(DEPDIR)/threadkey_test.Tpo -c -o threadkey_test.o `test -f 'tests/threadkey_test.c' || echo '$(srcdir)/'`tests/threadkey_test.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/threadkey_test.Tpo $(DEPDIR)/threadkey_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/threadkey_test.c' object='threadkey_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o threadkey_test.o `test -f 'tests/threadkey_test.c' || echo '$(srcdir)/'`tests/threadkey_test.c + +threadkey_test.obj: tests/threadkey_test.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT threadkey_test.obj -MD -MP -MF $(DEPDIR)/threadkey_test.Tpo -c -o threadkey_test.obj `if test -f 'tests/threadkey_test.c'; then $(CYGPATH_W) 'tests/threadkey_test.c'; else $(CYGPATH_W) '$(srcdir)/tests/threadkey_test.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/threadkey_test.Tpo $(DEPDIR)/threadkey_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/threadkey_test.c' object='threadkey_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o threadkey_test.obj `if test -f 'tests/threadkey_test.c'; then $(CYGPATH_W) 'tests/threadkey_test.c'; else $(CYGPATH_W) '$(srcdir)/tests/threadkey_test.c'; fi` + thread_leak_test.o: tests/thread_leak_test.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread_leak_test.o -MD -MP -MF $(DEPDIR)/thread_leak_test.Tpo -c -o thread_leak_test.o `test -f 'tests/thread_leak_test.c' || echo '$(srcdir)/'`tests/thread_leak_test.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread_leak_test.Tpo $(DEPDIR)/thread_leak_test.Po diff --git a/tests/tests.am b/tests/tests.am index e773c45a..2ef84ba6 100644 --- a/tests/tests.am +++ b/tests/tests.am @@ -68,6 +68,11 @@ check_PROGRAMS += threadleaktest threadleaktest_SOURCES = tests/thread_leak_test.c threadleaktest_LDADD = $(test_ldadd) +TESTS += threadkey_test$(EXEEXT) +check_PROGRAMS += threadkey_test +threadkey_test_SOURCES = tests/threadkey_test.c +threadkey_test_LDADD = $(test_ldadd) + TESTS += initsecondarythread$(EXEEXT) check_PROGRAMS += initsecondarythread initsecondarythread_SOURCES = tests/initsecondarythread.c diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c new file mode 100755 index 00000000..5b6a5167 --- /dev/null +++ b/tests/threadkey_test.c @@ -0,0 +1,61 @@ + +#ifndef GC_THREADS +# define GC_THREADS +#endif + +#define GC_NO_THREAD_REDIRECTS 1 + +#include "gc.h" + +#include + +pthread_key_t key; +pthread_once_t key_once = PTHREAD_ONCE_INIT; + +void * entry (void *arg) +{ + pthread_setspecific(key, + (void *)GC_HIDE_POINTER(GC_STRDUP("hello, world"))); + return arg; +} + +void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg) +{ + int res = GC_register_my_thread (sb); + pthread_t t; + + GC_pthread_create (&t, NULL, entry, NULL); + if (res == GC_SUCCESS) + GC_unregister_my_thread (); + return NULL; +} + +void on_thread_exit (void *v) +{ + GC_call_with_stack_base (on_thread_exit_inner, NULL); +} + +void make_key (void) +{ + pthread_key_create (&key, on_thread_exit); +} + +#ifndef LIMIT +# define LIMIT 50 +#endif + +int main (void) +{ + int i; + GC_INIT (); + + pthread_once (&key_once, make_key); + + for (i = 0; i < LIMIT; i++) + { + pthread_t t; + GC_pthread_create (&t, NULL, entry, NULL); + } + + return 0; +} -- cgit v1.2.1 From 14138b3744b20ba6e0b99e1b92f833bb6398e332 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 11 May 2011 09:12:35 +0000 Subject: 2011-05-11 Ivan Maidanski * os_dep.c (GC_gww_page_was_ever_dirty): Fix comment (for GWW_VDB). * os_dep.c (GC_dirty_init): Use memset() for GC_written_pages resetting (for PROC_VDB). --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ os_dep.c | 6 ++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e45f4a8..dff02807 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-11 Ivan Maidanski + + * os_dep.c (GC_gww_page_was_ever_dirty): Fix comment (for + GWW_VDB). + * os_dep.c (GC_dirty_init): Use memset() for GC_written_pages + resetting (for PROC_VDB). + 2011-05-11 Ivan Maidanski (mostly really Ludovic Courtes) * tests/threadkey_test.c: New file. diff --git a/os_dep.c b/os_dep.c index eb69a7ec..ed8726e0 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2772,7 +2772,7 @@ STATIC void GC_default_push_other_roots(void) } # ifdef CHECKSUMS - /* Used only if PROC_VDB. */ + /* Used only if GWW_VDB. */ # ifdef MPROTECT_VDB STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h) # else @@ -3641,9 +3641,7 @@ GC_INNER void GC_dirty_init(void) GC_dirty_maintained = TRUE; if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { - register int i; - for (i = 0; i < PHT_SIZE; i++) - GC_written_pages[i] = (word)(-1); + memset(GC_written_pages, 0xff, sizeof(page_hash_table)); if (GC_print_stats == VERBOSE) GC_log_printf("Allocated bytes:%lu:all pages may have been written\n", (unsigned long)(GC_bytes_allocd -- cgit v1.2.1 From 41e6c3ce9d6c0b8106346ac1133db578437f4e81 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 11 May 2011 13:27:32 +0000 Subject: 2011-05-11 Ivan Maidanski * backgraph.c (add_edge): Recognize DEBUG_PRINT_BIG_N_EDGES macro. * os_dep.c (GC_set_and_save_fault_handler): Recognize SIGACTION_FLAGS_NODEFER_HACK macro. * pthread_support.c (mark_mutex): Recognize GLIBC_2_1_MUTEX_HACK macro. * pthread_support.c (GC_acquire_mark_lock): Remove commented out code. * include/gc_inline.h (GC_MALLOC_WORDS, GC_MALLOC_ATOMIC_WORDS, GC_CONS): Remove trailing space (before back-slash). * include/private/gc_hdrs.h (GET_BI, GET_HDR_ADDR): Ditto. * include/private/gc_pmark.h (PUSH_OBJ, PUSH_CONTENTS, SET_MARK_BIT_EXIT_IF_SET, LONG_MULT, PUSH_CONTENTS_HDR, GC_PUSH_ONE_STACK, GC_PUSH_ONE_HEAP): Ditto. * include/private/thread_local_alloc.h (GC_key_create): Ditto. * include/private/gc_priv.h (SUNOS5SIGS): Don't include sys/siginfo.h on Linux. * include/private/gcconfig.h: Reformat comments (and some code). * include/private/gcconfig.h (FORCE_WRITE_PREFETCH): New macro recognized, force PREFETCH_FOR_WRITE to be defined on x86. * include/private/gcconfig.h (USE_HPUX_FIXED_STACKBOTTOM): New macro recognized (for HP/UX). --HG-- branch : bdwgc --- ChangeLog | 24 +++++++++++ backgraph.c | 14 +++---- include/gc_inline.h | 8 ++-- include/private/gc_hdrs.h | 4 +- include/private/gc_pmark.h | 44 ++++++++++---------- include/private/gc_priv.h | 2 +- include/private/gcconfig.h | 80 ++++++++++++++++++------------------ include/private/thread_local_alloc.h | 2 +- os_dep.c | 19 +++++---- pthread_support.c | 7 +--- 10 files changed, 108 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index dff02807..1ccedb28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2011-05-11 Ivan Maidanski + + * backgraph.c (add_edge): Recognize DEBUG_PRINT_BIG_N_EDGES macro. + * os_dep.c (GC_set_and_save_fault_handler): Recognize + SIGACTION_FLAGS_NODEFER_HACK macro. + * pthread_support.c (mark_mutex): Recognize GLIBC_2_1_MUTEX_HACK + macro. + * pthread_support.c (GC_acquire_mark_lock): Remove commented out + code. + * include/gc_inline.h (GC_MALLOC_WORDS, GC_MALLOC_ATOMIC_WORDS, + GC_CONS): Remove trailing space (before back-slash). + * include/private/gc_hdrs.h (GET_BI, GET_HDR_ADDR): Ditto. + * include/private/gc_pmark.h (PUSH_OBJ, PUSH_CONTENTS, + SET_MARK_BIT_EXIT_IF_SET, LONG_MULT, PUSH_CONTENTS_HDR, + GC_PUSH_ONE_STACK, GC_PUSH_ONE_HEAP): Ditto. + * include/private/thread_local_alloc.h (GC_key_create): Ditto. + * include/private/gc_priv.h (SUNOS5SIGS): Don't include + sys/siginfo.h on Linux. + * include/private/gcconfig.h: Reformat comments (and some code). + * include/private/gcconfig.h (FORCE_WRITE_PREFETCH): New macro + recognized, force PREFETCH_FOR_WRITE to be defined on x86. + * include/private/gcconfig.h (USE_HPUX_FIXED_STACKBOTTOM): New + macro recognized (for HP/UX). + 2011-05-11 Ivan Maidanski * os_dep.c (GC_gww_page_was_ever_dirty): Fix comment (for diff --git a/backgraph.c b/backgraph.c index 60d000cf..60a9e0f9 100644 --- a/backgraph.c +++ b/backgraph.c @@ -254,14 +254,12 @@ static void add_edge(ptr_t p, ptr_t q) } be_cont -> edges[i] = p; be -> n_edges++; - if (be -> n_edges == 100) { -# if 0 - if (GC_print_stats) { - GC_err_printf("The following object has in-degree >= 100:\n"); - GC_print_heap_obj(q); - } -# endif - } +# ifdef DEBUG_PRINT_BIG_N_EDGES + if (GC_print_stats == VERBOSE && be -> n_edges == 100) { + GC_err_printf("The following object has big in-degree:\n"); + GC_print_heap_obj(q); + } +# endif } typedef void (*per_object_func)(ptr_t p, size_t n_bytes, word gc_descr); diff --git a/include/gc_inline.h b/include/gc_inline.h index e2bb881e..cc49da22 100644 --- a/include/gc_inline.h +++ b/include/gc_inline.h @@ -118,7 +118,7 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, /* free list array. For single-threaded applications, this may be */ /* a global array. */ # define GC_MALLOC_WORDS(result,n,tiny_fl) \ -{ \ +{ \ size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ @@ -126,7 +126,7 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, } # define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \ -{ \ +{ \ size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ PTRFREE, GC_malloc_atomic(grans*GC_GRANULE_BYTES), \ @@ -135,12 +135,12 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, /* And once more for two word initialized objects: */ # define GC_CONS(result, first, second, tiny_fl) \ -{ \ +{ \ size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ *(void **)(result) = (void *)(first)); \ - ((void **)(result))[1] = (void *)(second); \ + ((void **)(result))[1] = (void *)(second); \ } #endif /* !GC_INLINE_H */ diff --git a/include/private/gc_hdrs.h b/include/private/gc_hdrs.h index 777b016a..0360adbc 100644 --- a/include/private/gc_hdrs.h +++ b/include/private/gc_hdrs.h @@ -176,7 +176,6 @@ typedef struct bi { register word hi = \ (word)(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \ register bottom_index * _bi = GC_top_index[TL_HASH(hi)]; \ - \ while (_bi -> key != hi && _bi != GC_all_nils) \ _bi = _bi -> hash_link; \ (bottom_indx) = _bi; \ @@ -184,8 +183,7 @@ typedef struct bi { # define GET_HDR_ADDR(p, ha) \ { \ register bottom_index * bi; \ - \ - GET_BI(p, bi); \ + GET_BI(p, bi); \ (ha) = &(HDR_FROM_BI(bi, p)); \ } # define GET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \ diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index 30640505..42fbb204 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -133,7 +133,6 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); #define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \ { \ register word _descr = (hhdr) -> hb_descr; \ - \ GC_ASSERT(!HBLK_IS_FREE(hhdr)); \ if (_descr != 0) { \ mark_stack_top++; \ @@ -153,10 +152,9 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); source, exit_label) \ { \ hdr * my_hhdr; \ - \ HC_GET_HDR(current, my_hhdr, source, exit_label); \ PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \ - source, exit_label, my_hhdr, TRUE); \ + source, exit_label, my_hhdr, TRUE); \ exit_label: ; \ } @@ -169,7 +167,7 @@ exit_label: ; \ { \ char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \ if (*mark_byte_addr) goto exit_label; \ - *mark_byte_addr = 1; \ + *mark_byte_addr = 1; \ } #else # ifdef PARALLEL_MARK @@ -227,8 +225,8 @@ exit_label: ; \ # define LONG_MULT(hprod, lprod, x, y) { \ unsigned long long prod = (unsigned long long)(x) \ * (unsigned long long)(y); \ - hprod = prod >> 32; \ - lprod = (unsigned32)prod; \ + hprod = prod >> 32; \ + lprod = (unsigned32)prod; \ } #endif /* !I386 */ @@ -250,16 +248,16 @@ exit_label: ; \ /* first block, then we are in the all_interior_pointers case, and */ \ /* it is safe to use any displacement value. */ \ size_t gran_displ = BYTES_TO_GRANULES(displ); \ - size_t gran_offset = hhdr -> hb_map[gran_displ]; \ + size_t gran_offset = hhdr -> hb_map[gran_displ]; \ size_t byte_offset = displ & (GRANULE_BYTES - 1); \ - ptr_t base = current; \ + ptr_t base = current; \ /* The following always fails for large block references. */ \ if (EXPECT((gran_offset | byte_offset) != 0, FALSE)) { \ if (hhdr -> hb_large_block) { \ /* gran_offset is bogus. */ \ size_t obj_displ; \ base = (ptr_t)(hhdr -> hb_block); \ - obj_displ = (ptr_t)(current) - base; \ + obj_displ = (ptr_t)(current) - base; \ if (obj_displ != displ) { \ GC_ASSERT(obj_displ < hhdr -> hb_sz); \ /* Must be in all_interior_pointer case, not first block */ \ @@ -308,7 +306,7 @@ exit_label: ; \ size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\ unsigned32 low_prod, high_prod; \ unsigned32 inv_sz = hhdr -> hb_inv_sz; \ - ptr_t base = current; \ + ptr_t base = current; \ LONG_MULT(high_prod, low_prod, displ, inv_sz); \ /* product is > and within sz_in_bytes of displ * sz_in_bytes * 2**32 */ \ if (EXPECT(low_prod >> 16 != 0, FALSE)) { \ @@ -316,7 +314,7 @@ exit_label: ; \ if (inv_sz == LARGE_INV_SZ) { \ size_t obj_displ; \ base = (ptr_t)(hhdr -> hb_block); \ - obj_displ = (ptr_t)(current) - base; \ + obj_displ = (ptr_t)(current) - base; \ if (obj_displ != displ) { \ GC_ASSERT(obj_displ < hhdr -> hb_sz); \ /* Must be in all_interior_pointer case, not first block */ \ @@ -377,20 +375,20 @@ exit_label: ; \ #if NEED_FIXUP_POINTER /* Try both the raw version and the fixed up one. */ # define GC_PUSH_ONE_STACK(p, source) \ - if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ - && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ - PUSH_ONE_CHECKED_STACK(p, source); \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + PUSH_ONE_CHECKED_STACK(p, source); \ } \ FIXUP_POINTER(p); \ - if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ - && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ - PUSH_ONE_CHECKED_STACK(p, source); \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + PUSH_ONE_CHECKED_STACK(p, source); \ } #else /* !NEED_FIXUP_POINTER */ # define GC_PUSH_ONE_STACK(p, source) \ - if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ - && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ - PUSH_ONE_CHECKED_STACK(p, source); \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + PUSH_ONE_CHECKED_STACK(p, source); \ } #endif @@ -401,9 +399,9 @@ exit_label: ; \ */ #define GC_PUSH_ONE_HEAP(p,source) \ FIXUP_POINTER(p); \ - if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ - && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ - GC_mark_stack_top = GC_mark_and_push( \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + GC_mark_stack_top = GC_mark_and_push( \ (void *)(p), GC_mark_stack_top, \ GC_mark_stack_limit, (void * *)(source)); \ } diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 84d40f54..71ef9ff5 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -2113,7 +2113,7 @@ GC_EXTERN signed_word GC_bytes_found; /* possible/needed. */ #if defined(UNIX_LIKE) || (defined(NEED_FIND_LIMIT) && defined(CYGWIN32)) # include -# if defined(SUNOS5SIGS) && !defined(FREEBSD) +# if defined(SUNOS5SIGS) && !defined(FREEBSD) && !defined(LINUX) # include # endif /* Define SETJMP and friends to be the version that restores */ diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 22ce8a28..54d93645 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -54,8 +54,8 @@ # endif /* And one for FreeBSD: */ -# if (defined(__FreeBSD__) || defined(__DragonFly__) || \ - defined(__FreeBSD_kernel__)) && !defined(FREEBSD) +# if (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__FreeBSD_kernel__)) && !defined(FREEBSD) # define FREEBSD # endif @@ -260,8 +260,8 @@ # endif # define mach_type_known # endif -# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || \ - defined(powerpc64) || defined(__powerpc64__)) +# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) \ + || defined(powerpc64) || defined(__powerpc64__)) # define POWERPC # define mach_type_known # endif @@ -671,11 +671,10 @@ * allocation. */ -/* If we are using a recent version of gcc, we can use __builtin_unwind_init() - * to push the relevant registers onto the stack. - */ -# if defined(__GNUC__) && ((__GNUC__ >= 3) || \ - (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \ +/* If we are using a recent version of gcc, we can use */ +/* __builtin_unwind_init() to push the relevant registers onto the stack. */ +# if defined(__GNUC__) && ((__GNUC__ >= 3) \ + || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \ && !defined(__INTEL_COMPILER) && !defined(__PATHCC__) # define HAVE_BUILTIN_UNWIND_INIT # endif @@ -752,7 +751,7 @@ # include # endif # define OS_TYPE "MACOS" - /* see os_dep.c for details of global data segments. */ + /* see os_dep.c for details of global data segments. */ # define STACKBOTTOM ((ptr_t) LMGetCurStackBase()) # define DATAEND /* not needed */ # define GETPAGESIZE() 4096 @@ -812,8 +811,8 @@ # define ALIGNMENT 4 # define STACKBOTTOM ((ptr_t) 0xc0000000) # endif - /* XXX: see get_end(3), get_etext() and get_end() should not be used. - These aren't used when dyld support is enabled (it is by default) */ + /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ + /* These aren't used when dyld support is enabled (it is by default). */ # define DATASTART ((ptr_t) get_etext()) # define DATAEND ((ptr_t) get_end()) # ifndef USE_MMAP @@ -830,8 +829,8 @@ # define PREFETCH_FOR_WRITE(x) \ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x))) # endif - /* There seems to be some issues with trylock hanging on darwin. This - should be looked into some more */ + /* There seems to be some issues with trylock hanging on darwin. */ + /* This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK # endif # ifdef OPENBSD @@ -1249,26 +1248,26 @@ # define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) # endif # ifdef USE_I686_PREFETCH - /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */ - /* for the next rtelease. */ + /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */ + /* for the next rtelease. */ # define PREFETCH(x) \ - __asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x))) - /* Empirically prefetcht0 is much more effective at reducing */ - /* cache miss stalls for the targeted load instructions. But it */ - /* seems to interfere enough with other cache traffic that the net */ - /* result is worse than prefetchnta. */ -# if 0 - /* Using prefetches for write seems to have a slight negative */ - /* impact on performance, at least for a PIII/500. */ + __asm__ __volatile__ ("prefetchnta %0" : : "m"(*(char *)(x))) + /* Empirically prefetcht0 is much more effective at reducing */ + /* cache miss stalls for the targeted load instructions. But it */ + /* seems to interfere enough with other cache traffic that the */ + /* net result is worse than prefetchnta. */ +# ifdef FORCE_WRITE_PREFETCH + /* Using prefetches for write seems to have a slight negative */ + /* impact on performance, at least for a PIII/500. */ # define PREFETCH_FOR_WRITE(x) \ - __asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x))) + __asm__ __volatile__ ("prefetcht0 %0" : : "m"(*(char *)(x))) # endif # endif # ifdef USE_3DNOW_PREFETCH # define PREFETCH(x) \ - __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x))) + __asm__ __volatile__ ("prefetch %0" : : "m"(*(char *)(x))) # define PREFETCH_FOR_WRITE(x) \ - __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x))) + __asm__ __volatile__ ("prefetchw %0" : : "m"(*(char *)(x))) # endif # endif # ifdef CYGWIN32 @@ -1308,8 +1307,7 @@ extern int _stklen; extern int __djgpp_stack_limit; # define DATASTART ((ptr_t)((((word) (etext)) + 0x1ff) & ~0x1ff)) -/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \ - + _stklen)) */ +/* #define STACKBOTTOM ((ptr_t)((word)_stubinfo+_stubinfo->size+_stklen)) */ # define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen)) /* This may not be right. */ # endif @@ -1388,9 +1386,9 @@ extern long __nullarea; extern char _end; extern char *_STACKTOP; - /* Depending on calling conventions Watcom C either precedes - or does not precedes with underscore names of C-variables. - Make sure startup code variables always have the same names. */ + /* Depending on calling conventions Watcom C either precedes */ + /* or does not precedes with underscore names of C-variables. */ + /* Make sure startup code variables always have the same names. */ #pragma aux __nullarea "*"; #pragma aux _end "*"; # define STACKBOTTOM ((ptr_t) _STACKTOP) @@ -1414,8 +1412,8 @@ # define OS_TYPE "DARWIN" # define DARWIN_DONT_PARSE_STACK # define DYNAMIC_LOADING - /* XXX: see get_end(3), get_etext() and get_end() should not be used. - These aren't used when dyld support is enabled (it is by default) */ + /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ + /* These aren't used when dyld support is enabled (it is by default). */ # define DATASTART ((ptr_t) get_etext()) # define DATAEND ((ptr_t) get_end()) # define STACKBOTTOM ((ptr_t) 0xc0000000) @@ -1426,8 +1424,8 @@ # define MPROTECT_VDB # include # define GETPAGESIZE() getpagesize() - /* There seems to be some issues with trylock hanging on darwin. This - should be looked into some more */ + /* There seems to be some issues with trylock hanging on darwin. */ + /* This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK # endif /* DARWIN */ # endif @@ -1581,7 +1579,7 @@ # define OS_TYPE "HPUX" extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) -# if 0 +# ifdef USE_HPUX_FIXED_STACKBOTTOM /* The following appears to work for 7xx systems running HP/UX */ /* 9.xx Furthermore, it might result in much faster */ /* collections than HEURISTIC2, which may involve scanning */ @@ -2127,8 +2125,8 @@ # define OS_TYPE "DARWIN" # define DARWIN_DONT_PARSE_STACK # define DYNAMIC_LOADING - /* XXX: see get_end(3), get_etext() and get_end() should not be used. - These aren't used when dyld support is enabled (it is by default) */ + /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ + /* These aren't used when dyld support is enabled (it is by default) */ # define DATASTART ((ptr_t) get_etext()) # define DATAEND ((ptr_t) get_end()) # define STACKBOTTOM ((ptr_t) 0x7fff5fc00000) @@ -2139,8 +2137,8 @@ # define MPROTECT_VDB # include # define GETPAGESIZE() getpagesize() - /* There seems to be some issues with trylock hanging on darwin. This - should be looked into some more */ + /* There seems to be some issues with trylock hanging on darwin. */ + /* This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK # endif # ifdef FREEBSD diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 93f943d2..b36fffdd 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -116,7 +116,7 @@ typedef struct thread_local_freelists { /* this is currently missing in WinCE */ # define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF # endif -# define GC_key_create(key, d) \ +# define GC_key_create(key, d) \ ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) /* Need TlsFree on process exit/detach ? */ typedef DWORD GC_key_t; diff --git a/os_dep.c b/os_dep.c index ed8726e0..bff6cde9 100644 --- a/os_dep.c +++ b/os_dep.c @@ -855,16 +855,17 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_set_and_save_fault_handler(GC_fault_handler_t h) { -# if defined(SUNOS5SIGS) || defined(IRIX5) \ +# if defined(SUNOS5SIGS) || defined(IRIX5) \ || defined(OSF1) || defined(HURD) || defined(NETBSD) - struct sigaction act; + struct sigaction act; - act.sa_handler = h; -# if 0 /* Was necessary for Solaris 2.3 and very temporary */ - /* NetBSD bugs. */ - act.sa_flags = SA_RESTART | SA_NODEFER; + act.sa_handler = h; +# ifdef SIGACTION_FLAGS_NODEFER_HACK + /* Was necessary for Solaris 2.3 and very temporary */ + /* NetBSD bugs. */ + act.sa_flags = SA_RESTART | SA_NODEFER; # else - act.sa_flags = SA_RESTART; + act.sa_flags = SA_RESTART; # endif (void) sigemptyset(&act.sa_mask); @@ -893,8 +894,8 @@ GC_INNER word GC_page_size = 0; } # endif /* NEED_FIND_LIMIT || UNIX_LIKE */ -# if defined(NEED_FIND_LIMIT) || \ - defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS) +# if defined(NEED_FIND_LIMIT) \ + || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) /* Some tools to implement HEURISTIC2 */ # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */ diff --git a/pthread_support.c b/pthread_support.c index af16a57d..8caaee07 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1767,7 +1767,7 @@ GC_INNER void GC_lock(void) GC_INNER unsigned long GC_mark_lock_holder = NO_THREAD; #endif -#if 0 +#ifdef GLIBC_2_1_MUTEX_HACK /* Ugly workaround for a linux threads bug in the final versions */ /* of glibc2.1. Pthread_mutex_trylock sets the mutex owner */ /* field even when it fails to acquire the mutex. This causes */ @@ -1785,11 +1785,6 @@ static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER; GC_INNER void GC_acquire_mark_lock(void) { -/* - if (pthread_mutex_lock(&mark_mutex) != 0) { - ABORT("pthread_mutex_lock failed"); - } -*/ GC_generic_lock(&mark_mutex); # ifdef GC_ASSERTIONS GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self()); -- cgit v1.2.1 From 4e6f7dd9c9b84580b2cb7cd9943067e86f251398 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 11 May 2011 17:06:08 +0000 Subject: 2011-05-11 Ivan Maidanski * pthread_support.c (GC_check_tls): Fix "#endif" comment. * include/gc.h (GC_REDIRECT_TO_LOCAL): Remove deprecated comment. * include/private/thread_local_alloc.h (THREAD_LOCAL_ALLOC): Remove redundant test of the macro. * include/private/thread_local_alloc.h: Reformat the code. --HG-- branch : bdwgc --- ChangeLog | 8 ++ include/gc.h | 5 -- include/private/thread_local_alloc.h | 168 +++++++++++++++++------------------ pthread_support.c | 29 +++--- 4 files changed, 104 insertions(+), 106 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ccedb28..7d87f5b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-11 Ivan Maidanski + + * pthread_support.c (GC_check_tls): Fix "#endif" comment. + * include/gc.h (GC_REDIRECT_TO_LOCAL): Remove deprecated comment. + * include/private/thread_local_alloc.h (THREAD_LOCAL_ALLOC): + Remove redundant test of the macro. + * include/private/thread_local_alloc.h: Reformat the code. + 2011-05-11 Ivan Maidanski * backgraph.c (add_edge): Recognize DEBUG_PRINT_BIG_N_EDGES macro. diff --git a/include/gc.h b/include/gc.h index 8c996cbc..3e3f56e3 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1443,11 +1443,6 @@ GC_API void GC_CALL GC_win32_free_heap(void); # include "gc_amiga_redirects.h" #endif - /* - * GC_REDIRECT_TO_LOCAL is now redundant; - * that's the default with THREAD_LOCAL_ALLOC. - */ - #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index b36fffdd..258b592e 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -24,108 +24,104 @@ #include "private/gc_priv.h" -#if defined(THREAD_LOCAL_ALLOC) +#ifdef THREAD_LOCAL_ALLOC #include "gc_inline.h" -# if defined(USE_HPUX_TLS) -# error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS -# endif +#if defined(USE_HPUX_TLS) +# error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS +#endif -# if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) && \ - !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) && \ - !defined(USE_CUSTOM_SPECIFIC) -# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) -# if defined(__GNUC__) /* Fixed for versions past 2.95? */ \ - || defined(MSWINCE) -# define USE_WIN32_SPECIFIC -# else -# define USE_WIN32_COMPILER_TLS -# endif /* !GNU */ -# elif defined(LINUX) && !defined(ARM32) && !defined(AVR32) && \ - (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >=3)) -# define USE_COMPILER_TLS -# elif (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ - defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ - defined(GC_NETBSD_THREADS) -# define USE_PTHREAD_SPECIFIC -# elif defined(GC_HPUX_THREADS) -# ifdef __GNUC__ -# define USE_PTHREAD_SPECIFIC - /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work. */ -# else -# define USE_COMPILER_TLS -# endif +#if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) \ + && !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) \ + && !defined(USE_CUSTOM_SPECIFIC) +# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) +# if defined(__GNUC__) /* Fixed for versions past 2.95? */ \ + || defined(MSWINCE) +# define USE_WIN32_SPECIFIC # else -# define USE_CUSTOM_SPECIFIC /* Use our own. */ +# define USE_WIN32_COMPILER_TLS +# endif /* !GNU */ +# elif defined(LINUX) && !defined(ARM32) && !defined(AVR32) \ + && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >=3)) +# define USE_COMPILER_TLS +# elif defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) \ + || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) \ + || defined(GC_NETBSD_THREADS) +# define USE_PTHREAD_SPECIFIC +# elif defined(GC_HPUX_THREADS) +# ifdef __GNUC__ +# define USE_PTHREAD_SPECIFIC + /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work. */ +# else +# define USE_COMPILER_TLS # endif +# else +# define USE_CUSTOM_SPECIFIC /* Use our own. */ # endif +#endif -# include +#include /* One of these should be declared as the tlfs field in the */ /* structure pointed to by a GC_thread. */ typedef struct thread_local_freelists { -# ifdef THREAD_LOCAL_ALLOC - void * ptrfree_freelists[TINY_FREELISTS]; - void * normal_freelists[TINY_FREELISTS]; -# ifdef GC_GCJ_SUPPORT - void * gcj_freelists[TINY_FREELISTS]; -# define ERROR_FL ((void *)(word)-1) - /* Value used for gcj_freelist[-1]; allocation is */ - /* erroneous. */ -# endif - /* Free lists contain either a pointer or a small count */ - /* reflecting the number of granules allocated at that */ - /* size. */ - /* 0 ==> thread-local allocation in use, free list */ - /* empty. */ - /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */ - /* too few objects of this size have been */ - /* allocated by this thread. */ - /* >= HBLKSIZE => pointer to nonempty free list. */ - /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */ - /* local alloc, equivalent to 0. */ -# define DIRECT_GRANULES (HBLKSIZE/GRANULE_BYTES) - /* Don't use local free lists for up to this much */ - /* allocation. */ - -# endif + void * ptrfree_freelists[TINY_FREELISTS]; + void * normal_freelists[TINY_FREELISTS]; +# ifdef GC_GCJ_SUPPORT + void * gcj_freelists[TINY_FREELISTS]; +# define ERROR_FL ((void *)(word)-1) + /* Value used for gcj_freelist[-1]; allocation is */ + /* erroneous. */ +# endif + /* Free lists contain either a pointer or a small count */ + /* reflecting the number of granules allocated at that */ + /* size. */ + /* 0 ==> thread-local allocation in use, free list */ + /* empty. */ + /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */ + /* too few objects of this size have been */ + /* allocated by this thread. */ + /* >= HBLKSIZE => pointer to nonempty free list. */ + /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */ + /* local alloc, equivalent to 0. */ +# define DIRECT_GRANULES (HBLKSIZE/GRANULE_BYTES) + /* Don't use local free lists for up to this much */ + /* allocation. */ } *GC_tlfs; -# if defined(USE_PTHREAD_SPECIFIC) -# define GC_getspecific pthread_getspecific -# define GC_setspecific pthread_setspecific -# define GC_key_create pthread_key_create - typedef pthread_key_t GC_key_t; -# elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) -# define GC_getspecific(x) (x) -# define GC_setspecific(key, v) ((key) = (v), 0) -# define GC_key_create(key, d) 0 - typedef void * GC_key_t; -# elif defined(USE_WIN32_SPECIFIC) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -# define NOSERVICE -# include -# define GC_getspecific TlsGetValue -# define GC_setspecific(key, v) !TlsSetValue(key, v) +#if defined(USE_PTHREAD_SPECIFIC) +# define GC_getspecific pthread_getspecific +# define GC_setspecific pthread_setspecific +# define GC_key_create pthread_key_create + typedef pthread_key_t GC_key_t; +#elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) +# define GC_getspecific(x) (x) +# define GC_setspecific(key, v) ((key) = (v), 0) +# define GC_key_create(key, d) 0 + typedef void * GC_key_t; +#elif defined(USE_WIN32_SPECIFIC) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# define NOSERVICE +# include +# define GC_getspecific TlsGetValue +# define GC_setspecific(key, v) !TlsSetValue(key, v) /* We assume 0 == success, msft does the opposite. */ -# ifndef TLS_OUT_OF_INDEXES - /* this is currently missing in WinCE */ -# define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF -# endif -# define GC_key_create(key, d) \ - ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) - /* Need TlsFree on process exit/detach ? */ - typedef DWORD GC_key_t; -# elif defined(USE_CUSTOM_SPECIFIC) -# include "private/specific.h" -# else -# error implement me +# ifndef TLS_OUT_OF_INDEXES + /* this is currently missing in WinCE */ +# define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF # endif - +# define GC_key_create(key, d) \ + ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) + /* Need TlsFree on process exit/detach? */ + typedef DWORD GC_key_t; +#elif defined(USE_CUSTOM_SPECIFIC) +# include "private/specific.h" +#else +# error implement me +#endif /* Each thread structure must be initialized. */ /* This call must be made from the new thread. */ diff --git a/pthread_support.c b/pthread_support.c index 8caaee07..3a3f6672 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -288,12 +288,12 @@ STATIC long GC_nprocs = 1; /* a guess as any ... */ #ifdef THREAD_LOCAL_ALLOC -/* We must explicitly mark ptrfree and gcj free lists, since the free */ -/* list links wouldn't otherwise be found. We also set them in the */ -/* normal free lists, since that involves touching less memory than if */ -/* we scanned them normally. */ -GC_INNER void GC_mark_thread_local_free_lists(void) -{ + /* We must explicitly mark ptrfree and gcj free lists, since the free */ + /* list links wouldn't otherwise be found. We also set them in the */ + /* normal free lists, since that involves touching less memory than */ + /* if we scanned them normally. */ + GC_INNER void GC_mark_thread_local_free_lists(void) + { int i; GC_thread p; @@ -303,9 +303,9 @@ GC_INNER void GC_mark_thread_local_free_lists(void) GC_mark_thread_local_fls_for(&(p->tlfs)); } } -} + } -#if defined(GC_ASSERTIONS) +# if defined(GC_ASSERTIONS) void GC_check_tls_for(GC_tlfs p); # if defined(USE_CUSTOM_SPECIFIC) void GC_check_tsd_marks(tsd *key); @@ -328,9 +328,8 @@ GC_INNER void GC_mark_thread_local_free_lists(void) GC_check_tsd_marks(GC_thread_key); # endif } -#endif /* GC_ASSERTIONS */ - -#endif /* Thread_local_alloc */ +# endif /* GC_ASSERTIONS */ +#endif /* THREAD_LOCAL_ALLOC */ #ifdef PARALLEL_MARK @@ -456,7 +455,7 @@ void GC_push_thread_structures(void) GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); # if defined(THREAD_LOCAL_ALLOC) GC_push_all((ptr_t)(&GC_thread_key), - (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key)); + (ptr_t)(&GC_thread_key) + sizeof(&GC_thread_key)); # endif } @@ -615,7 +614,7 @@ GC_INNER unsigned char *GC_check_finalizer_nested(void) /* thread_local_alloc.c) checks only that it's close. */ return((char *)tsd > me && (char *)tsd < me + 1000); } -#endif +#endif /* GC_ASSERTIONS && THREAD_LOCAL_ALLOC */ #ifdef HANDLE_FORK /* Remove all entries from the GC_threads table, except the */ @@ -640,7 +639,7 @@ STATIC void GC_remove_all_threads_but_me(void) if (!(p -> flags & FINISHED)) { GC_destroy_thread_local(&(p->tlfs)); } -# endif /* THREAD_LOCAL_ALLOC */ +# endif if (p != &first_thread) GC_INTERNAL_FREE(p); } } @@ -1440,7 +1439,7 @@ GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *), me = GC_register_my_thread_inner(sb, self); me -> flags = si -> flags; # if defined(THREAD_LOCAL_ALLOC) - GC_init_thread_local(&(me->tlfs)); + GC_init_thread_local(&(me->tlfs)); # endif UNLOCK(); *pstart = si -> start_routine; -- cgit v1.2.1 From bdefd5933477b297c44bf19abe17a3cabaa362ec Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 13 May 2011 14:40:31 +0000 Subject: 2011-05-13 Ivan Maidanski * dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local variable. * pthread_support.c (GC_unregister_my_thread_inner): Revert back GC_remove_specific invocation; add a comment. * include/private/thread_local_alloc.h (GC_remove_specific): Revert back. * specific.c: Expand all tabs to spaces. * specific.c (slow_getspecific): Cast qtid to AO_t. * include/private/specific.h (quick_thread_id): Reformat comment. * include/private/specific.h (key_create, setspecific, remove_specific): Remove "extern" keyword. * include/private/specific.h (getspecific): Change type of "qtid" local variable to unsigned long. --HG-- branch : bdwgc --- ChangeLog | 16 ++++ dyn_load.c | 1 - include/private/specific.h | 14 ++-- include/private/thread_local_alloc.h | 3 + pthread_support.c | 4 + specific.c | 145 +++++++++++++++++------------------ 6 files changed, 100 insertions(+), 83 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d87f5b2..4d0d3376 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-05-13 Ivan Maidanski + + * dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local + variable. + * pthread_support.c (GC_unregister_my_thread_inner): Revert back + GC_remove_specific invocation; add a comment. + * include/private/thread_local_alloc.h (GC_remove_specific): + Revert back. + * specific.c: Expand all tabs to spaces. + * specific.c (slow_getspecific): Cast qtid to AO_t. + * include/private/specific.h (quick_thread_id): Reformat comment. + * include/private/specific.h (key_create, setspecific, + remove_specific): Remove "extern" keyword. + * include/private/specific.h (getspecific): Change type of "qtid" + local variable to unsigned long. + 2011-05-11 Ivan Maidanski * pthread_support.c (GC_check_tls): Fix "#endif" comment. diff --git a/dyn_load.c b/dyn_load.c index a00e0102..7cdceffb 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -135,7 +135,6 @@ GC_FirstDLOpenedLinkMap(void) { extern ElfW(Dyn) _DYNAMIC; ElfW(Dyn) *dp; - 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 */ diff --git a/include/private/specific.h b/include/private/specific.h index 372238dc..8b5cf847 100644 --- a/include/private/specific.h +++ b/include/private/specific.h @@ -51,8 +51,8 @@ typedef struct thread_specific_entry { /* Return the "quick thread id". Default version. Assumes page size, */ /* or at least thread stack separation, is at least 4K. */ -/* Must be defined so that it never returns 0. (Page 0 can't really */ -/* be part of any stack, since that would make 0 a valid stack pointer.)*/ +/* Must be defined so that it never returns 0. (Page 0 can't really be */ +/* part of any stack, since that would make 0 a valid stack pointer.) */ #define quick_thread_id() (((unsigned long)GC_approx_sp()) >> 12) #define INVALID_QTID ((unsigned long)0) @@ -67,11 +67,9 @@ typedef struct thread_specific_data { typedef tsd * PREFIXED(key_t); -extern int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)); - -extern int PREFIXED(setspecific) (tsd * key, void * value); - -extern void PREFIXED(remove_specific) (tsd * key); +int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)); +int PREFIXED(setspecific) (tsd * key, void * value); +void PREFIXED(remove_specific) (tsd * key); /* An internal version of getspecific that assumes a cache miss. */ void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, @@ -80,7 +78,7 @@ void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, /* GC_INLINE is defined in gc_priv.h. */ GC_INLINE void * PREFIXED(getspecific) (tsd * key) { - long qtid = quick_thread_id(); + unsigned long qtid = quick_thread_id(); unsigned hash_val = CACHE_HASH(qtid); tse * volatile * entry_ptr = key -> cache + hash_val; tse * entry = *entry_ptr; /* Must be loaded only once. */ diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 258b592e..55d8fd6e 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -94,11 +94,13 @@ typedef struct thread_local_freelists { # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific # define GC_key_create pthread_key_create +# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef pthread_key_t GC_key_t; #elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) # define GC_setspecific(key, v) ((key) = (v), 0) # define GC_key_create(key, d) 0 +# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef void * GC_key_t; #elif defined(USE_WIN32_SPECIFIC) # ifndef WIN32_LEAN_AND_MEAN @@ -115,6 +117,7 @@ typedef struct thread_local_freelists { # endif # define GC_key_create(key, d) \ ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) +# define GC_remove_specific(key) /* No need for cleanup on exit. */ /* Need TlsFree on process exit/detach? */ typedef DWORD GC_key_t; #elif defined(USE_CUSTOM_SPECIFIC) diff --git a/pthread_support.c b/pthread_support.c index 3a3f6672..175663c0 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1182,6 +1182,10 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) } else { me -> flags |= FINISHED; } +# if defined(THREAD_LOCAL_ALLOC) + /* It is required to call remove_specific defined in specific.c. */ + GC_remove_specific(GC_thread_key); +# endif } GC_API int GC_CALL GC_unregister_my_thread(void) diff --git a/specific.c b/specific.c index b8ea49dd..cbeb2331 100644 --- a/specific.c +++ b/specific.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED @@ -11,35 +11,35 @@ * modified is included with the above copyright notice. */ -#include "private/gc_priv.h" /* For configuration, pthreads.h. */ +#include "private/gc_priv.h" /* For configuration, pthreads.h. */ #include "private/thread_local_alloc.h" - /* To determine type of tsd impl. */ - /* Includes private/specific.h */ - /* if needed. */ + /* To determine type of tsd impl. */ + /* Includes private/specific.h */ + /* if needed. */ #if defined(USE_CUSTOM_SPECIFIC) #include "atomic_ops.h" static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID}; - /* A thread-specific data entry which will never */ - /* appear valid to a reader. Used to fill in empty */ - /* cache entries to avoid a check for 0. */ + /* A thread-specific data entry which will never */ + /* appear valid to a reader. Used to fill in empty */ + /* cache entries to avoid a check for 0. */ int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)) { int i; - tsd * result = (tsd *)MALLOC_CLEAR(sizeof (tsd)); + tsd * result = (tsd *)MALLOC_CLEAR(sizeof(tsd)); /* A quick alignment check, since we need atomic stores */ - GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0); + GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0); if (0 == result) return ENOMEM; pthread_mutex_init(&(result -> lock), NULL); for (i = 0; i < TS_CACHE_SIZE; ++i) { - result -> cache[i] = &invalid_tse; + result -> cache[i] = &invalid_tse; } # ifdef GC_ASSERTIONS for (i = 0; i < TS_HASH_SIZE; ++i) { - GC_ASSERT(result -> hash[i] == 0); + GC_ASSERT(result -> hash[i] == 0); } # endif *key_ptr = result; @@ -50,24 +50,24 @@ int PREFIXED(setspecific) (tsd * key, void * value) { pthread_t self = pthread_self(); int hash_val = HASH(self); volatile tse * entry = (volatile tse *)MALLOC_CLEAR(sizeof (tse)); - + GC_ASSERT(self != INVALID_THREADID); if (0 == entry) return ENOMEM; pthread_mutex_lock(&(key -> lock)); - /* Could easily check for an existing entry here. */ + /* Could easily check for an existing entry here. */ entry -> next = key -> hash[hash_val]; entry -> thread = self; entry -> value = value; GC_ASSERT(entry -> qtid == INVALID_QTID); - /* There can only be one writer at a time, but this needs to be */ - /* atomic with respect to concurrent readers. */ + /* There can only be one writer at a time, but this needs to be */ + /* atomic with respect to concurrent readers. */ AO_store_release((volatile AO_t *)(key -> hash + hash_val), (AO_t)entry); pthread_mutex_unlock(&(key -> lock)); return 0; } -/* Remove thread-specific data for this thread. Should be called on */ -/* thread exit. */ +/* Remove thread-specific data for this thread. Should be called on */ +/* thread exit. */ void PREFIXED(remove_specific) (tsd * key) { pthread_t self = pthread_self(); unsigned hash_val = HASH(self); @@ -77,89 +77,86 @@ void PREFIXED(remove_specific) (tsd * key) { pthread_mutex_lock(&(key -> lock)); entry = *link; while (entry != NULL && entry -> thread != self) { - link = &(entry -> next); - entry = *link; + link = &(entry -> next); + entry = *link; } - /* Invalidate qtid field, since qtids may be reused, and a later */ - /* cache lookup could otherwise find this entry. */ - entry -> qtid = INVALID_QTID; + /* Invalidate qtid field, since qtids may be reused, and a later */ + /* cache lookup could otherwise find this entry. */ + entry -> qtid = INVALID_QTID; if (entry != NULL) { - *link = entry -> next; - /* Atomic! concurrent accesses still work. */ - /* They must, since readers don't lock. */ - /* We shouldn't need a volatile access here, */ - /* since both this and the preceding write */ - /* should become visible no later than */ - /* the pthread_mutex_unlock() call. */ + *link = entry -> next; + /* Atomic! concurrent accesses still work. */ + /* They must, since readers don't lock. */ + /* We shouldn't need a volatile access here, */ + /* since both this and the preceding write */ + /* should become visible no later than */ + /* the pthread_mutex_unlock() call. */ } - /* If we wanted to deallocate the entry, we'd first have to clear */ - /* any cache entries pointing to it. That probably requires */ - /* additional synchronization, since we can't prevent a concurrent */ + /* If we wanted to deallocate the entry, we'd first have to clear */ + /* any cache entries pointing to it. That probably requires */ + /* additional synchronization, since we can't prevent a concurrent */ /* cache lookup, which should still be examining deallocated memory.*/ - /* This can only happen if the concurrent access is from another */ - /* thread, and hence has missed the cache, but still... */ + /* This can only happen if the concurrent access is from another */ + /* thread, and hence has missed the cache, but still... */ - /* With GC, we're done, since the pointers from the cache will */ - /* be overwritten, all local pointers to the entries will be */ - /* dropped, and the entry will then be reclaimed. */ + /* With GC, we're done, since the pointers from the cache will */ + /* be overwritten, all local pointers to the entries will be */ + /* dropped, and the entry will then be reclaimed. */ pthread_mutex_unlock(&(key -> lock)); } -/* Note that even the slow path doesn't lock. */ -void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, - tse * volatile * cache_ptr) { +/* Note that even the slow path doesn't lock. */ +void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, + tse * volatile * cache_ptr) { pthread_t self = pthread_self(); unsigned hash_val = HASH(self); tse *entry = key -> hash[hash_val]; GC_ASSERT(qtid != INVALID_QTID); while (entry != NULL && entry -> thread != self) { - entry = entry -> next; - } + entry = entry -> next; + } if (entry == NULL) return NULL; - /* Set cache_entry. */ - entry -> qtid = qtid; - /* It's safe to do this asynchronously. Either value */ - /* is safe, though may produce spurious misses. */ - /* We're replacing one qtid with another one for the */ - /* same thread. */ - *cache_ptr = entry; - /* Again this is safe since pointer assignments are */ - /* presumed atomic, and either pointer is valid. */ + /* Set cache_entry. */ + entry -> qtid = (AO_t)qtid; + /* It's safe to do this asynchronously. Either value */ + /* is safe, though may produce spurious misses. */ + /* We're replacing one qtid with another one for the */ + /* same thread. */ + *cache_ptr = entry; + /* Again this is safe since pointer assignments are */ + /* presumed atomic, and either pointer is valid. */ return entry -> value; } #ifdef GC_ASSERTIONS - -/* Check that that all elements of the data structure associated */ -/* with key are marked. */ -void PREFIXED(check_tsd_marks) (tsd *key) -{ + /* Check that that all elements of the data structure associated */ + /* with key are marked. */ + void PREFIXED(check_tsd_marks) (tsd *key) + { int i; tse *p; if (!GC_is_marked(GC_base(key))) { - ABORT("Unmarked thread-specific-data table"); + ABORT("Unmarked thread-specific-data table"); } for (i = 0; i < TS_HASH_SIZE; ++i) { - for (p = key -> hash[i]; p != 0; p = p -> next) { - if (!GC_is_marked(GC_base(p))) { - GC_err_printf( - "Thread-specific-data entry at %p not marked\n",p); - ABORT("Unmarked tse"); - } - } + for (p = key -> hash[i]; p != 0; p = p -> next) { + if (!GC_is_marked(GC_base(p))) { + GC_err_printf("Thread-specific-data entry at %p not marked\n", p); + ABORT("Unmarked tse"); + } + } } for (i = 0; i < TS_CACHE_SIZE; ++i) { - p = key -> cache[i]; - if (p != &invalid_tse && !GC_is_marked(GC_base(p))) { - GC_err_printf( - "Cached thread-specific-data entry at %p not marked\n",p); - ABORT("Unmarked cached tse"); - } + p = key -> cache[i]; + if (p != &invalid_tse && !GC_is_marked(GC_base(p))) { + GC_err_printf("Cached thread-specific-data entry at %p not marked\n", + p); + ABORT("Unmarked cached tse"); + } } -} - -#endif + } +#endif /* GC_ASSERTIONS */ #endif /* USE_CUSTOM_SPECIFIC */ -- cgit v1.2.1 From c30b3749a27a58760850d47b347c1c06d206b483 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 13 May 2011 15:05:22 +0000 Subject: 2011-05-13 Ivan Maidanski * tests/threadkey_test.c (key_once, main): Work around for Solaris PTHREAD_ONCE_INIT. * tests/threadkey_test.c (LIMIT): Use smaller value for Solaris. --HG-- branch : bdwgc --- ChangeLog | 6 ++++++ tests/threadkey_test.c | 30 ++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4d0d3376..a5ffb560 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-13 Ivan Maidanski + + * tests/threadkey_test.c (key_once, main): Work around for Solaris + PTHREAD_ONCE_INIT. + * tests/threadkey_test.c (LIMIT): Use smaller value for Solaris. + 2011-05-13 Ivan Maidanski * dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c index 5b6a5167..5bf18de0 100755 --- a/tests/threadkey_test.c +++ b/tests/threadkey_test.c @@ -10,7 +10,12 @@ #include pthread_key_t key; -pthread_once_t key_once = PTHREAD_ONCE_INIT; + +#ifdef GC_SOLARIS_THREADS + /* pthread_once_t key_once = { PTHREAD_ONCE_INIT }; */ +#else + pthread_once_t key_once = PTHREAD_ONCE_INIT; +#endif void * entry (void *arg) { @@ -41,7 +46,11 @@ void make_key (void) } #ifndef LIMIT -# define LIMIT 50 +# ifdef GC_SOLARIS_THREADS +# define LIMIT 40 +# else +# define LIMIT 50 +# endif #endif int main (void) @@ -49,13 +58,14 @@ int main (void) int i; GC_INIT (); - pthread_once (&key_once, make_key); - - for (i = 0; i < LIMIT; i++) - { - pthread_t t; - GC_pthread_create (&t, NULL, entry, NULL); - } - +# ifdef GC_SOLARIS_THREADS + pthread_key_create (&key, on_thread_exit); +# else + pthread_once (&key_once, make_key); +# endif + for (i = 0; i < LIMIT; i++) { + pthread_t t; + GC_pthread_create (&t, NULL, entry, NULL); + } return 0; } -- cgit v1.2.1 From 12a8b4cb59eae4c0a8d9f2a13fc473d546965206 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 13 May 2011 15:18:45 +0000 Subject: 2011-05-13 Ivan Maidanski * tests/threadkey_test.c (LIMIT): Use smaller value (don't create more than 30 in parallel by default). --HG-- branch : bdwgc --- ChangeLog | 5 +++++ tests/threadkey_test.c | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index a5ffb560..208daeff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-13 Ivan Maidanski + + * tests/threadkey_test.c (LIMIT): Use smaller value (don't create + more than 30 in parallel by default). + 2011-05-13 Ivan Maidanski * tests/threadkey_test.c (key_once, main): Work around for Solaris diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c index 5bf18de0..0ae94bb1 100755 --- a/tests/threadkey_test.c +++ b/tests/threadkey_test.c @@ -46,11 +46,7 @@ void make_key (void) } #ifndef LIMIT -# ifdef GC_SOLARIS_THREADS -# define LIMIT 40 -# else -# define LIMIT 50 -# endif +# define LIMIT 30 #endif int main (void) -- cgit v1.2.1 From b01c86283c21b43d13117a5d70d0759e4dec67d8 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 16 May 2011 07:06:33 +0000 Subject: 2011-05-16 Ivan Maidanski * pthread_stop_world.c (GC_suspend_handler_inner): Remove "dummy", "sig" local variables; rename my_thread local variable to "self". --HG-- branch : bdwgc --- ChangeLog | 5 +++++ pthread_stop_world.c | 18 ++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 208daeff..d96748e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-16 Ivan Maidanski + + * pthread_stop_world.c (GC_suspend_handler_inner): Remove "dummy", + "sig" local variables; rename my_thread local variable to "self". + 2011-05-13 Ivan Maidanski * tests/threadkey_test.c (LIMIT): Use smaller value (don't create diff --git a/pthread_stop_world.c b/pthread_stop_world.c index feb70a3b..dfb0d8ad 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -178,15 +178,13 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context); /*ARGSUSED*/ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) { - int sig = (int)(word)sig_arg; - int dummy; - pthread_t my_thread = pthread_self(); + pthread_t self = pthread_self(); GC_thread me; IF_CANCEL(int cancel_state;) - AO_t my_stop_count = AO_load(&GC_stop_count); - if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); + if ((signed_word)sig_arg != SIG_SUSPEND) + ABORT("Bad signal in suspend_handler"); DISABLE_CANCEL(cancel_state); /* pthread_setcancelstate is not defined to be async-signal-safe. */ @@ -198,10 +196,10 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) /* cancellation point is inherently a problem, unless there is */ /* some way to disable cancellation in the handler. */ # ifdef DEBUG_THREADS - GC_log_printf("Suspending 0x%x\n", (unsigned)my_thread); + GC_log_printf("Suspending 0x%x\n", (unsigned)self); # endif - me = GC_lookup_thread(my_thread); + me = GC_lookup_thread(self); /* The lookup here is safe, since I'm doing this on behalf */ /* of a thread which holds the allocation lock in order */ /* to stop the world. Thus concurrent modification of the */ @@ -209,7 +207,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) if (me -> stop_info.last_stop_count == my_stop_count) { /* Duplicate signal. OK if we are retrying. */ if (!GC_retry_signals) { - WARN("Duplicate suspend signal in thread %p\n", pthread_self()); + WARN("Duplicate suspend signal in thread %p\n", self); } RESTORE_CANCEL(cancel_state); return; @@ -217,7 +215,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) # ifdef SPARC me -> stop_info.stack_ptr = GC_save_regs_in_stack(); # else - me -> stop_info.stack_ptr = (ptr_t)(&dummy); + me -> stop_info.stack_ptr = (ptr_t)(&me); # endif # ifdef IA64 me -> backing_store_ptr = GC_save_regs_in_stack(); @@ -252,7 +250,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context) /* unlikely to be efficient. */ # ifdef DEBUG_THREADS - GC_log_printf("Continuing 0x%x\n", (unsigned)my_thread); + GC_log_printf("Continuing 0x%x\n", (unsigned)self); # endif RESTORE_CANCEL(cancel_state); } -- cgit v1.2.1 From 8657c970c3ff389703dbc70003504634ab39d3a2 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 16 May 2011 13:12:15 +0000 Subject: 2011-05-16 Ivan Maidanski * pthread_stop_world.c (pthread_sigmask): Undefine even if not DEBUG_THREADS. * pthread_stop_world.c (GC_unblock_gc_signals): New function (only if GC_EXPLICIT_SIGNALS_UNBLOCK). * pthread_support.c (GC_unblock_gc_signals): New prototype. * pthread_support.c (GC_register_my_thread_inner, GC_register_my_thread): Call GC_unblock_gc_signals (only if GC_EXPLICIT_SIGNALS_UNBLOCK); add comment. * include/private/gcconfig.h (GC_EXPLICIT_SIGNALS_UNBLOCK): New macro. --HG-- branch : bdwgc --- ChangeLog | 13 +++++++++++++ include/private/gcconfig.h | 5 +++++ pthread_stop_world.c | 36 ++++++++++++++++++++++++++---------- pthread_support.c | 16 ++++++++++++++++ 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index d96748e4..3eef9290 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-05-16 Ivan Maidanski + + * pthread_stop_world.c (pthread_sigmask): Undefine even if not + DEBUG_THREADS. + * pthread_stop_world.c (GC_unblock_gc_signals): New function (only + if GC_EXPLICIT_SIGNALS_UNBLOCK). + * pthread_support.c (GC_unblock_gc_signals): New prototype. + * pthread_support.c (GC_register_my_thread_inner, + GC_register_my_thread): Call GC_unblock_gc_signals (only if + GC_EXPLICIT_SIGNALS_UNBLOCK); add comment. + * include/private/gcconfig.h (GC_EXPLICIT_SIGNALS_UNBLOCK): New + macro. + 2011-05-16 Ivan Maidanski * pthread_stop_world.c (GC_suspend_handler_inner): Remove "dummy", diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 54d93645..9e277e5b 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2324,6 +2324,11 @@ # define SUNOS5SIGS #endif +#if !defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(SUNOS5SIGS) \ + && !defined(GC_NO_PTHREAD_SIGMASK) +# define GC_EXPLICIT_SIGNALS_UNBLOCK +#endif + #ifdef GC_NETBSD_THREADS # define SIGRTMIN 33 # define SIGRTMAX 63 diff --git a/pthread_stop_world.c b/pthread_stop_world.c index dfb0d8ad..9302f93f 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -43,6 +43,9 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; #include #include "atomic_ops.h" +/* It's safe to call original pthread_sigmask() here. */ +#undef pthread_sigmask + #ifdef DEBUG_THREADS # ifndef NSIG # if defined(MAXSIG) @@ -56,9 +59,6 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; # endif # endif /* NSIG */ - /* It's safe to call original pthread_sigmask() here. */ -# undef pthread_sigmask - void GC_print_sig_mask(void) { sigset_t blocked; @@ -141,6 +141,20 @@ STATIC volatile AO_t GC_world_is_stopped = FALSE; # endif #endif +#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + /* Some targets (eg., Solaris) might require this to be called when */ + /* doing thread registering from the thread destructor. */ + GC_INNER void GC_unblock_gc_signals(void) + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIG_SUSPEND); + sigaddset(&set, SIG_THR_RESTART); + if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) + ABORT("pthread_sigmask failed"); + } +#endif /* GC_EXPLICIT_SIGNALS_UNBLOCK */ + STATIC sem_t GC_suspend_ack_sem; #ifdef GC_NETBSD_THREADS @@ -769,13 +783,15 @@ GC_INNER void GC_start_world(void) } } # ifdef GC_NETBSD_THREADS_WORKAROUND - for (i = 0; i < n_live_threads; i++) - while (0 != (code = sem_wait(&GC_restart_ack_sem))) - if (errno != EINTR) { - if (GC_print_stats) - GC_log_printf("sem_wait() returned %d\n", code); - ABORT("sem_wait() for restart handler failed"); - } + for (i = 0; i < n_live_threads; i++) { + while (0 != (code = sem_wait(&GC_restart_ack_sem))) { + if (errno != EINTR) { + if (GC_print_stats) + GC_log_printf("sem_wait() returned %d\n", code); + ABORT("sem_wait() for restart handler failed"); + } + } + } # endif # ifdef DEBUG_THREADS GC_log_printf("World started\n"); diff --git a/pthread_support.c b/pthread_support.c index 175663c0..4f3be43f 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1358,6 +1358,10 @@ GC_INLINE void GC_record_stack_base(GC_thread me, # endif } +#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + GC_INNER void GC_unblock_gc_signals(void); /* from pthread_stop_world.c */ +#endif + STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, pthread_t my_pthread) { @@ -1372,6 +1376,11 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, me -> stop_info.mach_thread = mach_thread_self(); # endif GC_record_stack_base(me, sb); +# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + /* Since this could be executed from a detached thread */ + /* destructor, our signals might already be blocked. */ + GC_unblock_gc_signals(); +# endif return me; } @@ -1398,8 +1407,15 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) if (me == 0) { me = GC_register_my_thread_inner(sb, self); } else { + /* This code is executed when a thread is registered from the */ + /* client thread key destructor. */ GC_record_stack_base(me, sb); me -> flags &= ~FINISHED; +# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + /* Since this could be executed from a thread destructor, */ + /* our signals might be blocked. */ + GC_unblock_gc_signals(); +# endif } me -> flags |= DETACHED; /* Treat as detached, since we do not need to worry about */ -- cgit v1.2.1 From 1118e3e62fb3a7e672cc3625e89a6368022e3039 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 17 May 2011 06:45:30 +0000 Subject: 2011-05-17 Ivan Maidanski * pthread_support.c (GC_delete_gc_thread): Rename "gc_id" local variable to "t". * win32_threads.c (GC_delete_gc_thread): Ditto. * pthread_support.c (pthread_join, pthread_detach, pthread_cancel): Rename "thread_gc_id" local variable to "t". * win32_threads.c (GC_pthread_detach): Ditto. * win32_threads.c (GC_delete_gc_thread): Remove "gc_nvid" local variable. * win32_threads.c (GC_pthread_join): Rename "joinee" local variable to "t". --HG-- branch : bdwgc --- ChangeLog | 13 +++++++++++++ pthread_support.c | 35 +++++++++++++++++------------------ win32_threads.c | 40 ++++++++++++++++++++-------------------- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3eef9290..e7cd2c7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-05-17 Ivan Maidanski + + * pthread_support.c (GC_delete_gc_thread): Rename "gc_id" local + variable to "t". + * win32_threads.c (GC_delete_gc_thread): Ditto. + * pthread_support.c (pthread_join, pthread_detach, + pthread_cancel): Rename "thread_gc_id" local variable to "t". + * win32_threads.c (GC_pthread_detach): Ditto. + * win32_threads.c (GC_delete_gc_thread): Remove "gc_nvid" local + variable. + * win32_threads.c (GC_pthread_join): Rename "joinee" local + variable to "t". + 2011-05-16 Ivan Maidanski * pthread_stop_world.c (pthread_sigmask): Undefine even if not diff --git a/pthread_support.c b/pthread_support.c index 4f3be43f..58d515d6 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -534,15 +534,15 @@ STATIC void GC_delete_thread(pthread_t id) /* been notified, then there may be more than one thread */ /* in the table with the same pthread id. */ /* This is OK, but we need a way to delete a specific one. */ -STATIC void GC_delete_gc_thread(GC_thread gc_id) +STATIC void GC_delete_gc_thread(GC_thread t) { - pthread_t id = gc_id -> id; + pthread_t id = t -> id; int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ; register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; GC_ASSERT(I_HOLD_LOCK()); - while (p != gc_id) { + while (p != t) { prev = p; p = p -> next; } @@ -1226,12 +1226,12 @@ GC_INNER void GC_thread_exit_proc(void *arg) GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) { int result; - GC_thread thread_gc_id; + GC_thread t; DCL_LOCK_STATE; INIT_REAL_SYMS(); LOCK(); - thread_gc_id = GC_lookup_thread(thread); + t = GC_lookup_thread(thread); /* This is guaranteed to be the intended one, since the thread id */ /* can't have been recycled by pthreads. */ UNLOCK(); @@ -1250,7 +1250,7 @@ GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) if (result == 0) { LOCK(); /* Here the pthread thread id may have been recycled. */ - GC_delete_gc_thread(thread_gc_id); + GC_delete_gc_thread(t); UNLOCK(); } return result; @@ -1259,20 +1259,20 @@ GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) { int result; - GC_thread thread_gc_id; + GC_thread t; DCL_LOCK_STATE; INIT_REAL_SYMS(); LOCK(); - thread_gc_id = GC_lookup_thread(thread); + t = GC_lookup_thread(thread); UNLOCK(); result = REAL_FUNC(pthread_detach)(thread); if (result == 0) { LOCK(); - thread_gc_id -> flags |= DETACHED; + t -> flags |= DETACHED; /* Here the pthread thread id may have been recycled. */ - if (thread_gc_id -> flags & FINISHED) { - GC_delete_gc_thread(thread_gc_id); + if ((t -> flags & FINISHED) != 0) { + GC_delete_gc_thread(t); } UNLOCK(); } @@ -1292,20 +1292,19 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) GC_API int WRAP_FUNC(pthread_cancel)(pthread_t thread) { # ifdef CANCEL_SAFE - GC_thread thread_gc_id; + GC_thread t; DCL_LOCK_STATE; # endif INIT_REAL_SYMS(); # ifdef CANCEL_SAFE LOCK(); - thread_gc_id = GC_lookup_thread(thread); + t = GC_lookup_thread(thread); /* We test DISABLED_GC because pthread_exit could be called at */ - /* the same time. (If thread_gc_id is NULL then pthread_cancel */ - /* should return ESRCH.) */ - if (thread_gc_id != 0 - && (thread_gc_id -> flags & DISABLED_GC) == 0) { - thread_gc_id -> flags |= DISABLED_GC; + /* the same time. (If t is NULL then pthread_cancel should */ + /* return ESRCH.) */ + if (t != NULL && (t -> flags & DISABLED_GC) == 0) { + t -> flags |= DISABLED_GC; GC_dont_gc++; } UNLOCK(); diff --git a/win32_threads.c b/win32_threads.c index 8e0bcc53..cd8e8e8f 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -616,37 +616,36 @@ GC_INNER unsigned char *GC_check_finalizer_nested(void) /* GC_win32_dll_threads is set. */ /* If GC_win32_dll_threads is set it should be called from the */ /* thread being deleted. */ -STATIC void GC_delete_gc_thread(GC_vthread gc_id) +STATIC void GC_delete_gc_thread(GC_vthread t) { # ifndef MSWINCE - CloseHandle(gc_id->handle); + CloseHandle(t->handle); # endif # ifndef GC_NO_THREADS_DISCOVERY if (GC_win32_dll_threads) { /* This is intended to be lock-free. */ /* It is either called synchronously from the thread being */ /* deleted, or by the joining thread. */ - /* In this branch asynchronous changes to *gc_id are possible. */ + /* In this branch asynchronous changes to (*t) are possible. */ /* It's not allowed to call GC_printf (and the friends) here, */ /* see GC_stop_world() for the information. */ - gc_id -> stack_base = 0; - gc_id -> id = 0; + t -> stack_base = 0; + t -> id = 0; # ifdef GC_PTHREADS - GC_PTHREAD_PTRVAL(gc_id->pthread_id) = 0; + GC_PTHREAD_PTRVAL(t->pthread_id) = 0; # endif - AO_store_release(&gc_id->tm.in_use, FALSE); + AO_store_release(&t->tm.in_use, FALSE); } else # endif /* else */ { - /* Cast away volatile qualifier, since we have lock. */ - GC_thread gc_nvid = (GC_thread)gc_id; - DWORD id = gc_nvid -> id; + DWORD id = ((GC_thread)t) -> id; + /* Cast away volatile qualifier, since we have lock. */ word hv = THREAD_TABLE_INDEX(id); register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; GC_ASSERT(I_HOLD_LOCK()); - while (p != gc_nvid) { + while (p != (GC_thread)t) { prev = p; p = p -> tm.next; } @@ -2349,7 +2348,7 @@ GC_INNER void GC_thr_init(void) GC_API int GC_pthread_join(pthread_t pthread_id, void **retval) { int result; - GC_thread joinee; + GC_thread t; # ifdef DEBUG_THREADS GC_log_printf("thread %p(0x%lx) is joining thread %p\n", @@ -2364,21 +2363,22 @@ GC_INNER void GC_thr_init(void) /* FIXME: It would be better if this worked more like */ /* pthread_support.c. */ # ifndef GC_WIN32_PTHREADS - while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10); + while ((t = GC_lookup_pthread(pthread_id)) == 0) + Sleep(10); # endif result = pthread_join(pthread_id, retval); # ifdef GC_WIN32_PTHREADS /* win32_pthreads id are unique */ - joinee = GC_lookup_pthread(pthread_id); + t = GC_lookup_pthread(pthread_id); # endif if (!GC_win32_dll_threads) { DCL_LOCK_STATE; LOCK(); - GC_delete_gc_thread(joinee); + GC_delete_gc_thread(t); UNLOCK(); } /* otherwise DllMain handles it. */ @@ -2524,20 +2524,20 @@ GC_INNER void GC_thr_init(void) GC_API int GC_pthread_detach(pthread_t thread) { int result; - GC_thread thread_gc_id; + GC_thread t; DCL_LOCK_STATE; if (!parallel_initialized) GC_init_parallel(); LOCK(); - thread_gc_id = GC_lookup_pthread(thread); + t = GC_lookup_pthread(thread); UNLOCK(); result = pthread_detach(thread); if (result == 0) { LOCK(); - thread_gc_id -> flags |= DETACHED; + t -> flags |= DETACHED; /* Here the pthread thread id may have been recycled. */ - if (thread_gc_id -> flags & FINISHED) { - GC_delete_gc_thread(thread_gc_id); + if ((t -> flags & FINISHED) != 0) { + GC_delete_gc_thread(t); } UNLOCK(); } -- cgit v1.2.1 From cc800e89a33b44e50038b00cbd25cfd545a576a1 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 17 May 2011 08:59:42 +0000 Subject: 2011-05-17 Ivan Maidanski * pthread_support.c (pthread_join): Add assertion (check thread is finished). * pthread_support.c (GC_register_my_thread): Don't detach the thread if invoked from the thread destructor. * win32_threads.c (GC_register_my_thread): Ditto. * win32_threads.c (GC_unregister_my_thread): Don't delete the thread (just set FINISHED) if the thread is not detached (only if GC_PTHREADS); add assertion (check the thread is not finished). * tests/threadkey_test.c (main): Join some created threads. --HG-- branch : bdwgc --- ChangeLog | 12 ++++++++++++ pthread_support.c | 32 ++++++++++++++++++-------------- tests/threadkey_test.c | 5 ++++- win32_threads.c | 27 +++++++++++++++++++++------ 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7cd2c7a..bb57cc5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-17 Ivan Maidanski + + * pthread_support.c (pthread_join): Add assertion (check thread is + finished). + * pthread_support.c (GC_register_my_thread): Don't detach the + thread if invoked from the thread destructor. + * win32_threads.c (GC_register_my_thread): Ditto. + * win32_threads.c (GC_unregister_my_thread): Don't delete the + thread (just set FINISHED) if the thread is not detached (only if + GC_PTHREADS); add assertion (check the thread is not finished). + * tests/threadkey_test.c (main): Join some created threads. + 2011-05-17 Ivan Maidanski * pthread_support.c (GC_delete_gc_thread): Rename "gc_id" local diff --git a/pthread_support.c b/pthread_support.c index 58d515d6..f2d1754c 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1250,6 +1250,7 @@ GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) if (result == 0) { LOCK(); /* Here the pthread thread id may have been recycled. */ + GC_ASSERT((t -> flags & FINISHED) != 0); GC_delete_gc_thread(t); UNLOCK(); } @@ -1402,23 +1403,26 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) LOCK(); me = GC_lookup_thread(self); - if (0 == me || (me -> flags & FINISHED) != 0) { - if (me == 0) { - me = GC_register_my_thread_inner(sb, self); - } else { - /* This code is executed when a thread is registered from the */ - /* client thread key destructor. */ - GC_record_stack_base(me, sb); - me -> flags &= ~FINISHED; -# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK - /* Since this could be executed from a thread destructor, */ - /* our signals might be blocked. */ - GC_unblock_gc_signals(); -# endif - } + if (0 == me) { + me = GC_register_my_thread_inner(sb, self); me -> flags |= DETACHED; /* Treat as detached, since we do not need to worry about */ /* pointer results. */ +# if defined(THREAD_LOCAL_ALLOC) + GC_init_thread_local(&(me->tlfs)); +# endif + UNLOCK(); + return GC_SUCCESS; + } else if ((me -> flags & FINISHED) != 0) { + /* This code is executed when a thread is registered from the */ + /* client thread key destructor. */ + GC_record_stack_base(me, sb); + me -> flags &= ~FINISHED; /* but not DETACHED */ +# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + /* Since this could be executed from a thread destructor, */ + /* our signals might be blocked. */ + GC_unblock_gc_signals(); +# endif # if defined(THREAD_LOCAL_ALLOC) GC_init_thread_local(&(me->tlfs)); # endif diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c index 0ae94bb1..1ea761d9 100755 --- a/tests/threadkey_test.c +++ b/tests/threadkey_test.c @@ -61,7 +61,10 @@ int main (void) # endif for (i = 0; i < LIMIT; i++) { pthread_t t; - GC_pthread_create (&t, NULL, entry, NULL); + void *res; + if (GC_pthread_create (&t, NULL, entry, NULL) == 0 + && (i & 1) != 0) + GC_pthread_join (t, &res); } return 0; } diff --git a/win32_threads.c b/win32_threads.c index cd8e8e8f..68752fae 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -733,7 +733,7 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) # ifdef GC_PTHREADS /* else */ if ((me -> flags & FINISHED) != 0) { GC_record_stack_base(me, sb); - me -> flags = (me -> flags & ~FINISHED) | DETACHED; + me -> flags &= ~FINISHED; /* but not DETACHED */ # ifdef THREAD_LOCAL_ALLOC GC_init_thread_local((GC_tlfs)(&me->tlfs)); # endif @@ -761,19 +761,34 @@ GC_API int GC_CALL GC_unregister_my_thread(void) /* Can't happen: see GC_use_threads_discovery(). */ GC_ASSERT(FALSE); # else +# ifdef GC_PTHREADS + /* FIXME: If not DETACHED then just set FINISHED. */ +# endif /* FIXME: Should we just ignore this? */ GC_delete_thread(GetCurrentThreadId()); # endif } else { +# if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS) + GC_thread me; +# endif DWORD thread_id = GetCurrentThreadId(); + LOCK(); +# if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS) + me = GC_lookup_thread_inner(thread_id); + GC_ASSERT(!(me -> flags & FINISHED)); +# endif # if defined(THREAD_LOCAL_ALLOC) - { - GC_thread me = GC_lookup_thread_inner(thread_id); - GC_destroy_thread_local(&(me->tlfs)); - } + GC_destroy_thread_local(&(me->tlfs)); +# endif +# ifdef GC_PTHREADS + if ((me -> flags & DETACHED) == 0) { + me -> flags |= FINISHED; + } else # endif - GC_delete_thread(thread_id); + /* else */ { + GC_delete_thread(thread_id); + } UNLOCK(); } return GC_SUCCESS; -- cgit v1.2.1 From f2fd8dfe5697ea8949268a47a2fd9767eb2dea8d Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 18 May 2011 08:55:41 +0000 Subject: 2011-05-18 Ivan Maidanski * checksums.c (GC_check_blocks, GC_check_dirty): Do log printing only if GC_print_stats; print errors using GC_err_printf. * checksums.c (GC_check_blocks): Join adjacent printf() calls into a single one. --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ checksums.c | 26 ++++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb57cc5c..2bf04567 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-18 Ivan Maidanski + + * checksums.c (GC_check_blocks, GC_check_dirty): Do log printing + only if GC_print_stats; print errors using GC_err_printf. + * checksums.c (GC_check_blocks): Join adjacent printf() calls into + a single one. + 2011-05-17 Ivan Maidanski * pthread_support.c (pthread_join): Add assertion (check thread is diff --git a/checksums.c b/checksums.c index 0400697d..b93bcf98 100644 --- a/checksums.c +++ b/checksums.c @@ -165,13 +165,14 @@ STATIC void GC_check_blocks(void) GC_bytes_in_used_blocks = 0; GC_apply_to_all_blocks(GC_add_block, (word)0); - GC_log_printf( - "GC_bytes_in_used_blocks = %lu, bytes_in_free_blocks = %lu ", - (unsigned long)GC_bytes_in_used_blocks, - (unsigned long)bytes_in_free_blocks); - GC_log_printf("GC_heapsize = %lu\n", (unsigned long)GC_heapsize); + if (GC_print_stats) + GC_log_printf("GC_bytes_in_used_blocks = %lu," + " bytes_in_free_blocks = %lu, heapsize = %lu\n", + (unsigned long)GC_bytes_in_used_blocks, + (unsigned long)bytes_in_free_blocks, + (unsigned long)GC_heapsize); if (GC_bytes_in_used_blocks + bytes_in_free_blocks != GC_heapsize) { - GC_log_printf("LOST SOME BLOCKS!!\n"); + GC_err_printf("LOST SOME BLOCKS!!\n"); } } @@ -203,19 +204,20 @@ void GC_check_dirty(void) } } out: - GC_log_printf("Checked %lu clean and %lu dirty pages\n", - (unsigned long)GC_n_clean, (unsigned long)GC_n_dirty); + if (GC_print_stats) + GC_log_printf("Checked %lu clean and %lu dirty pages\n", + (unsigned long)GC_n_clean, (unsigned long)GC_n_dirty); if (GC_n_dirty_errors > 0) { - GC_log_printf("Found %d dirty bit errors (%d were faulted)\n", + GC_err_printf("Found %d dirty bit errors (%d were faulted)\n", GC_n_dirty_errors, GC_n_faulted_dirty_errors); } if (GC_n_changed_errors > 0) { - GC_log_printf("Found %lu changed bit errors\n", + GC_err_printf("Found %lu changed bit errors\n", (unsigned long)GC_n_changed_errors); - GC_log_printf( + GC_err_printf( "These may be benign (provoked by nonpointer changes)\n"); # ifdef THREADS - GC_log_printf( + GC_err_printf( "Also expect 1 per thread currently allocating a stubborn obj\n"); # endif } -- cgit v1.2.1 From 40523425ef8624ab3ad7381588dd6effcdb12388 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 18 May 2011 09:40:00 +0000 Subject: 2011-05-18 Ivan Maidanski * include/private/gcconfig.h (MPROTECT_VDB): Undefine if PROC_VDB. * tests/test.c (NUMBER_ROUND_UP): New macro. * tests/test.c (check_heap_stats): Round up total expected heap size to the nearest 4 MiB bound. * tests/test.c (check_heap_stats): Print the current and expected heap sizes in case of failure. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ include/private/gcconfig.h | 5 +++++ tests/test.c | 13 +++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2bf04567..88fefdc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-18 Ivan Maidanski + + * include/private/gcconfig.h (MPROTECT_VDB): Undefine if PROC_VDB. + * tests/test.c (NUMBER_ROUND_UP): New macro. + * tests/test.c (check_heap_stats): Round up total expected heap + size to the nearest 4 MiB bound. + * tests/test.c (check_heap_stats): Print the current and expected + heap sizes in case of failure. + 2011-05-18 Ivan Maidanski * checksums.c (GC_check_blocks, GC_check_dirty): Do log printing diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 9e277e5b..9052d22e 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2399,6 +2399,11 @@ /* #undef GWW_VDB - handled in os_dep.c */ #endif +#ifdef PROC_VDB + /* Multi-VDB mode is not implemented. */ +# undef MPROTECT_VDB +#endif + #if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ && !defined(GWW_VDB) && !defined(GC_DISABLE_INCREMENTAL) # define DEFAULT_VDB diff --git a/tests/test.c b/tests/test.c index 63a10527..b844b63c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1236,6 +1236,8 @@ void run_one_test(void) GC_log_printf("Finished %p\n", &start_time); } +#define NUMBER_ROUND_UP(v, bound) ((((v) + (bound) - 1) / (bound)) * (bound)) + void check_heap_stats(void) { size_t max_heap_sz; @@ -1271,6 +1273,10 @@ void check_heap_stats(void) max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4; # endif # endif +# endif + max_heap_sz *= n_tests; +# ifdef USE_MMAP + max_heap_sz = NUMBER_ROUND_UP(max_heap_sz, 4 * 1024 * 1024); # endif /* Garbage collect repeatedly so that all inaccessible objects */ /* can be finalized. */ @@ -1337,8 +1343,11 @@ void check_heap_stats(void) GC_printf("Incorrect execution - missed some allocations\n"); FAIL; } - if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz*n_tests) { - GC_printf("Unexpected heap growth - collector may be broken\n"); + if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz) { + GC_printf("Unexpected heap growth - collector may be broken" + " (heapsize: %lu, expected: %u)\n", + (unsigned long)(GC_get_heap_size() + GC_get_unmapped_bytes()), + max_heap_sz); FAIL; } # ifdef THREADS -- cgit v1.2.1 From 8cbc40b57d9759088c475a92d2290164a7e3d3b3 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 18 May 2011 09:46:36 +0000 Subject: 2011-05-18 Ivan Maidanski * include/private/gcconfig.h (MPROTECT_VDB): Enable for Solaris in single-threaded environment. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ include/private/gcconfig.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index 88fefdc9..c76b4023 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-18 Ivan Maidanski + + * include/private/gcconfig.h (MPROTECT_VDB): Enable for Solaris in + single-threaded environment. + 2011-05-18 Ivan Maidanski * include/private/gcconfig.h (MPROTECT_VDB): Undefine if PROC_VDB. diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 9052d22e..e2238790 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -1129,6 +1129,9 @@ # ifdef SOLARIS25_PROC_VDB_BUG_FIXED # define PROC_VDB # endif +# ifndef GC_THREADS +# define MPROTECT_VDB +# endif # define DYNAMIC_LOADING # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP @@ -2201,6 +2204,9 @@ # ifdef SOLARIS25_PROC_VDB_BUG_FIXED # define PROC_VDB # endif +# ifndef GC_THREADS +# define MPROTECT_VDB +# endif # define DYNAMIC_LOADING # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP -- cgit v1.2.1 From 0d9a36c005b8eaa3415bf545b7d6e947dbd4e251 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 19 May 2011 07:50:49 +0000 Subject: 2011-05-19 Ivan Maidanski (really Jie Liu) * include/private/gcconfig.h (end, InitStackBottom): Declare extern variable for RTEMS. * include/private/gcconfig.h (DATASTART, DATAEND, STACKBOTTOM): Update (for RTEMS). * include/private/gcconfig.h (DATAEND): Fix a typo in the macro name (for RTEMS). * tests/test.c (CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER): Replace with CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER (for RTEMS). --HG-- branch : bdwgc --- ChangeLog | 11 +++++++++++ include/private/gcconfig.h | 8 +++++--- tests/test.c | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c76b4023..fc728d08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-19 Ivan Maidanski (really Jie Liu) + + * include/private/gcconfig.h (end, InitStackBottom): Declare + extern variable for RTEMS. + * include/private/gcconfig.h (DATASTART, DATAEND, STACKBOTTOM): + Update (for RTEMS). + * include/private/gcconfig.h (DATAEND): Fix a typo in the macro + name (for RTEMS). + * tests/test.c (CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER): + Replace with CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER (for RTEMS). + 2011-05-18 Ivan Maidanski * include/private/gcconfig.h (MPROTECT_VDB): Enable for Solaris in diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index e2238790..5cd3672d 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -1380,9 +1380,11 @@ # define OS_TYPE "RTEMS" # include extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfffff) & ~0xfffff)) -# define DATAENT ((ptr_t)(DATASTART + 0xfffff)) -# define STACKBOTTOM ((ptr_t) 0x03fff000) + extern int end[]; + extern void *InitStackBottom; +# define DATASTART ((ptr_t)etext) +# define DATAEND ((ptr_t)end) +# define STACKBOTTOM ((ptr_t)InitStackBottom) # endif # ifdef DOS4GW # define OS_TYPE "DOS4GW" diff --git a/tests/test.c b/tests/test.c index b844b63c..e7826c2b 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1393,7 +1393,7 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) WINMAIN_LPTSTR cmd, int n) #elif defined(RTEMS) # include -# define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER +# define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER # define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER # define CONFIGURE_RTEMS_INIT_TASKS_TABLE # define CONFIGURE_MAXIMUM_TASKS 1 -- cgit v1.2.1 From 673d34fcb4f129d4494fcc8e4098ebcbc76c4490 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 20 May 2011 07:53:39 +0000 Subject: 2011-05-20 Ivan Maidanski * doc/README.solaris2: Update. --HG-- branch : bdwgc --- ChangeLog | 4 ++++ doc/README.solaris2 | 20 +++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc728d08..041cce51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-20 Ivan Maidanski + + * doc/README.solaris2: Update. + 2011-05-19 Ivan Maidanski (really Jie Liu) * include/private/gcconfig.h (end, InitStackBottom): Declare diff --git a/doc/README.solaris2 b/doc/README.solaris2 index f9141063..d5716e4f 100644 --- a/doc/README.solaris2 +++ b/doc/README.solaris2 @@ -13,7 +13,7 @@ not safe: "Many library routines use malloc() internally, so use brk() and sbrk() only when you know that malloc() definitely will not be used by any library routine." This doesn't make a lot of sense to me, since there seems to be no documentation as to which routines can transitively call malloc. -Nonetheless, under Solaris2, the collector now (since 4.12) allocates +Nonetheless, under Solaris2, the collector now allocates memory using mmap by default. (It defines USE_MMAP in gcconfig.h.) You may want to reverse this decisions if you use -DREDIRECT_MALLOC=... @@ -24,21 +24,19 @@ The collector must be compiled with -DGC_THREADS to be thread safe. This assumes use of the pthread_ interface. Old style Solaris threads are no longer supported. -It is also essential that gc.h be included in files that call thr_create, -thr_join, thr_suspend, thr_continue, or dlopen. Gc.h macro defines -these to also do GC bookkeeping, etc. Gc.h must be included with -one or both of these macros defined, otherwise -these replacements are not visible. -A collector built in this way way only be used by programs that are -linked with the threads library. +It is also essential that gc.h be included in files that call pthread_create, +pthread_join, pthread_detach, or dlopen. gc.h macro defines these to also do +GC bookkeeping, etc. gc.h must be included with one or both of these macros +defined, otherwise these replacements are not visible. A collector built in +this way way only be used by programs that are linked with the threads library. Since 5.0 alpha5, dlopen disables collection temporarily, unless USE_PROC_FOR_LIBRARIES is defined. In some unlikely cases, this can result in unpleasant heap growth. But it seems better than the race/deadlock issues we had before. -If solaris_threads are used on an X86 processor with malloc redirected to -GC_malloc, it is necessary to call GC_thr_init explicitly before forking the +If threads are used on an X86 processor with malloc redirected to +GC_malloc, it is necessary to call GC_INIT explicitly before forking the first thread. (This avoids a deadlock arising from calling GC_thr_init with the allocation lock held.) @@ -46,7 +44,7 @@ It appears that there is a problem in using gc_cpp.h in conjunction with Solaris threads and Sun's C++ runtime. Apparently the overloaded new operator is invoked by some iostream initialization code before threads are correctly initialized. As a result, call to thr_self() in garbage collector -initialization segfaults. Currently the only known workaround is to not +initialization SEGV faults. Currently the only known workaround is to not invoke the garbage collector from a user defined global operator new, or to have it invoke the garbage-collector's allocators only after main has started. (Note that the latter requires a moderately expensive test in operator -- cgit v1.2.1 From 9210c35043d6a76e4c65a37d235f69626ae55835 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 20 May 2011 09:57:35 +0000 Subject: 2011-05-20 Ivan Maidanski * mark.c (alloc_mark_stack): Use FALSE/TRUE (instead of 0/1) for boolean local variables. * doc/README.macros (GC_PREFER_MPROTECT_VDB): Update. * os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty, GC_remove_protection): Define for GWW_VDB and PROC_VDB in a single place. * os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty): Compute PHT_HASH(h) only once (store result to a local variable). --HG-- branch : bdwgc --- ChangeLog | 11 ++++ doc/README.macros | 5 +- mark.c | 4 +- os_dep.c | 168 +++++++++++++++++++++++------------------------------- 4 files changed, 88 insertions(+), 100 deletions(-) diff --git a/ChangeLog b/ChangeLog index 041cce51..54ad2e01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-20 Ivan Maidanski + + * mark.c (alloc_mark_stack): Use FALSE/TRUE (instead of 0/1) for + boolean local variables. + * doc/README.macros (GC_PREFER_MPROTECT_VDB): Update. + * os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty, + GC_remove_protection): Define for GWW_VDB and PROC_VDB in a single + place. + * os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty): Compute + PHT_HASH(h) only once (store result to a local variable). + 2011-05-20 Ivan Maidanski * doc/README.solaris2: Update. diff --git a/doc/README.macros b/doc/README.macros index 4fd5c840..a6291baf 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -506,8 +506,9 @@ DONT_USE_USER32_DLL (Win32 only) Don't use "user32" DLL import library (containing MessageBox() entry); useful for a static GC library. GC_PREFER_MPROTECT_VDB Choose MPROTECT_VDB manually in case of multiple - virtual dirty bit strategies are implemented (at present useful on Win32 - to force MPROTECT_VDB strategy instead of the default GWW_VDB one). + virtual dirty bit strategies are implemented (at present useful on Win32 and + Solaris to force MPROTECT_VDB strategy instead of the default GWW_VDB or + PROC_VDB ones). GC_IGNORE_GCJ_INFO Disable GCJ-style type information (useful for debugging on WinCE). diff --git a/mark.c b/mark.c index 5fd37aef..b962863b 100644 --- a/mark.c +++ b/mark.c @@ -1198,12 +1198,12 @@ static void alloc_mark_stack(size_t n) # ifdef GWW_VDB /* Don't recycle a stack segment obtained with the wrong flags. */ /* Win32 GetWriteWatch requires the right kind of memory. */ - static GC_bool GC_incremental_at_stack_alloc = 0; + static GC_bool GC_incremental_at_stack_alloc = FALSE; GC_bool recycle_old = (!GC_incremental || GC_incremental_at_stack_alloc); GC_incremental_at_stack_alloc = GC_incremental; # else -# define recycle_old 1 +# define recycle_old TRUE # endif GC_mark_stack_too_small = FALSE; diff --git a/os_dep.c b/os_dep.c index bff6cde9..1fc63625 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1557,11 +1557,9 @@ void GC_register_data_segments(void) # else /* !OS2 */ # if defined(GWW_VDB) - # ifndef MEM_WRITE_WATCH # define MEM_WRITE_WATCH 0x200000 # endif - # ifndef WRITE_WATCH_FLAG_RESET # define WRITE_WATCH_FLAG_RESET 1 # endif @@ -1648,9 +1646,9 @@ void GC_register_data_segments(void) done = TRUE; } -# else /* !GWW_VDB */ +# else # define GetWriteWatch_alloc_flag 0 -# endif /* GWW_VDB */ +# endif /* !GWW_VDB */ # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) @@ -2607,7 +2605,6 @@ STATIC void GC_default_push_other_roots(void) # endif /* SN_TARGET_PS3 */ GC_INNER void (*GC_push_other_roots)(void) = GC_default_push_other_roots; - #endif /* THREADS */ /* @@ -2658,9 +2655,45 @@ STATIC void GC_default_push_other_roots(void) STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2) { register int i; - for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i]; } + +# ifdef MPROTECT_VDB + STATIC GC_bool GC_gww_page_was_dirty(struct hblk * h) +# else + GC_INNER GC_bool GC_page_was_dirty(struct hblk * h) +# endif + { + register word index; + if (HDR(h) == 0) + return TRUE; + index = PHT_HASH(h); + return get_pht_entry_from_index(GC_grungy_pages, index); + } + +# if defined(CHECKSUMS) || defined(PROC_VDB) + /* Used only if GWW_VDB. */ +# ifdef MPROTECT_VDB + STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h) +# else + GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h) +# endif + { + register word index; + if (HDR(h) == 0) + return TRUE; + index = PHT_HASH(h); + return get_pht_entry_from_index(GC_written_pages, index); + } +# endif /* CHECKSUMS || PROC_VDB */ + +# ifndef MPROTECT_VDB + /* Ignore write hints. They don't help us here. */ + /*ARGSUSED*/ + GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, + GC_bool is_ptrfree) {} +# endif + #endif /* PROC_VDB || GWW_VDB */ #ifdef GWW_VDB @@ -2682,7 +2715,7 @@ STATIC void GC_default_push_other_roots(void) detect_GetWriteWatch(); GC_dirty_maintained = GC_GWW_AVAILABLE(); } -# endif +# endif /* !MPROTECT_VDB */ # ifdef MPROTECT_VDB STATIC void GC_gww_read_dirty(void) @@ -2761,40 +2794,9 @@ STATIC void GC_default_push_other_roots(void) GC_or_pages(GC_written_pages, GC_grungy_pages); } - -# ifdef MPROTECT_VDB - STATIC GC_bool GC_gww_page_was_dirty(struct hblk * h) -# else - GC_INNER GC_bool GC_page_was_dirty(struct hblk * h) -# endif - { - return HDR(h) == 0 || - get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h)); - } - -# ifdef CHECKSUMS - /* Used only if GWW_VDB. */ -# ifdef MPROTECT_VDB - STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h) -# else - GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h) -# endif - { - return HDR(h) == 0 || - get_pht_entry_from_index(GC_written_pages, PHT_HASH(h)); - } -# endif /* CHECKSUMS */ - -# ifndef MPROTECT_VDB - /*ARGSUSED*/ - GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, - GC_bool is_ptrfree) {} -# endif - #endif /* GWW_VDB */ #ifdef DEFAULT_VDB - /* All of the following assume the allocation lock is held. */ /* The client asserts that unallocated pages in the heap are never */ @@ -2847,17 +2849,15 @@ STATIC void GC_default_push_other_roots(void) /*ARGSUSED*/ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) {} - #endif /* DEFAULT_VDB */ #ifdef MANUAL_VDB - /* Initialize virtual dirty bit implementation. */ GC_INNER void GC_dirty_init(void) { if (GC_print_stats == VERBOSE) GC_log_printf("Initializing MANUAL_VDB...\n"); - /* GC_dirty_pages and GC_grungy_pages are already cleared. */ + /* GC_dirty_pages and GC_grungy_pages are already cleared. */ GC_dirty_maintained = TRUE; } @@ -2904,9 +2904,7 @@ STATIC void GC_default_push_other_roots(void) #endif /* MANUAL_VDB */ - #ifdef MPROTECT_VDB - /* See DEFAULT_VDB for interface descriptions. */ /* @@ -3591,25 +3589,23 @@ ssize_t read(int fd, void *buf, size_t nbyte) /* We should probably also do this for __read, or whatever stdio */ /* actually calls. */ #endif - #endif /* 0 */ -#ifdef CHECKSUMS - /*ARGSUSED*/ - GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h) - { -# if defined(GWW_VDB) - if (GC_GWW_AVAILABLE()) - return GC_gww_page_was_ever_dirty(h); -# endif - return(TRUE); - } -#endif /* CHECKSUMS */ - -# endif /* MPROTECT_VDB */ +# ifdef CHECKSUMS + /*ARGSUSED*/ + GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h) + { +# if defined(GWW_VDB) + if (GC_GWW_AVAILABLE()) + return GC_gww_page_was_ever_dirty(h); +# endif + return(TRUE); + } +# endif /* CHECKSUMS */ -# ifdef PROC_VDB +#endif /* MPROTECT_VDB */ +#ifdef PROC_VDB /* * See DEFAULT_VDB for interface descriptions. */ @@ -3621,19 +3617,18 @@ ssize_t read(int fd, void *buf, size_t nbyte) * address space), but it avoids intercepting system calls. */ -#include -#include -#include -#include -#include -#include -#include - -#define INITIAL_BUF_SZ 16384 -STATIC word GC_proc_buf_size = INITIAL_BUF_SZ; -STATIC char *GC_proc_buf = NULL; +# include +# include +# include +# include +# include +# include +# include -STATIC int GC_proc_fd = 0; +# define INITIAL_BUF_SZ 16384 + STATIC word GC_proc_buf_size = INITIAL_BUF_SZ; + STATIC char *GC_proc_buf = NULL; + STATIC int GC_proc_fd = 0; GC_INNER void GC_dirty_init(void) { @@ -3662,12 +3657,7 @@ GC_INNER void GC_dirty_init(void) GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size); } -/* Ignore write hints. They don't help us here. */ -/*ARGSUSED*/ -GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, - GC_bool is_ptrfree) {} - -#define READ read +# define READ read GC_INNER void GC_read_dirty(void) { @@ -3739,24 +3729,10 @@ GC_INNER void GC_read_dirty(void) GC_or_pages(GC_written_pages, GC_grungy_pages); } -#undef READ +# undef READ +#endif /* PROC_VDB */ -GC_INNER 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_INNER 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); -} - -# endif /* PROC_VDB */ - - -# ifdef PCR_VDB +#ifdef PCR_VDB # include "vd/PCR_VD.h" @@ -3817,7 +3793,7 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE); } -# endif /* PCR_VDB */ +#endif /* PCR_VDB */ #if defined(MPROTECT_VDB) && defined(DARWIN) /* The following sources were used as a "reference" for this exception @@ -3998,10 +3974,10 @@ typedef enum { GC_INNER void GC_darwin_register_mach_handler_thread(mach_port_t thread); # endif -#else /* !THREADS */ +#else /* The compiler should optimize away any GC_mprotect_state computations */ # define GC_mprotect_state GC_MP_NORMAL -#endif +#endif /* !THREADS */ STATIC void *GC_mprotect_thread(void *arg) { -- cgit v1.2.1 From 96c2f8c9171d173780d818c138465e28b472c6d7 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 20 May 2011 15:09:18 +0000 Subject: 2011-05-20 Ivan Maidanski * mark.c (GC_push_selected): Remove "push_fn" argument (use GC_push_all directly); update the documentation; reformat the comment. * mark.c (GC_push_conditional): Simplify the code (for better readability). --HG-- branch : bdwgc --- ChangeLog | 8 ++++++++ mark.c | 61 ++++++++++++++++++++++++++++--------------------------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index 54ad2e01..b812e3cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-20 Ivan Maidanski + + * mark.c (GC_push_selected): Remove "push_fn" argument (use + GC_push_all directly); update the documentation; reformat the + comment. + * mark.c (GC_push_conditional): Simplify the code (for better + readability). + 2011-05-20 Ivan Maidanski * mark.c (alloc_mark_stack): Use FALSE/TRUE (instead of 0/1) for diff --git a/mark.c b/mark.c index b962863b..aff1e2fe 100644 --- a/mark.c +++ b/mark.c @@ -1281,53 +1281,50 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) #ifndef GC_DISABLE_INCREMENTAL - /* - * 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.) - */ + /* Analogous to the above, but push only those pages h with */ + /* dirty_fn(h) != 0. We use GC_push_all 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 GC_push_all pushes a small fixed */ + /* number of entries. (This is invoked only if GC_push_all 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, - GC_bool (*dirty_fn)(struct hblk *), - void (*push_fn)(ptr_t, ptr_t)) + GC_bool (*dirty_fn)(struct hblk *)) { struct hblk * h; bottom = (ptr_t)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1)); top = (ptr_t)(((word) top) & ~(ALIGNMENT-1)); - if (top == 0 || bottom == top) return; + h = HBLKPTR(bottom + HBLKSIZE); if (top <= (ptr_t) h) { if ((*dirty_fn)(h-1)) { - (*push_fn)(bottom, top); + GC_push_all(bottom, top); } return; } if ((*dirty_fn)(h-1)) { - (*push_fn)(bottom, (ptr_t)h); + GC_push_all(bottom, (ptr_t)h); } + while ((ptr_t)(h+1) <= top) { if ((*dirty_fn)(h)) { if ((word)(GC_mark_stack_top - GC_mark_stack) > 3 * GC_mark_stack_size / 4) { /* Danger of mark stack overflow */ - (*push_fn)((ptr_t)h, top); + GC_push_all((ptr_t)h, top); return; } else { - (*push_fn)((ptr_t)h, (ptr_t)(h+1)); + GC_push_all((ptr_t)h, (ptr_t)(h+1)); } } h++; } - if ((ptr_t)h != top) { - if ((*dirty_fn)(h)) { - (*push_fn)((ptr_t)h, top); - } + + if ((ptr_t)h != top && (*dirty_fn)(h)) { + GC_push_all((ptr_t)h, top); } if (GC_mark_stack_top >= GC_mark_stack_limit) { ABORT("Unexpected mark stack overflow"); @@ -1341,20 +1338,18 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) GC_INNER 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); -# else - GC_push_all(bottom, top); -# endif - } else { + if (!all) { + GC_push_selected(bottom, top, GC_page_was_dirty); + } else { +# ifdef PROC_VDB + if (GC_dirty_maintained) { + /* Pages that were never dirtied cannot contain pointers. */ + GC_push_selected(bottom, top, GC_page_was_ever_dirty); + } else +# endif + /* else */ { GC_push_all(bottom, top); } - } else { - GC_push_selected(bottom, top, GC_page_was_dirty, GC_push_all); } } #endif /* !GC_DISABLE_INCREMENTAL */ -- cgit v1.2.1 From aa77490f8878487a93afbdab19dbe558fe557177 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 22 May 2011 12:46:28 +0000 Subject: 2011-05-22 Ivan Maidanski * os_dep.c (GC_get_main_stack_base): Convert to GC_get_stack_base for BeOS and OS/2; define HAVE_GET_STACK_BASE. * os_dep.c (GET_MAIN_STACKBASE_SPECIAL): Define when a specific GC_get_main_stack_base implementation is defined. * os_dep.c (GC_get_main_stack_base): Define that based on GC_get_stack_base() in a single place (only if GET_MAIN_STACKBASE_SPECIAL is unset); check GC_get_stack_base() result. --HG-- branch : bdwgc --- ChangeLog | 11 +++++++++++ os_dep.c | 65 +++++++++++++++++++++++---------------------------------------- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index b812e3cb..66b3e5f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-22 Ivan Maidanski + + * os_dep.c (GC_get_main_stack_base): Convert to GC_get_stack_base + for BeOS and OS/2; define HAVE_GET_STACK_BASE. + * os_dep.c (GET_MAIN_STACKBASE_SPECIAL): Define when a specific + GC_get_main_stack_base implementation is defined. + * os_dep.c (GC_get_main_stack_base): Define that based on + GC_get_stack_base() in a single place (only if + GET_MAIN_STACKBASE_SPECIAL is unset); check GC_get_stack_base() + result. + 2011-05-20 Ivan Maidanski * mark.c (GC_push_selected): Remove "push_fn" argument (use diff --git a/os_dep.c b/os_dep.c index 1fc63625..7769274e 100644 --- a/os_dep.c +++ b/os_dep.c @@ -774,7 +774,6 @@ GC_INNER word GC_page_size = 0; sb -> mem_base = trunc_sp + size; return GC_SUCCESS; } - # else /* CYGWIN32 */ /* An alternate version for Cygwin (adapted from Dave Korn's */ /* gcc version of boehm-gc). */ @@ -787,15 +786,6 @@ GC_INNER word GC_page_size = 0; # endif /* CYGWIN32 */ # define HAVE_GET_STACK_BASE - /* This is always called from the main thread. */ - ptr_t GC_get_main_stack_base(void) - { - struct GC_stack_base sb; - GC_get_stack_base(&sb); - GC_ASSERT((void *)&sb HOTTER_THAN sb.mem_base); - return (ptr_t)sb.mem_base; - } - #else /* !MSWIN32 */ GC_INNER void GC_setpagesize(void) { @@ -811,25 +801,29 @@ GC_INNER word GC_page_size = 0; #ifdef BEOS # include - ptr_t GC_get_main_stack_base(void) + + GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) { thread_info th; get_thread_info(find_thread(NULL),&th); - return th.stack_end; + sb->mem_base = th.stack_end; + return GC_SUCCESS; } +# define HAVE_GET_STACK_BASE #endif /* BEOS */ #ifdef OS2 - ptr_t GC_get_main_stack_base(void) + GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) { - PTIB ptib; + PTIB ptib; /* thread information block */ PPIB ppib; - if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) { ABORT("DosGetInfoBlocks failed"); } - return((ptr_t)(ptib -> tib_pstacklimit)); + sb->mem_base = ptib->tib_pstacklimit; + return GC_SUCCESS; } +# define HAVE_GET_STACK_BASE #endif /* OS2 */ # ifdef AMIGA @@ -1113,11 +1107,9 @@ GC_INNER word GC_page_size = 0; ABORT("Absurd stack bottom value"); return (ptr_t)result; } - #endif /* LINUX_STACKBOTTOM */ #ifdef FREEBSD_STACKBOTTOM - /* This uses an undocumented sysctl call, but at least one expert */ /* believes it will stay. */ @@ -1141,6 +1133,7 @@ GC_INNER word GC_page_size = 0; { return STACKBOTTOM; } +# define GET_MAIN_STACKBASE_SPECIAL #elif !defined(BEOS) && !defined(AMIGA) && !defined(OS2) \ && !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) \ && !defined(GC_OPENBSD_THREADS) \ @@ -1223,6 +1216,7 @@ GC_INNER word GC_page_size = 0; GC_ASSERT((ptr_t)(&result) HOTTER_THAN result); return(result); } +# define GET_MAIN_STACKBASE_SPECIAL #endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */ #if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) && !defined(NACL) @@ -1281,7 +1275,6 @@ GC_INNER word GC_page_size = 0; # endif return GC_SUCCESS; } - # define HAVE_GET_STACK_BASE #endif /* GC_LINUX_THREADS */ @@ -1315,17 +1308,7 @@ GC_INNER word GC_page_size = 0; sb->mem_base = stack.ss_sp; return GC_SUCCESS; } - # define HAVE_GET_STACK_BASE - - /* This is always called from the main thread. */ - ptr_t GC_get_main_stack_base(void) - { - struct GC_stack_base sb; - GC_get_stack_base(&sb); - GC_ASSERT((void *)&sb HOTTER_THAN sb.mem_base); - return (ptr_t)sb.mem_base; - } #endif /* GC_OPENBSD_THREADS */ #if defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC) @@ -1375,19 +1358,7 @@ GC_INNER word GC_page_size = 0; b -> mem_base = s.ss_sp; return GC_SUCCESS; } - # define HAVE_GET_STACK_BASE - - /* This is always called from the main thread. The above */ - /* implementation of GC_get_stack_base() requires the latter to be */ - /* first called from GC_get_main_stack_base() (to cache the proper */ - /* ss_sp value). */ - ptr_t GC_get_main_stack_base(void) - { - struct GC_stack_base sb; - GC_get_stack_base(&sb); - return (ptr_t)sb.mem_base; - } #endif /* GC_SOLARIS_THREADS */ #ifndef HAVE_GET_STACK_BASE @@ -1424,6 +1395,18 @@ GC_INNER word GC_page_size = 0; } #endif /* !HAVE_GET_STACK_BASE */ +#ifndef GET_MAIN_STACKBASE_SPECIAL + /* This is always called from the main thread. Default implementation. */ + ptr_t GC_get_main_stack_base(void) + { + struct GC_stack_base sb; + if (GC_get_stack_base(&sb) != GC_SUCCESS) + ABORT("GC_get_stack_base failed"); + GC_ASSERT((void *)&sb HOTTER_THAN sb.mem_base); + return (ptr_t)sb.mem_base; + } +#endif /* !GET_MAIN_STACKBASE_SPECIAL */ + /* * Register static data segment(s) as roots. * If more data segments are added later then they need to be registered -- cgit v1.2.1 From 94d29b350098c3dfe82b8f9513583b30d50b8352 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 23 May 2011 09:51:11 +0000 Subject: 2011-05-23 Ivan Maidanski * os_dep.c (GC_read_dirty): Add debug logging if DEBUG_DIRTY_BITS (for PROC_VDB only); print errors via GC_err_printf; rename "ps" and "np" local variables to npages and pagesize, respectively; remove "current_addr" local variable. * os_dep.c: Refprmat comments. --HG-- branch : bdwgc --- ChangeLog | 8 ++ os_dep.c | 250 ++++++++++++++++++++++++++++++-------------------------------- 2 files changed, 127 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66b3e5f0..6035f983 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-23 Ivan Maidanski + + * os_dep.c (GC_read_dirty): Add debug logging if DEBUG_DIRTY_BITS + (for PROC_VDB only); print errors via GC_err_printf; rename "ps" + and "np" local variables to npages and pagesize, respectively; + remove "current_addr" local variable. + * os_dep.c: Refprmat comments. + 2011-05-22 Ivan Maidanski * os_dep.c (GC_get_main_stack_base): Convert to GC_get_stack_base diff --git a/os_dep.c b/os_dep.c index 7769274e..c65d93a6 100644 --- a/os_dep.c +++ b/os_dep.c @@ -19,10 +19,10 @@ #if defined(LINUX) && !defined(POWERPC) # include # if (LINUX_VERSION_CODE <= 0x10400) - /* Ugly hack to get struct sigcontext_struct definition. Required */ - /* for some early 1.3.X releases. Will hopefully go away soon. */ - /* in some later Linux releases, asm/sigcontext.h may have to */ - /* be included instead. */ + /* Ugly hack to get struct sigcontext_struct definition. Required */ + /* for some early 1.3.X releases. Will hopefully go away soon. */ + /* in some later Linux releases, asm/sigcontext.h may have to */ + /* be included instead. */ # define __KERNEL__ # include # undef __KERNEL__ @@ -34,8 +34,8 @@ # include # if 2 <= __GLIBC__ # if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__ - /* glibc 2.1 no longer has sigcontext.h. But signal.h */ - /* has the right declaration for glibc 2.1. */ + /* glibc 2.1 no longer has sigcontext.h. But signal.h */ + /* has the right declaration for glibc 2.1. */ # include # endif /* 0 == __GLIBC_MINOR__ */ # else /* not 2 <= __GLIBC__ */ @@ -136,7 +136,7 @@ STATIC GC_bool GC_pages_executable = FALSE; #endif #define IGNORE_PAGES_EXECUTABLE 1 - /* Undefined on GC_pages_executable real use. */ + /* Undefined on GC_pages_executable real use. */ #if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \ || !defined(SMALL_CONFIG)) @@ -144,9 +144,9 @@ #endif #ifdef NEED_PROC_MAPS -/* We need to parse /proc/self/maps, either to find dynamic libraries, */ -/* and/or to find the register backing store base (IA64). Do it once */ -/* here. */ +/* We need to parse /proc/self/maps, either to find dynamic libraries, */ +/* and/or to find the register backing store base (IA64). Do it once */ +/* here. */ #define READ read @@ -197,12 +197,10 @@ STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count) } #endif /* THREADS */ -/* - * Copy the contents of /proc/self/maps to a buffer in our address space. - * Return the address of the buffer, or zero on failure. - * This code could be simplified if we could determine its size - * ahead of time. - */ +/* Copy the contents of /proc/self/maps to a buffer in our address */ +/* space. Return the address of the buffer, or zero on failure. */ +/* This code could be simplified if we could determine its size ahead */ +/* of time. */ GC_INNER char * GC_get_maps(void) { int f; @@ -243,7 +241,7 @@ GC_INNER char * GC_get_maps(void) /* thus can't use stdio. */ do { while (maps_size >= maps_buf_sz) { - /* Grow only by powers of 2, since we leak "too small" buffers. */ + /* Grow only by powers of 2, since we leak "too small" buffers.*/ while (maps_size >= maps_buf_sz) maps_buf_sz *= 2; maps_buf = GC_scratch_alloc(maps_buf_sz); # ifdef THREADS @@ -283,10 +281,10 @@ GC_INNER char * GC_get_maps(void) } # endif } while (maps_size >= maps_buf_sz || maps_size < old_maps_size); - /* In the single-threaded case, the second clause is false. */ + /* In the single-threaded case, the second clause is false. */ maps_buf[maps_size] = '\0'; - /* Apply fn to result. */ + /* Apply fn to result. */ return maps_buf; } @@ -304,12 +302,10 @@ GC_INNER char * GC_get_maps(void) * anywhere, which is safer anyway. */ -/* - * Assign various fields of the first line in buf_ptr to *start, *end, - * *prot, *maj_dev and *mapping_name. Mapping_name may be NULL. - * *prot and *mapping_name are assigned pointers into the original - * buffer. - */ +/* Assign various fields of the first line in buf_ptr to (*start), */ +/* (*end), (*prot), (*maj_dev) and (*mapping_name). mapping_name may */ +/* be NULL. (*prot) and (*mapping_name) are assigned pointers into the */ +/* original buffer. */ GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, char **prot, unsigned int *maj_dev, char **mapping_name) @@ -572,7 +568,7 @@ GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp) } # ifdef THREADS - /* Due to the siglongjump we need to manually unmask SIGPROF. */ + /* Due to the siglongjump we need to manually unmask SIGPROF. */ __syscall(SYS_sigprocmask, SIG_UNBLOCK, sigmask(SIGPROF)); # endif @@ -864,8 +860,8 @@ GC_INNER word GC_page_size = 0; (void) sigemptyset(&act.sa_mask); # ifdef GC_IRIX_THREADS - /* Older versions have a bug related to retrieving and */ - /* and setting a handler at the same time. */ + /* Older versions have a bug related to retrieving and */ + /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); # else @@ -873,9 +869,9 @@ GC_INNER word GC_page_size = 0; # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ || defined(HPUX) || defined(HURD) || defined(NETBSD) \ || defined(FREEBSD) - /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ - /* Pthreads doesn't exist under Irix 5.x, so we */ - /* don't have to worry in the threads case. */ + /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ + /* Pthreads doesn't exist under Irix 5.x, so we */ + /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); # endif # endif /* GC_IRIX_THREADS */ @@ -901,8 +897,8 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_setup_temporary_fault_handler(void) { - /* Handler is process-wide, so this should only happen in */ - /* one thread at a time. */ + /* Handler is process-wide, so this should only happen in */ + /* one thread at a time. */ GC_ASSERT(I_HOLD_LOCK()); GC_set_and_save_fault_handler(GC_fault_handler); } @@ -1407,14 +1403,10 @@ GC_INNER word GC_page_size = 0; } #endif /* !GET_MAIN_STACKBASE_SPECIAL */ -/* - * Register static data segment(s) as roots. - * If more data segments are added later then they need to be registered - * add that point (as we do with SunOS dynamic loading), - * or GC_mark_roots needs to check for them (as we do with PCR). - * Called with allocator lock held. - */ - +/* Register static data segment(s) as roots. If more data segments are */ +/* added later then they need to be registered at that point (as we do */ +/* with SunOS dynamic loading), or GC_mark_roots needs to check for */ +/* them (as we do with PCR). Called with allocator lock held. */ # ifdef OS2 void GC_register_data_segments(void) @@ -1701,7 +1693,7 @@ void GC_register_data_segments(void) /* the malloc heap with HeapWalk on the default heap. But that */ /* apparently works only for NT-based Windows. */ - STATIC size_t GC_max_root_size = 100000; /* Appr. largest root size. */ + STATIC size_t GC_max_root_size = 100000; /* Appr. largest root size. */ # ifndef CYGWIN32 /* In the long run, a better data structure would also be nice ... */ @@ -2055,7 +2047,7 @@ STATIC ptr_t GC_unix_mmap_get_mem(word bytes) /* usable by arbitrary C code, since one-past-end pointers */ /* don't work, so we discard it and try again. */ munmap(result, (size_t)(-GC_page_size) - (size_t)result); - /* Leave last page mapped, so we can't repeat. */ + /* Leave last page mapped, so we can't repeat. */ return GC_unix_mmap_get_mem(bytes); } # else @@ -2719,23 +2711,20 @@ STATIC void GC_default_push_other_roots(void) pages = gww_buf; count = GC_GWW_BUF_LEN; - /* - * GetWriteWatch is documented as returning non-zero when it fails, - * but the documentation doesn't explicitly say why it would fail or - * what its behaviour will be if it fails. - * It does appear to fail, at least on recent W2K instances, if - * the underlying memory was not allocated with the appropriate - * flag. This is common if GC_enable_incremental is called - * shortly after GC initialization. To avoid modifying the - * interface, we silently work around such a failure, it only - * affects the initial (small) heap allocation. - * If there are more dirty - * pages than will fit in the buffer, this is not treated as a - * failure; we must check the page count in the loop condition. - * Since each partial call will reset the status of some - * pages, this should eventually terminate even in the overflow - * case. - */ + /* GetWriteWatch is documented as returning non-zero when it */ + /* fails, but the documentation doesn't explicitly say why it */ + /* would fail or what its behaviour will be if it fails. */ + /* It does appear to fail, at least on recent W2K instances, if */ + /* the underlying memory was not allocated with the appropriate */ + /* flag. This is common if GC_enable_incremental is called */ + /* shortly after GC initialization. To avoid modifying the */ + /* interface, we silently work around such a failure, it only */ + /* affects the initial (small) heap allocation. If there are */ + /* more dirty pages than will fit in the buffer, this is not */ + /* treated as a failure; we must check the page count in the */ + /* loop condition. Since each partial call will reset the */ + /* status of some pages, this should eventually terminate even */ + /* in the overflow case. */ if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET, GC_heap_sects[i].hs_start, GC_heap_sects[i].hs_bytes, @@ -2759,7 +2748,7 @@ STATIC void GC_default_push_other_roots(void) set_pht_entry_from_index(GC_grungy_pages, hash); } count = 1; /* Done with this section. */ - } else /* succeeded */{ + } else /* succeeded */ { pages_end = pages + count; while (pages != pages_end) { struct hblk * h = (struct hblk *) *pages++; @@ -2770,9 +2759,9 @@ STATIC void GC_default_push_other_roots(void) } } } while (count == GC_GWW_BUF_LEN); - /* FIXME: It's unclear from Microsoft's documentation if this loop */ - /* is useful. We suspect the call just fails if the buffer fills */ - /* up. But that should still be handled correctly. */ + /* FIXME: It's unclear from Microsoft's documentation if this loop */ + /* is useful. We suspect the call just fails if the buffer fills */ + /* up. But that should still be handled correctly. */ } GC_or_pages(GC_written_pages, GC_grungy_pages); @@ -2807,12 +2796,10 @@ STATIC void GC_default_push_other_roots(void) return(TRUE); } - /* - * The following two routines are typically less crucial. They matter - * most with large dynamic libraries, or if we can't accurately identify - * stacks, e.g. under Solaris 2.X. Otherwise the following default - * versions are adequate. - */ + /* The following two routines are typically less crucial. */ + /* They matter most with large dynamic libraries, or if we can't */ + /* accurately identify stacks, e.g. under Solaris 2.X. Otherwise the */ + /* following default versions are adequate. */ # ifdef CHECKSUMS /* Could any valid GC heap pointer ever have been written to this page? */ /*ARGSUSED*/ @@ -3221,14 +3208,12 @@ STATIC void GC_default_push_other_roots(void) } #endif /* !DARWIN */ -/* - * We hold the allocation lock. We expect block h to be written - * shortly. Ensure that all pages containing any part of the n hblks - * starting at h are no longer protected. If is_ptrfree is false, - * also ensure that they will subsequently appear to be dirty. - * Not allowed to call GC_printf (and the friends) here, see Win32 - * GC_stop_world() for the information. - */ +/* We hold the allocation lock. We expect block h to be written */ +/* shortly. Ensure that all pages containing any part of the n hblks */ +/* starting at h are no longer protected. If is_ptrfree is false, also */ +/* ensure that they will subsequently appear to be dirty. Not allowed */ +/* to call GC_printf (and the friends) here, see Win32 GC_stop_world() */ +/* for the information. */ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree) { @@ -3589,16 +3574,13 @@ ssize_t read(int fd, void *buf, size_t nbyte) #endif /* MPROTECT_VDB */ #ifdef PROC_VDB -/* - * See DEFAULT_VDB for interface descriptions. - */ +/* See DEFAULT_VDB for interface descriptions. */ -/* - * This implementation assumes a Solaris 2.X like /proc pseudo-file-system - * from which we can read page modified bits. This facility is far from - * optimal (e.g. we would like to get the info for only some of the - * address space), but it avoids intercepting system calls. - */ +/* This implementation assumes a Solaris 2.X like /proc */ +/* pseudo-file-system from which we can read page modified bits. This */ +/* facility is far from optimal (e.g. we would like to get the info for */ +/* only some of the address space), but it avoids intercepting system */ +/* calls. */ # include # include @@ -3644,24 +3626,22 @@ GC_INNER void GC_dirty_init(void) GC_INNER void GC_read_dirty(void) { - unsigned long ps, np; int nmaps; - ptr_t vaddr; + unsigned long npages; + unsigned pagesize; + ptr_t vaddr, limit; struct prasmap * map; char * bufp; - ptr_t current_addr, limit; int i; - BZERO(GC_grungy_pages, (sizeof GC_grungy_pages)); - + BZERO(GC_grungy_pages, sizeof(GC_grungy_pages)); bufp = GC_proc_buf; if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { /* Retry with larger buffer. */ word new_size = 2 * GC_proc_buf_size; char *new_buf; - if (GC_print_stats) - GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n", + GC_err_printf("/proc read failed: GC_proc_buf_size = %lu\n", (unsigned long)GC_proc_buf_size); new_buf = GC_scratch_alloc(new_size); @@ -3680,33 +3660,43 @@ GC_INNER void GC_read_dirty(void) /* Copy dirty bits into GC_grungy_pages */ nmaps = ((struct prpageheader *)bufp) -> pr_nmap; - /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n", - nmaps, PG_REFERENCED, PG_MODIFIED); */ - bufp = bufp + sizeof(struct prpageheader); +# ifdef DEBUG_DIRTY_BITS + GC_log_printf("Proc VDB read: pr_nmap= %u, pr_npage= %lu\n", + nmaps, ((struct prpageheader *)bufp)->pr_npage); + +# endif + bufp += sizeof(struct prpageheader); for (i = 0; i < nmaps; i++) { map = (struct prasmap *)bufp; vaddr = (ptr_t)(map -> pr_vaddr); - ps = map -> pr_pagesize; - np = map -> pr_npage; - /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */ - limit = vaddr + ps * np; - bufp += sizeof (struct prasmap); - for (current_addr = vaddr; - current_addr < limit; current_addr += ps) { - if ((*bufp++) & PG_MODIFIED) { - register struct hblk * h = (struct hblk *) current_addr; + npages = map -> pr_npage; + pagesize = map -> pr_pagesize; +# ifdef DEBUG_DIRTY_BITS + GC_log_printf( + "pr_vaddr= %p, npage= %lu, mflags= 0x%x, pagesize= 0x%x\n", + vaddr, npages, map->pr_mflags, pagesize); +# endif - while ((ptr_t)h < current_addr + ps) { + bufp += sizeof(struct prasmap); + limit = vaddr + pagesize * npages; + for (; vaddr < limit; vaddr += pagesize) { + if ((*bufp++) & PG_MODIFIED) { + register struct hblk * h; + ptr_t next_vaddr = vaddr + pagesize; +# ifdef DEBUG_DIRTY_BITS + GC_log_printf("dirty page at: %p\n", vaddr); +# endif + for (h = (struct hblk *)vaddr; (ptr_t)h < next_vaddr; h++) { register word index = PHT_HASH(h); - set_pht_entry_from_index(GC_grungy_pages, index); - h++; } } } - bufp += sizeof(long) - 1; - bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1)); + bufp = (char *)(((word)bufp + (sizeof(long)-1)) & ~(sizeof(long)-1)); } +# ifdef DEBUG_DIRTY_BITS + GC_log_printf("Proc VDB read done.\n"); +# endif /* Update GC_written_pages. */ GC_or_pages(GC_written_pages, GC_grungy_pages); @@ -3965,9 +3955,9 @@ typedef enum { STATIC void *GC_mprotect_thread(void *arg) { mach_msg_return_t r; - /* These two structures contain some private kernel data. We don't need to - access any of it so we don't bother defining a proper struct. The - correct definitions are in the xnu source code. */ + /* These two structures contain some private kernel data. We don't */ + /* need to access any of it so we don't bother defining a proper */ + /* struct. The correct definitions are in the xnu source code. */ struct { mach_msg_header_t head; char data[256]; @@ -4154,9 +4144,9 @@ GC_INNER void GC_dirty_init(void) # endif /* BROKEN_EXCEPTION_HANDLING */ } -/* The source code for Apple's GDB was used as a reference for the exception - forwarding code. This code is similar to be GDB code only because there is - only one way to do it. */ +/* The source code for Apple's GDB was used as a reference for the */ +/* exception forwarding code. This code is similar to be GDB code only */ +/* because there is only one way to do it. */ STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task, exception_type_t exception, exception_data_t data, @@ -4275,8 +4265,8 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, r = thread_get_state(thread, flavor, (natural_t*)&exc_state, &exc_state_count); if(r != KERN_SUCCESS) { - /* The thread is supposed to be suspended while the exception handler - is called. This shouldn't fail. */ + /* The thread is supposed to be suspended while the exception */ + /* handler is called. This shouldn't fail. */ # ifdef BROKEN_EXCEPTION_HANDLING GC_err_printf("thread_get_state failed in catch_exception_raise\n"); return KERN_SUCCESS; @@ -4288,11 +4278,11 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, /* This is the address that caused the fault */ addr = (char*) exc_state.DARWIN_EXC_STATE_DAR; if (HDR(addr) == 0) { - /* Ugh... just like the SIGBUS problem above, it seems we get a bogus - KERN_PROTECTION_FAILURE every once and a while. We wait till we get - a bunch in a row before doing anything about it. If a "real" fault - ever occurs it'll just keep faulting over and over and we'll hit - the limit pretty quickly. */ + /* Ugh... just like the SIGBUS problem above, it seems we get */ + /* a bogus KERN_PROTECTION_FAILURE every once and a while. We wait */ + /* till we get a bunch in a row before doing anything about it. */ + /* If a "real" fault ever occurs it'll just keep faulting over and */ + /* over and we'll hit the limit pretty quickly. */ # ifdef BROKEN_EXCEPTION_HANDLING static char *last_fault; static int last_fault_count; @@ -4309,9 +4299,9 @@ catch_exception_raise(mach_port_t exception_port, mach_port_t thread, GC_err_printf( "Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n", addr); - /* Can't pass it along to the signal handler because that is - ignoring SIGBUS signals. We also shouldn't call ABORT here as - signals don't always work too well from the exception handler. */ + /* Can't pass it along to the signal handler because that is */ + /* ignoring SIGBUS signals. We also shouldn't call ABORT here as */ + /* signals don't always work too well from the exception handler. */ exit(EXIT_FAILURE); # else /* BROKEN_EXCEPTION_HANDLING */ /* Pass it along to the next exception handler @@ -4388,10 +4378,8 @@ GC_API int GC_CALL GC_get_pages_executable(void) # endif } -/* - * Call stack save code for debugging. - * Should probably be in mach_dep.c, but that requires reorganization. - */ +/* Call stack save code for debugging. Should probably be in */ +/* mach_dep.c, but that requires reorganization. */ /* I suspect the following works for most X86 *nix variants, so */ /* long as the frame pointer is explicitly stored. In the case of gcc, */ -- cgit v1.2.1 From f5fef6ddeba6bd5e6e11697dffe9a16365e5df32 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 23 May 2011 13:42:56 +0000 Subject: 2011-05-23 Ivan Maidanski * include/private/gc_priv.h (GC_ASSERT): Use "%d" (instead of %ld) for line number printing. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ include/private/gc_priv.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6035f983..6ac4b618 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-23 Ivan Maidanski + + * include/private/gc_priv.h (GC_ASSERT): Use "%d" (instead of %ld) + for line number printing. + 2011-05-23 Ivan Maidanski * os_dep.c (GC_read_dirty): Add debug logging if DEBUG_DIRTY_BITS diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 71ef9ff5..8ff8c0fc 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -2020,8 +2020,8 @@ GC_EXTERN signed_word GC_bytes_found; #ifdef GC_ASSERTIONS # define GC_ASSERT(expr) \ if (!(expr)) { \ - GC_err_printf("Assertion failure: %s:%ld\n", \ - __FILE__, (unsigned long)__LINE__); \ + GC_err_printf("Assertion failure: %s:%d\n", \ + __FILE__, __LINE__); \ ABORT("assertion failure"); \ } #else -- cgit v1.2.1 From dfab2f1df7be126f50b61bcf60d2b2011efe5fa0 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 23 May 2011 15:18:05 +0000 Subject: 2011-05-23 Ivan Maidanski * mark.c (GC_dirty): Add prototype (only if MANUAL_VDB). * stubborn.c (GC_dirty): Ditto. * include/private/gcconfig.h (GWW_VDB, MPROTECT_VDB, PCR_VDB, PROC_VDB): Undefine if MANUAL_VDB. * include/private/gcconfig.h (DEFAULT_VDB): Don't define if MANUAL_VDB. * os_dep.c (async_set_pht_entry_from_index): Define for MANUAL_VDB. * os_dep.c (GC_read_dirty): Set GC_dirty_maintained only if success; if ioctl() failed then just print warning instead of aborting. --HG-- branch : bdwgc --- ChangeLog | 14 ++++++++++++++ include/private/gcconfig.h | 8 ++++++-- mark.c | 8 ++++++-- os_dep.c | 10 ++++++++-- stubborn.c | 2 ++ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6ac4b618..c49fc468 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-05-23 Ivan Maidanski + + * mark.c (GC_dirty): Add prototype (only if MANUAL_VDB). + * stubborn.c (GC_dirty): Ditto. + * include/private/gcconfig.h (GWW_VDB, MPROTECT_VDB, PCR_VDB, + PROC_VDB): Undefine if MANUAL_VDB. + * include/private/gcconfig.h (DEFAULT_VDB): Don't define if + MANUAL_VDB. + * os_dep.c (async_set_pht_entry_from_index): Define for + MANUAL_VDB. + * os_dep.c (GC_read_dirty): Set GC_dirty_maintained only if + success; if ioctl() failed then just print warning instead of + aborting. + 2011-05-23 Ivan Maidanski * include/private/gc_priv.h (GC_ASSERT): Use "%d" (instead of %ld) diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 5cd3672d..bd99e6d0 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2380,11 +2380,14 @@ # define GC_DISABLE_INCREMENTAL #endif -#ifdef GC_DISABLE_INCREMENTAL +#if defined(GC_DISABLE_INCREMENTAL) || defined(MANUAL_VDB) # undef GWW_VDB # undef MPROTECT_VDB # undef PCR_VDB # undef PROC_VDB +#endif + +#ifdef GC_DISABLE_INCREMENTAL # undef CHECKSUMS #endif @@ -2413,7 +2416,8 @@ #endif #if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ - && !defined(GWW_VDB) && !defined(GC_DISABLE_INCREMENTAL) + && !defined(GWW_VDB) && !defined(MANUAL_VDB) \ + && !defined(GC_DISABLE_INCREMENTAL) # define DEFAULT_VDB #endif diff --git a/mark.c b/mark.c index aff1e2fe..65811084 100644 --- a/mark.c +++ b/mark.c @@ -1396,6 +1396,10 @@ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, return mark_stack_ptr; } +#if defined(MANUAL_VDB) && defined(THREADS) + void GC_dirty(ptr_t p); +#endif + /* Mark and push (i.e. gray) a single object p onto the main */ /* mark stack. Consider p to be valid if it is an interior */ /* pointer. */ @@ -1431,8 +1435,8 @@ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, } # if defined(MANUAL_VDB) && defined(THREADS) /* Pointer is on the stack. We may have dirtied the object */ - /* it points to, but not yet have called GC_dirty(); */ - GC_dirty(p); /* Implicitly affects entire object. */ + /* it points to, but not yet have called GC_dirty(); */ + GC_dirty(p); /* Implicitly affects entire object. */ # endif PUSH_CONTENTS_HDR(r, GC_mark_stack_top, GC_mark_stack_limit, source, mark_and_push_exit, hhdr, FALSE); diff --git a/os_dep.c b/os_dep.c index c65d93a6..21613d9a 100644 --- a/os_dep.c +++ b/os_dep.c @@ -2850,6 +2850,9 @@ STATIC void GC_default_push_other_roots(void) return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index)); } +# define async_set_pht_entry_from_index(db, index) \ + set_pht_entry_from_index(db, index) /* for now */ + /* Mark the page containing p as dirty. Logically, this dirties the */ /* entire object. */ void GC_dirty(ptr_t p) @@ -3600,7 +3603,6 @@ GC_INNER void GC_dirty_init(void) int fd; char buf[30]; - GC_dirty_maintained = TRUE; if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { memset(GC_written_pages, 0xff, sizeof(page_hash_table)); if (GC_print_stats == VERBOSE) @@ -3608,6 +3610,7 @@ GC_INNER void GC_dirty_init(void) (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc)); } + sprintf(buf, "/proc/%ld", (long)getpid()); fd = open(buf, O_RDONLY); if (fd < 0) { @@ -3617,8 +3620,11 @@ GC_INNER void GC_dirty_init(void) close(fd); syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC); if (GC_proc_fd < 0) { - ABORT("/proc ioctl failed"); + WARN("/proc ioctl(PIOCOPENPD) failed", 0); + return; } + + GC_dirty_maintained = TRUE; GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size); } diff --git a/stubborn.c b/stubborn.c index a297dd51..b1991f13 100644 --- a/stubborn.c +++ b/stubborn.c @@ -22,6 +22,8 @@ /* written, but not yet GC_dirty()ed objects must be referenced */ /* by a stack. */ + void GC_dirty(ptr_t p); + GC_API void * GC_CALL GC_malloc_stubborn(size_t lb) { return(GC_malloc(lb)); -- cgit v1.2.1 From b331a8a9fe4ba4c0a395a4b9604987033181e195 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 23 May 2011 21:19:19 +0000 Subject: 2011-05-23 Ivan Maidanski * tests/threadkey_test.c (SKIP_THREADKEY_TEST): Skip the test if defined; explicitly define for some targets. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++-- tests/threadkey_test.c | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) mode change 100755 => 100644 tests/threadkey_test.c diff --git a/ChangeLog b/ChangeLog index c49fc468..6ff981ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,14 @@ +2011-05-23 Ivan Maidanski + + * tests/threadkey_test.c (SKIP_THREADKEY_TEST): Skip the test if + defined; explicitly define for some targets. + 2011-05-23 Ivan Maidanski * mark.c (GC_dirty): Add prototype (only if MANUAL_VDB). * stubborn.c (GC_dirty): Ditto. * include/private/gcconfig.h (GWW_VDB, MPROTECT_VDB, PCR_VDB, - PROC_VDB): Undefine if MANUAL_VDB. + PROC_VDB): Undefine if MANUAL_VDB. * include/private/gcconfig.h (DEFAULT_VDB): Don't define if MANUAL_VDB. * os_dep.c (async_set_pht_entry_from_index): Define for @@ -23,7 +28,7 @@ (for PROC_VDB only); print errors via GC_err_printf; rename "ps" and "np" local variables to npages and pagesize, respectively; remove "current_addr" local variable. - * os_dep.c: Refprmat comments. + * os_dep.c: Reformat comments. 2011-05-22 Ivan Maidanski diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c old mode 100755 new mode 100644 index 1ea761d9..bf3f51ea --- a/tests/threadkey_test.c +++ b/tests/threadkey_test.c @@ -7,6 +7,23 @@ #include "gc.h" +#if (!defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ + || defined(__native_client__)) && !defined(SKIP_THREADKEY_TEST) + /* FIXME: Skip this test on Solaris for now. The test may fail on */ + /* other targets as well. Currently, tested only on Linux, Cygwin */ + /* and Darwin. */ +# define SKIP_THREADKEY_TEST +#endif + +#ifdef SKIP_THREADKEY_TEST + +int main (void) +{ + return 0; +} + +#else + #include pthread_key_t key; @@ -68,3 +85,5 @@ int main (void) } return 0; } + +#endif -- cgit v1.2.1 From 59e8ade2b928cf23b80f6015c793eddd37df3adf Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 26 May 2011 11:03:55 +0000 Subject: Adjust file permissions --HG-- branch : bdwgc --- win32_threads.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 win32_threads.c diff --git a/win32_threads.c b/win32_threads.c old mode 100755 new mode 100644 -- cgit v1.2.1 From 45be3421b34137a1533d8de4e6b9fbddda5e6689 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 30 May 2011 13:37:49 +0000 Subject: 2011-05-30 Ivan Maidanski * configure.ac (SOLARIS25_PROC_VDB_BUG_FIXED): Don't define for Solaris/x86 2.10+. * configure: Regenerate. --HG-- branch : bdwgc --- ChangeLog | 6 ++++++ configure | 3 ++- configure.ac | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6ff981ad..eaa86932 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-30 Ivan Maidanski + + * configure.ac (SOLARIS25_PROC_VDB_BUG_FIXED): Don't define for + Solaris/x86 2.10+. + * configure: Regenerate. + 2011-05-23 Ivan Maidanski * tests/threadkey_test.c (SKIP_THREADKEY_TEST): Skip the test if diff --git a/configure b/configure index 3681b580..572544aa 100755 --- a/configure +++ b/configure @@ -5556,7 +5556,8 @@ $as_echo "$as_me: WARNING: OpenBSD/Alpha without dlopen(). Shared library suppor alpha*-*-linux*) machdep="mach_dep.lo" ;; - i?86-*-solaris2.[89] | i?86-*-solaris2.1?) + i?86-*-solaris2.[89]) + # PROC_VDB appears to work in 2.8 and 2.9 but not in 2.10+ (for now). $as_echo "#define SOLARIS25_PROC_VDB_BUG_FIXED 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index f39e35dc..ca2813b5 100644 --- a/configure.ac +++ b/configure.ac @@ -395,7 +395,8 @@ case "$host" in alpha*-*-linux*) machdep="mach_dep.lo" ;; - i?86-*-solaris2.[[89]] | i?86-*-solaris2.1?) + i?86-*-solaris2.[[89]]) + # PROC_VDB appears to work in 2.8 and 2.9 but not in 2.10+ (for now). AC_DEFINE([SOLARIS25_PROC_VDB_BUG_FIXED], 1, [See the comment in gcconfig.h.]) ;; -- cgit v1.2.1 From 9cbf7e1173b9b158a92c13b6fe78b53130db1e73 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 30 May 2011 17:26:59 +0000 Subject: 2011-05-30 Ivan Maidanski * doc/README.solaris2: Add note. --HG-- branch : bdwgc --- ChangeLog | 4 ++++ doc/README.solaris2 | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index eaa86932..c0cc70f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-30 Ivan Maidanski + + * doc/README.solaris2: Add note. + 2011-05-30 Ivan Maidanski * configure.ac (SOLARIS25_PROC_VDB_BUG_FIXED): Don't define for diff --git a/doc/README.solaris2 b/doc/README.solaris2 index d5716e4f..d46fe262 100644 --- a/doc/README.solaris2 +++ b/doc/README.solaris2 @@ -17,6 +17,10 @@ Nonetheless, under Solaris2, the collector now allocates memory using mmap by default. (It defines USE_MMAP in gcconfig.h.) You may want to reverse this decisions if you use -DREDIRECT_MALLOC=... +Note: +Before you run "make check", you need to set your LD_LIBRARY_PATH correctly +(eg., to "/usr/local/lib") so that tests can find the shared library +libgcc_s.so.1. Alternatively, you can configure with --disable-shared. SOLARIS THREADS: -- cgit v1.2.1 From ad6ce46c3b318db501ec171a3a641495a4c63c77 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 31 May 2011 08:41:21 +0000 Subject: 2011-05-31 Ivan Maidanski * tests/test.c (check_heap_stats): Adjust printf format specifier for max_heap_sz; cast max_heap_sz accordingly. --HG-- branch : bdwgc --- ChangeLog | 5 +++++ tests/test.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0cc70f0..4eb5685c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-31 Ivan Maidanski + + * tests/test.c (check_heap_stats): Adjust printf format specifier + for max_heap_sz; cast max_heap_sz accordingly. + 2011-05-30 Ivan Maidanski * doc/README.solaris2: Add note. diff --git a/tests/test.c b/tests/test.c index e7826c2b..153d9775 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1345,9 +1345,9 @@ void check_heap_stats(void) } if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz) { GC_printf("Unexpected heap growth - collector may be broken" - " (heapsize: %lu, expected: %u)\n", + " (heapsize: %lu, expected: %lu)\n", (unsigned long)(GC_get_heap_size() + GC_get_unmapped_bytes()), - max_heap_sz); + (unsigned long)max_heap_sz); FAIL; } # ifdef THREADS -- cgit v1.2.1 From fd7cbb2a0f099fba2f2683694630f4e8e41b5d14 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 31 May 2011 09:09:34 +0000 Subject: 2011-05-31 Ivan Maidanski * win32_threads.c (GC_unregister_my_thread): Use KNOWN_FINISHED() instead of FINISHED macro. * tests/test.c (check_heap_stats): Round up max_heap_sz value for Win32 (same as for USE_MMAP). --HG-- branch : bdwgc --- ChangeLog | 7 +++++++ tests/test.c | 2 +- win32_threads.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4eb5685c..b31e5ed3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-31 Ivan Maidanski + + * win32_threads.c (GC_unregister_my_thread): Use KNOWN_FINISHED() + instead of FINISHED macro. + * tests/test.c (check_heap_stats): Round up max_heap_sz value for + Win32 (same as for USE_MMAP). + 2011-05-31 Ivan Maidanski * tests/test.c (check_heap_stats): Adjust printf format specifier diff --git a/tests/test.c b/tests/test.c index 153d9775..c486714a 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1275,7 +1275,7 @@ void check_heap_stats(void) # endif # endif max_heap_sz *= n_tests; -# ifdef USE_MMAP +# if defined(USE_MMAP) || defined(MSWIN32) max_heap_sz = NUMBER_ROUND_UP(max_heap_sz, 4 * 1024 * 1024); # endif /* Garbage collect repeatedly so that all inaccessible objects */ diff --git a/win32_threads.c b/win32_threads.c index 68752fae..15b4b15c 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -776,7 +776,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) LOCK(); # if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS) me = GC_lookup_thread_inner(thread_id); - GC_ASSERT(!(me -> flags & FINISHED)); + GC_ASSERT(!KNOWN_FINISHED(me)); # endif # if defined(THREAD_LOCAL_ALLOC) GC_destroy_thread_local(&(me->tlfs)); -- cgit v1.2.1 From 2d55d6568ca2c338749ce7ed0b83a7ee2708f2dc Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 31 May 2011 09:53:36 +0000 Subject: 2011-05-31 Ivan Maidanski * misc.c (vsnprintf): Redirect to vsprintf() if NO_VSNPRINTF. --HG-- branch : bdwgc --- ChangeLog | 4 ++++ misc.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b31e5ed3..cbba2527 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-31 Ivan Maidanski + + * misc.c (vsnprintf): Redirect to vsprintf() if NO_VSNPRINTF. + 2011-05-31 Ivan Maidanski * win32_threads.c (GC_unregister_my_thread): Use KNOWN_FINISHED() diff --git a/misc.c b/misc.c index 50d55e04..428cffe6 100644 --- a/misc.c +++ b/misc.c @@ -1300,7 +1300,11 @@ GC_API void GC_CALL GC_enable_incremental(void) #endif /* !MSWIN32 && !OS2 && !MACOS */ #define BUFSZ 1024 -#ifdef _MSC_VER + +#ifdef NO_VSNPRINTF + /* In case this function is missing (eg., in DJGPP v2.0.3). */ +# define vsnprintf(buf, bufsz, format, args) vsprintf(buf, format, args) +#elif defined(_MSC_VER) # ifdef MSWINCE /* _vsnprintf is deprecated in WinCE */ # define vsnprintf StringCchVPrintfA -- cgit v1.2.1 From 46d6814140e3d18acbff92dbfc7fc1cb5e7bfaf8 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 31 May 2011 15:27:12 +0000 Subject: 2011-05-31 Ivan Maidanski * alloc.c (GC_add_current_malloc_heap, GC_build_back_graph, GC_traverse_back_graph): Move prototype to gc_priv.h. * checksums.c (GC_page_was_ever_dirty): Ditto. * dbg_mlc.c (GC_default_print_heap_obj_proc): Ditto. * dyn_load.c (GC_parse_map_entry, GC_get_maps, GC_segment_is_thread_stack, GC_roots_present, GC_is_heap_base, GC_get_next_stack): Ditto. * finalize.c (GC_reset_finalizer_nested, GC_check_finalizer_nested): Ditto. * gcj_mlc.c (GC_start_debugging, GC_store_debug_info): Ditto. * malloc.c (GC_extend_size_map, GC_text_mapping): Ditto. * mark_rts.c (GC_mark_thread_local_free_lists): Ditto. * misc.c (GC_register_main_static_data, GC_init_win32, GC_setpagesize, GC_init_linux_data_start, GC_set_and_save_fault_handler, GC_init_dyld, GC_init_netbsd_elf, GC_initialize_offsets, GC_bl_init, GC_do_blocking_inner, GC_bl_init_no_interiors): Ditto. * os_dep.c (GC_greatest_stack_base_below, GC_push_all_stacks): Ditto. * reclaim.c (GC_check_leaked): Ditto. * win32_threads.c (GC_gww_dirty_init): Ditto. * darwin_stop_world.c (GC_is_mach_marker, GC_mprotect_stop, GC_mprotect_resume): Move prototype to darwin_stop_world.h. * pthread_support.c (GC_FindTopOfStack): Ditto. * dyn_load.c (GC_cond_add_roots): Merge adjacent definitions. * mark.c (GC_page_was_ever_dirty): Remove (as already declared). * mark_rts.c (GC_roots_present): Change return type to void pointer (to match the prototype); return NULL instead of FALSE. * mark_rts.c (GC_add_roots_inner): Cast GC_roots_present() result. * os_dep.c (NEED_PROC_MAPS): Move definition to gcconfig.h. * os_dep.c (GC_write_fault_handler): Make STATIC. * os_dep.c (GC_set_write_fault_handler): New function (only if GC_WIN32_THREADS). * pthread_start.c (GC_start_rtn_prepare_thread, GC_thread_exit_proc): Move prototype to pthread_support.h. * pthread_support.c (GC_nacl_initialize_gc_thread, GC_nacl_shutdown_gc_thread, GC_unblock_gc_signals): Ditto. * pthread_support.c (GC_stop_init): Move prototype to pthread_stop_world.h. * thread_local_alloc.c (GC_check_tls_for): Reformat comment. * win32_threads.c (GC_write_fault_handler): Remove prototype. * win32_threads.c (GC_register_my_thread_inner): Call GC_set_write_fault_handler instead of SetUnhandledExceptionFilter (only if MPROTECT_VDB). * doc/README.win32: Add information about DMC. * include/private/gc_priv.h (GC_set_write_fault_handler): New prototype (only if GC_WIN32_THREADS and MPROTECT_VDB). --HG-- branch : bdwgc --- ChangeLog | 51 +++++++++++++++++ alloc.c | 12 ---- checksums.c | 2 - darwin_stop_world.c | 9 --- dbg_mlc.c | 2 - doc/README.win32 | 6 ++ dyn_load.c | 34 ++---------- finalize.c | 9 +-- gcj_mlc.c | 7 --- include/private/darwin_stop_world.h | 13 +++++ include/private/gc_priv.h | 104 +++++++++++++++++++++++++++++++++++ include/private/gcconfig.h | 5 ++ include/private/pthread_stop_world.h | 2 + include/private/pthread_support.h | 19 +++++-- malloc.c | 4 -- mark.c | 5 -- mark_rts.c | 10 +--- misc.c | 34 +----------- os_dep.c | 34 +++++------- pthread_start.c | 6 -- pthread_support.c | 17 ------ reclaim.c | 4 -- thread_local_alloc.c | 2 +- win32_threads.c | 25 +++------ 24 files changed, 229 insertions(+), 187 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbba2527..a67cde62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2011-05-31 Ivan Maidanski + + * alloc.c (GC_add_current_malloc_heap, GC_build_back_graph, + GC_traverse_back_graph): Move prototype to gc_priv.h. + * checksums.c (GC_page_was_ever_dirty): Ditto. + * dbg_mlc.c (GC_default_print_heap_obj_proc): Ditto. + * dyn_load.c (GC_parse_map_entry, GC_get_maps, + GC_segment_is_thread_stack, GC_roots_present, GC_is_heap_base, + GC_get_next_stack): Ditto. + * finalize.c (GC_reset_finalizer_nested, + GC_check_finalizer_nested): Ditto. + * gcj_mlc.c (GC_start_debugging, GC_store_debug_info): Ditto. + * malloc.c (GC_extend_size_map, GC_text_mapping): Ditto. + * mark_rts.c (GC_mark_thread_local_free_lists): Ditto. + * misc.c (GC_register_main_static_data, GC_init_win32, + GC_setpagesize, GC_init_linux_data_start, + GC_set_and_save_fault_handler, GC_init_dyld, GC_init_netbsd_elf, + GC_initialize_offsets, GC_bl_init, GC_do_blocking_inner, + GC_bl_init_no_interiors): Ditto. + * os_dep.c (GC_greatest_stack_base_below, GC_push_all_stacks): + Ditto. + * reclaim.c (GC_check_leaked): Ditto. + * win32_threads.c (GC_gww_dirty_init): Ditto. + * darwin_stop_world.c (GC_is_mach_marker, GC_mprotect_stop, + GC_mprotect_resume): Move prototype to darwin_stop_world.h. + * pthread_support.c (GC_FindTopOfStack): Ditto. + * dyn_load.c (GC_cond_add_roots): Merge adjacent definitions. + * mark.c (GC_page_was_ever_dirty): Remove (as already declared). + * mark_rts.c (GC_roots_present): Change return type to void + pointer (to match the prototype); return NULL instead of FALSE. + * mark_rts.c (GC_add_roots_inner): Cast GC_roots_present() result. + * os_dep.c (NEED_PROC_MAPS): Move definition to gcconfig.h. + * os_dep.c (GC_write_fault_handler): Make STATIC. + * os_dep.c (GC_set_write_fault_handler): New function (only if + GC_WIN32_THREADS). + * pthread_start.c (GC_start_rtn_prepare_thread, + GC_thread_exit_proc): Move prototype to pthread_support.h. + * pthread_support.c (GC_nacl_initialize_gc_thread, + GC_nacl_shutdown_gc_thread, GC_unblock_gc_signals): + Ditto. + * pthread_support.c (GC_stop_init): Move prototype to + pthread_stop_world.h. + * thread_local_alloc.c (GC_check_tls_for): Reformat comment. + * win32_threads.c (GC_write_fault_handler): Remove prototype. + * win32_threads.c (GC_register_my_thread_inner): Call + GC_set_write_fault_handler instead of SetUnhandledExceptionFilter + (only if MPROTECT_VDB). + * doc/README.win32: Add information about DMC. + * include/private/gc_priv.h (GC_set_write_fault_handler): New + prototype (only if GC_WIN32_THREADS and MPROTECT_VDB). + 2011-05-31 Ivan Maidanski * misc.c (vsnprintf): Redirect to vsprintf() if NO_VSNPRINTF. diff --git a/alloc.c b/alloc.c index 59253521..a41cb1db 100644 --- a/alloc.c +++ b/alloc.c @@ -557,14 +557,6 @@ GC_API int GC_CALL GC_collect_a_little(void) return(result); } -#if !defined(REDIRECT_MALLOC) && (defined(MSWIN32) || defined(MSWINCE)) - GC_INNER void GC_add_current_malloc_heap(void); -#endif - -#ifdef MAKE_BACK_GRAPH - GC_INNER void GC_build_back_graph(void); -#endif - #ifndef SMALL_CONFIG /* Variables for world-stop average delay time statistic computation. */ /* "divisor" is incremented every world-stop and halved when reached */ @@ -788,10 +780,6 @@ STATIC void GC_clear_fl_marks(ptr_t q) void GC_check_tls(void); #endif -#ifdef MAKE_BACK_GRAPH - GC_INNER void GC_traverse_back_graph(void); -#endif - /* Finish up a collection. Assumes mark bits are consistent, lock is */ /* held, but the world is otherwise running. */ STATIC void GC_finish_collection(void) diff --git a/checksums.c b/checksums.c index b93bcf98..3f2af938 100644 --- a/checksums.c +++ b/checksums.c @@ -97,8 +97,6 @@ int GC_n_changed_errors = 0; int GC_n_clean = 0; int GC_n_dirty = 0; -GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h); - STATIC void GC_update_check_page(struct hblk *h, int index) { page_entry *pe = GC_sums + index; diff --git a/darwin_stop_world.c b/darwin_stop_world.c index 4fcd7bac..f05dc685 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -352,10 +352,6 @@ GC_INNER void GC_push_all_stacks(void) STATIC int GC_mach_threads_count = 0; /* FIXME: it is better to implement GC_mach_threads as a hash set. */ -# ifdef PARALLEL_MARK - GC_INNER GC_bool GC_is_mach_marker(thread_act_t thread); -# endif - /* returns true if there's a thread in act_list that wasn't in old_list */ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, thread_act_array_t old_list, @@ -460,11 +456,6 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, #endif /* !GC_NO_THREADS_DISCOVERY */ -#ifdef MPROTECT_VDB - GC_INNER void GC_mprotect_stop(void); - GC_INNER void GC_mprotect_resume(void); -#endif - /* Caller holds allocation lock. */ GC_INNER void GC_stop_world(void) { diff --git a/dbg_mlc.c b/dbg_mlc.c index c2820602..6f51c030 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -22,8 +22,6 @@ #endif #include -GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); - #ifndef SHORT_DBG_HDRS /* Check whether object with base pointer p has debugging info. */ /* p is assumed to point to a legitimate object in our part */ diff --git a/doc/README.win32 b/doc/README.win32 index 44656fae..4a030cf3 100644 --- a/doc/README.win32 +++ b/doc/README.win32 @@ -107,6 +107,12 @@ version, change the line near the top. By default, it does not require the assembler. If you do have the assembler, I recommend removing the -DUSE_GENERIC. +Digital Mars compiler +--------------------- + +Same as MS Visual C++ but might require +-DAO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE option to compile with the +parallel marker enabled. Watcom compiler --------------- diff --git a/dyn_load.c b/dyn_load.c index 7cdceffb..563550db 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -239,11 +239,6 @@ GC_INNER void GC_register_dynamic_libraries(void) #define MAPS_BUF_SIZE (32*1024) -GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, - char **prot, unsigned int *maj_dev, - char **mapping_name); -GC_INNER char *GC_get_maps(void); /* from os_dep.c */ - /* Sort an array of HeapSects by start address. */ /* Unfortunately at least some versions of */ /* Linux qsort end up calling malloc by way of sysconf, and hence can't */ @@ -274,10 +269,6 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements) } } -#ifdef THREADS - GC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi); -#endif - STATIC word GC_register_map_entries(char *maps) { char *prot; @@ -725,10 +716,6 @@ GC_INNER void GC_register_dynamic_libraries(void) # define IRIX6 #endif -GC_INNER void * GC_roots_present(ptr_t); - /* The type is a lie, since the real type doesn't make sense here, */ - /* and we only test for NULL. */ - /* We use /proc to track down all parts of the address space that are */ /* mapped by the process, and throw out regions we know we shouldn't */ /* worry about. This may also work under other SVR4 variants. */ @@ -854,15 +841,9 @@ GC_INNER void GC_register_dynamic_libraries(void) /* We traverse the entire address space and register all segments */ /* that could possibly have been written to. */ - - GC_INNER GC_bool GC_is_heap_base(ptr_t p); - -# ifdef GC_WIN32_THREADS - GC_INNER void GC_get_next_stack(char *start, char * limit, char **lo, - char **hi); - - STATIC void GC_cond_add_roots(char *base, char * limit) - { + STATIC void GC_cond_add_roots(char *base, char * limit) + { +# ifdef GC_WIN32_THREADS char * curr_base = base; char * next_stack_lo; char * next_stack_hi; @@ -876,10 +857,7 @@ GC_INNER void GC_register_dynamic_libraries(void) curr_base = next_stack_hi; } if (curr_base < limit) GC_add_roots_inner(curr_base, limit, TRUE); - } -# else - STATIC void GC_cond_add_roots(char *base, char * limit) - { +# else char dummy; char * stack_top = (char *) ((word)(&dummy) & ~(GC_sysinfo.dwAllocationGranularity-1)); @@ -889,8 +867,8 @@ GC_INNER void GC_register_dynamic_libraries(void) return; } GC_add_roots_inner(base, limit, TRUE); - } -# endif +# endif + } #ifdef DYNAMIC_LOADING /* GC_register_main_static_data is not needed unless DYNAMIC_LOADING. */ diff --git a/finalize.c b/finalize.c index c10d8543..40c725a9 100644 --- a/finalize.c +++ b/finalize.c @@ -485,18 +485,13 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, } } } -#endif +#endif /* !NO_DEBUGGING */ #ifndef SMALL_CONFIG STATIC word GC_old_dl_entries = 0; /* for stats printing */ #endif -#ifdef THREADS - /* Defined in pthread_support.c or win32_threads.c. Called with the */ - /* allocation lock held. */ - GC_INNER void GC_reset_finalizer_nested(void); - GC_INNER unsigned char *GC_check_finalizer_nested(void); -#else +#ifndef THREADS /* Global variables to minimize the level of recursion when a client */ /* finalizer allocates memory. */ STATIC unsigned char GC_finalizer_nested = 0; diff --git a/gcj_mlc.c b/gcj_mlc.c index 3c54974c..3467a396 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -204,13 +204,6 @@ static void maybe_finalize(void) return((void *) op); } -GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */ - -/* Store debugging info into p. Return displaced pointer. */ -/* Assumes we don't hold allocation lock. */ -GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, - int linenum); - /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ /* with GC_gcj_debug_kind. */ GC_API void * GC_CALL GC_debug_gcj_malloc(size_t lb, diff --git a/include/private/darwin_stop_world.h b/include/private/darwin_stop_world.h index ee601144..399304ea 100644 --- a/include/private/darwin_stop_world.h +++ b/include/private/darwin_stop_world.h @@ -30,4 +30,17 @@ struct thread_stop_info { ptr_t stack_ptr; /* Valid only when thread is in a "blocked" state. */ }; +#ifndef DARWIN_DONT_PARSE_STACK + GC_INNER ptr_t GC_FindTopOfStack(unsigned long); +#endif + +#ifdef MPROTECT_VDB + GC_INNER void GC_mprotect_stop(void); + GC_INNER void GC_mprotect_resume(void); +#endif + +#if defined(PARALLEL_MARK) && !defined(GC_NO_THREADS_DISCOVERY) + GC_INNER GC_bool GC_is_mach_marker(thread_act_t); +#endif + #endif diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 8ff8c0fc..eb40fdcd 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1267,8 +1267,10 @@ GC_EXTERN word GC_page_size; #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) struct _SYSTEM_INFO; GC_EXTERN struct _SYSTEM_INFO GC_sysinfo; + GC_INNER GC_bool GC_is_heap_base(ptr_t p); #endif + GC_EXTERN word GC_black_list_spacing; /* Average number of bytes between blacklisted */ /* blocks. Approximate. */ @@ -1794,6 +1796,7 @@ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); /* Do not immediately deallocate object on */ /* free() in the leak-finding mode, just mark */ /* it as freed (and deallocate it after GC). */ + GC_INNER GC_bool GC_check_leaked(ptr_t base); /* from dbg_mlc.c */ #endif GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ @@ -2008,6 +2011,7 @@ GC_EXTERN signed_word GC_bytes_found; #ifdef THREAD_LOCAL_ALLOC GC_EXTERN GC_bool GC_world_stopped; /* defined in alloc.c */ + GC_INNER void GC_mark_thread_local_free_lists(void); #endif #ifdef GC_GCJ_SUPPORT @@ -2017,6 +2021,106 @@ GC_EXTERN signed_word GC_bytes_found; GC_EXTERN ptr_t * GC_gcjobjfreelist; #endif +#if defined(GWW_VDB) && defined(MPROTECT_VDB) + GC_INNER GC_bool GC_gww_dirty_init(void); + /* Defined in os_dep.c. Returns TRUE if GetWriteWatch is available. */ + /* May be called repeatedly. */ +#endif + +#if defined(CHECKSUMS) || defined(PROC_VDB) + GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h); + /* Could the page contain valid heap pointers? */ +#endif + +GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); + +GC_INNER void GC_extend_size_map(size_t); /* in misc.c */ + +GC_INNER void GC_setpagesize(void); + +GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */ + +GC_INNER void GC_bl_init(void); +GC_INNER void GC_bl_init_no_interiors(void); /* defined in blacklst.c */ + +GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */ + +/* Store debugging info into p. Return displaced pointer. */ +/* Assumes we don't hold allocation lock. */ +GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, + int linenum); + +#ifdef REDIRECT_MALLOC +# ifdef GC_LINUX_THREADS + GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp); + /* from os_dep.c */ +# endif +#elif defined(MSWIN32) || defined(MSWINCE) + GC_INNER void GC_add_current_malloc_heap(void); +#endif /* !REDIRECT_MALLOC */ + +#ifdef MAKE_BACK_GRAPH + GC_INNER void GC_build_back_graph(void); + GC_INNER void GC_traverse_back_graph(void); +#endif + +#ifdef MSWIN32 + GC_INNER void GC_init_win32(void); +#endif + +#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) + GC_INNER void * GC_roots_present(ptr_t); + /* The type is a lie, since the real type doesn't make sense here, */ + /* and we only test for NULL. */ +#endif + +#ifdef GC_WIN32_THREADS + GC_INNER void GC_get_next_stack(char *start, char * limit, char **lo, + char **hi); +# ifdef MPROTECT_VDB + GC_INNER void GC_set_write_fault_handler(void); +# endif +#endif /* GC_WIN32_THREADS */ + +#ifdef THREADS + GC_INNER void GC_reset_finalizer_nested(void); + GC_INNER unsigned char *GC_check_finalizer_nested(void); + GC_INNER void GC_do_blocking_inner(ptr_t data, void * context); + GC_INNER void GC_push_all_stacks(void); +# ifdef USE_PROC_FOR_LIBRARIES + GC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi); +# endif +# ifdef IA64 + GC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound); +# endif +#endif /* THREADS */ + +#ifdef DYNAMIC_LOADING + GC_INNER GC_bool GC_register_main_static_data(void); +# ifdef DARWIN + GC_INNER void GC_init_dyld(void); +# endif +#endif /* DYNAMIC_LOADING */ + +#ifdef SEARCH_FOR_DATA_START + GC_INNER void GC_init_linux_data_start(void); +#endif + +#if defined(NETBSD) && defined(__ELF__) + GC_INNER void GC_init_netbsd_elf(void); +#endif + +#ifdef UNIX_LIKE + GC_INNER void GC_set_and_save_fault_handler(void (*handler)(int)); +#endif + +#ifdef NEED_PROC_MAPS + GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, + char **prot, unsigned int *maj_dev, + char **mapping_name); + GC_INNER char *GC_get_maps(void); /* from os_dep.c */ +#endif + #ifdef GC_ASSERTIONS # define GC_ASSERT(expr) \ if (!(expr)) { \ diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index bd99e6d0..81c77d65 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2451,6 +2451,11 @@ # endif #endif +#if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \ + || !defined(SMALL_CONFIG)) +# define NEED_PROC_MAPS +#endif + #if defined(LINUX) || defined(HURD) || defined(__GLIBC__) # define REGISTER_LIBRARIES_EARLY /* We sometimes use dl_iterate_phdr, which may acquire an internal */ diff --git a/include/private/pthread_stop_world.h b/include/private/pthread_stop_world.h index c883c3c8..cb67d230 100644 --- a/include/private/pthread_stop_world.h +++ b/include/private/pthread_stop_world.h @@ -39,4 +39,6 @@ struct thread_stop_info { # endif }; +GC_INNER void GC_stop_init(void); + #endif diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index 2b16bd56..ba0f6936 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -30,7 +30,7 @@ #ifdef THREAD_LOCAL_ALLOC # include "thread_local_alloc.h" -#endif /* THREAD_LOCAL_ALLOC */ +#endif /* We use the allocation lock to protect thread-related data structures. */ @@ -126,9 +126,20 @@ GC_EXTERN GC_bool GC_in_thread_creation; /* Only set to TRUE while allocation lock is held. */ /* When set, it is OK to run GC from unknown thread. */ -# ifdef NACL - GC_EXTERN __thread GC_thread GC_nacl_gc_thread_self; -# endif +#ifdef NACL + GC_EXTERN __thread GC_thread GC_nacl_gc_thread_self; + GC_INNER void GC_nacl_initialize_gc_thread(void); + GC_INNER void GC_nacl_shutdown_gc_thread(void); +#endif + +#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK + GC_INNER void GC_unblock_gc_signals(void); +#endif + +GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *), + void **pstart_arg, + struct GC_stack_base *sb, void *arg); +GC_INNER void GC_thread_exit_proc(void *); #endif /* GC_PTHREADS && !GC_WIN32_THREADS */ diff --git a/malloc.c b/malloc.c index fceb9dc6..d01f1e7f 100644 --- a/malloc.c +++ b/malloc.c @@ -18,8 +18,6 @@ #include #include -GC_INNER void GC_extend_size_map(size_t); /* in misc.c */ - /* Allocate reclaim list for kind: */ /* Return TRUE on success */ STATIC GC_bool GC_alloc_reclaim_list(struct obj_kind *kind) @@ -352,8 +350,6 @@ void * malloc(size_t lb) STATIC ptr_t GC_libpthread_end = 0; STATIC ptr_t GC_libld_start = 0; STATIC ptr_t GC_libld_end = 0; - GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp); - /* From os_dep.c */ STATIC void GC_init_lib_bounds(void) { diff --git a/mark.c b/mark.c index 65811084..fa67ef75 100644 --- a/mark.c +++ b/mark.c @@ -1331,11 +1331,6 @@ GC_INNER void GC_push_all(ptr_t bottom, ptr_t top) } } -# ifdef PROC_VDB - GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h); - /* Could the page contain valid heap pointers? */ -# endif - GC_INNER void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all) { if (!all) { diff --git a/mark_rts.c b/mark_rts.c index 02acf3bd..4cd97bdc 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -111,7 +111,7 @@ static int n_root_sets = 0; /* Is a range starting at b already in the table? If so return a */ /* pointer to it, else NULL. */ - GC_INNER struct roots * GC_roots_present(ptr_t b) + GC_INNER void * GC_roots_present(ptr_t b) { int h = rt_hash(b); struct roots *p = GC_root_index[h]; @@ -120,7 +120,7 @@ static int n_root_sets = 0; if (p -> r_start == (ptr_t)b) return(p); p = p -> r_next; } - return(FALSE); + return NULL; } /* Add the given root structure to the index. */ @@ -216,7 +216,7 @@ void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp) } } # else - old = GC_roots_present(b); + old = (struct roots *)GC_roots_present(b); if (old != 0) { if (e <= old -> r_end) /* already there */ return; /* else extend */ @@ -690,10 +690,6 @@ STATIC void GC_push_gc_structures(void) GC_push_typed_structures(); } -#ifdef THREAD_LOCAL_ALLOC - GC_INNER void GC_mark_thread_local_free_lists(void); -#endif - GC_INNER void GC_cond_register_dynamic_libraries(void) { # if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ diff --git a/misc.c b/misc.c index 428cffe6..34bb570e 100644 --- a/misc.c +++ b/misc.c @@ -59,7 +59,6 @@ #ifdef DYNAMIC_LOADING /* We need to register the main data segment. Returns TRUE unless */ /* this is done implicitly as part of dynamic library registration. */ - GC_INNER GC_bool GC_register_main_static_data(void); # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data() #else /* Don't unnecessarily call GC_register_main_static_data() in case */ @@ -586,25 +585,12 @@ GC_INNER GC_bool GC_is_initialized = FALSE; GC_INNER CRITICAL_SECTION GC_write_cs; #endif -#ifdef MSWIN32 - GC_INNER void GC_init_win32(void); -#endif - -GC_INNER void GC_setpagesize(void); - STATIC void GC_exit_check(void) { GC_gcollect(); } -#ifdef SEARCH_FOR_DATA_START - GC_INNER void GC_init_linux_data_start(void); -#endif - #ifdef UNIX_LIKE - - GC_INNER void GC_set_and_save_fault_handler(void (*handler)(int)); - static void looping_handler(int sig) { GC_err_printf("Caught signal %d: looping in handler\n", sig); @@ -627,14 +613,6 @@ STATIC void GC_exit_check(void) # define maybe_install_looping_handler() #endif -#if defined(DYNAMIC_LOADING) && defined(DARWIN) - GC_INNER void GC_init_dyld(void); -#endif - -#if defined(NETBSD) && defined(__ELF__) - GC_INNER void GC_init_netbsd_elf(void); -#endif - #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) STATIC int GC_stdout = 1; STATIC int GC_stderr = 2; @@ -675,9 +653,6 @@ STATIC word GC_parse_mem_size_arg(const char *str) return result; } -GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */ -GC_INNER void GC_bl_init(void); /* defined in blacklst.c */ - GC_API void GC_CALL GC_init(void) { /* LOCK(); -- no longer does anything this early. */ @@ -1556,12 +1531,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn, void *arg) return fn(&base, arg); } -#ifdef THREADS - - /* Defined in pthread_support.c or win32_threads.c. */ - GC_INNER void GC_do_blocking_inner(ptr_t data, void * context); - -#else +#ifndef THREADS GC_INNER ptr_t GC_blocked_sp = NULL; /* NULL value means we are not inside GC_do_blocking() call. */ @@ -1754,8 +1724,6 @@ GC_API int GC_CALL GC_get_find_leak(void) return GC_find_leak; } -GC_INNER void GC_bl_init_no_interiors(void); /* defined in blacklst.c */ - GC_API void GC_CALL GC_set_all_interior_pointers(int value) { DCL_LOCK_STATE; diff --git a/os_dep.c b/os_dep.c index 21613d9a..73b49396 100644 --- a/os_dep.c +++ b/os_dep.c @@ -138,11 +138,6 @@ #define IGNORE_PAGES_EXECUTABLE 1 /* Undefined on GC_pages_executable real use. */ -#if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \ - || !defined(SMALL_CONFIG)) -# define NEED_PROC_MAPS -#endif - #ifdef NEED_PROC_MAPS /* We need to parse /proc/self/maps, either to find dynamic libraries, */ /* and/or to find the register backing store base (IA64). Do it once */ @@ -474,7 +469,7 @@ GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp) # endif /* LINUX */ GC_data_start = GC_find_limit((ptr_t)(_end), FALSE); } -#endif +#endif /* SEARCH_FOR_DATA_START */ #ifdef ECOS @@ -1220,11 +1215,6 @@ GC_INNER word GC_page_size = 0; # include /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */ -# ifdef IA64 - GC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound); - /* From pthread_support.c */ -# endif - GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b) { pthread_attr_t attr; @@ -2555,16 +2545,11 @@ STATIC void GC_default_push_other_roots(void) # endif /* PCR */ - # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) - -GC_INNER void GC_push_all_stacks(void); - -STATIC void GC_default_push_other_roots(void) -{ - GC_push_all_stacks(); -} - + STATIC void GC_default_push_other_roots(void) + { + GC_push_all_stacks(); + } # endif /* GC_WIN32_THREADS || GC_PTHREADS */ # ifdef SN_TARGET_PS3 @@ -3096,7 +3081,7 @@ STATIC void GC_default_push_other_roots(void) == STATUS_ACCESS_VIOLATION) # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \ == 1) /* Write fault */ - GC_INNER LONG WINAPI GC_write_fault_handler( + STATIC LONG WINAPI GC_write_fault_handler( struct _EXCEPTION_POINTERS *exc_info) # endif /* MSWIN32 || MSWINCE */ { @@ -3209,6 +3194,13 @@ STATIC void GC_default_push_other_roots(void) ABORT("Unexpected bus error or segmentation fault"); # endif } + +# ifdef GC_WIN32_THREADS + GC_INNER void GC_set_write_fault_handler(void) + { + SetUnhandledExceptionFilter(GC_write_fault_handler); + } +# endif #endif /* !DARWIN */ /* We hold the allocation lock. We expect block h to be written */ diff --git a/pthread_start.c b/pthread_start.c index c3a01c41..9d3556b4 100644 --- a/pthread_start.c +++ b/pthread_start.c @@ -41,12 +41,6 @@ #include #include -GC_INNER GC_thread GC_start_rtn_prepare_thread(void *(**pstart)(void *), - void **pstart_arg, - struct GC_stack_base *sb, void *arg); -GC_INNER void GC_thread_exit_proc(void *arg); - /* defined in pthread_support.c */ - /* Invoked from GC_start_routine(). */ void * GC_CALLBACK GC_inner_start_routine(struct GC_stack_base *sb, void *arg) { diff --git a/pthread_support.c b/pthread_support.c index f2d1754c..33e37924 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -462,11 +462,6 @@ void GC_push_thread_structures(void) /* It may not be safe to allocate when we register the first thread. */ static struct GC_Thread_Rep first_thread; -#ifdef NACL - GC_INNER void GC_nacl_initialize_gc_thread(void); - GC_INNER void GC_nacl_shutdown_gc_thread(void); -#endif - /* Add a thread to GC_threads. We assume it wasn't already there. */ /* Caller holds allocation lock. */ STATIC GC_thread GC_new_thread(pthread_t id) @@ -886,10 +881,6 @@ STATIC void GC_fork_child_proc(void) __thread int GC_dummy_thread_local; #endif -#ifndef GC_DARWIN_THREADS - GC_INNER void GC_stop_init(void); /* defined in pthread_stop_world.c */ -#endif - /* We hold the allocation lock. */ GC_INNER void GC_thr_init(void) { @@ -1046,10 +1037,6 @@ GC_INNER void GC_init_parallel(void) } #endif /* !GC_NO_PTHREAD_SIGMASK */ -#if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) - GC_INNER ptr_t GC_FindTopOfStack(unsigned long); -#endif - /* Wrapper for functions that are likely to block for an appreciable */ /* length of time. */ @@ -1358,10 +1345,6 @@ GC_INLINE void GC_record_stack_base(GC_thread me, # endif } -#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK - GC_INNER void GC_unblock_gc_signals(void); /* from pthread_stop_world.c */ -#endif - STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, pthread_t my_pthread) { diff --git a/reclaim.c b/reclaim.c index 68dd1b98..405087b8 100644 --- a/reclaim.c +++ b/reclaim.c @@ -41,10 +41,6 @@ STATIC unsigned GC_n_leaked = 0; GC_INNER GC_bool GC_have_errors = FALSE; -#ifndef SHORT_DBG_HDRS - GC_INNER GC_bool GC_check_leaked(ptr_t base); /* from dbg_mlc.c */ -#endif - GC_INLINE void GC_add_leaked(ptr_t leaked) { # ifndef SHORT_DBG_HDRS diff --git a/thread_local_alloc.c b/thread_local_alloc.c index 1540f9ff..610db6fd 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -284,7 +284,7 @@ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p) } #if defined(GC_ASSERTIONS) - /* Check that all thread-local free-lists in p are completely marked. */ + /* Check that all thread-local free-lists in p are completely marked. */ void GC_check_tls_for(GC_tlfs p) { ptr_t q; diff --git a/win32_threads.c b/win32_threads.c index 15b4b15c..47dc39c1 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -350,17 +350,6 @@ STATIC GC_thread GC_new_thread(DWORD id) return(result); } -#ifdef MPROTECT_VDB - GC_INNER LONG WINAPI GC_write_fault_handler( - struct _EXCEPTION_POINTERS *exc_info); -#endif - -#if defined(GWW_VDB) && defined(MPROTECT_VDB) - GC_INNER GC_bool GC_gww_dirty_init(void); - /* Defined in os_dep.c. Returns TRUE if GetWriteWatch is available. */ - /* may be called repeatedly. */ -#endif - STATIC GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ @@ -389,12 +378,12 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, /* documentation. There is empirical evidence that it */ /* isn't. - HB */ # if defined(MPROTECT_VDB) -# if defined(GWW_VDB) - if (GC_incremental && !GC_gww_dirty_init()) - SetUnhandledExceptionFilter(GC_write_fault_handler); -# else - if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler); -# endif + if (GC_incremental +# ifdef GWW_VDB + && !GC_gww_dirty_init() +# endif + ) + GC_set_write_fault_handler(); # endif # ifndef GC_NO_THREADS_DISCOVERY @@ -1403,7 +1392,7 @@ GC_INNER void GC_push_all_stacks(void) /* in stack (or ADDR_LIMIT if unset) */ /* for markers. */ -#endif +#endif /* PARALLEL_MARK */ /* Find stack with the lowest address which overlaps the */ /* interval [start, limit). */ -- cgit v1.2.1 From c3e52de4a55fc3baa8ee981830b01fc65de95dfd Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 31 May 2011 17:22:01 +0000 Subject: 2011-05-31 Ivan Maidanski * NT_STATIC_THREADS_MAKEFILE (.cpp.obj): Remove duplicate .cpp filename passed. * NT_X64_THREADS_MAKEFILE (.cpp.obj): Use lowercase file extension. * NT_X64_STATIC_THREADS_MAKEFILE (.cpp.obj): Ditto. * NT_MAKEFILE (.cpp.obj): Ditto. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ NT_MAKEFILE | 2 +- NT_STATIC_THREADS_MAKEFILE | 2 +- NT_X64_STATIC_THREADS_MAKEFILE | 2 +- NT_X64_THREADS_MAKEFILE | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a67cde62..112224d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-31 Ivan Maidanski + + * NT_STATIC_THREADS_MAKEFILE (.cpp.obj): Remove duplicate .cpp + filename passed. + * NT_X64_THREADS_MAKEFILE (.cpp.obj): Use lowercase file + extension. + * NT_X64_STATIC_THREADS_MAKEFILE (.cpp.obj): Ditto. + * NT_MAKEFILE (.cpp.obj): Ditto. + 2011-05-31 Ivan Maidanski * alloc.c (GC_add_current_malloc_heap, GC_build_back_graph, diff --git a/NT_MAKEFILE b/NT_MAKEFILE index f9077a3d..809d9f77 100644 --- a/NT_MAKEFILE +++ b/NT_MAKEFILE @@ -18,7 +18,7 @@ all: gctest.exe cord\de.exe test_cpp.exe $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj .cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.CPP /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h diff --git a/NT_STATIC_THREADS_MAKEFILE b/NT_STATIC_THREADS_MAKEFILE index 6892d291..9a003478 100644 --- a/NT_STATIC_THREADS_MAKEFILE +++ b/NT_STATIC_THREADS_MAKEFILE @@ -25,7 +25,7 @@ all: gctest.exe cord\de.exe test_cpp.exe $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -DPARALLEL_MARK -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj .cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h diff --git a/NT_X64_STATIC_THREADS_MAKEFILE b/NT_X64_STATIC_THREADS_MAKEFILE index 7b31bfd5..93de9727 100644 --- a/NT_X64_STATIC_THREADS_MAKEFILE +++ b/NT_X64_STATIC_THREADS_MAKEFILE @@ -28,7 +28,7 @@ all: gctest.exe cord\de.exe test_cpp.exe # of safe uses of strncpy. It would be nice to leave the rest enabled. .cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.CPP /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h diff --git a/NT_X64_THREADS_MAKEFILE b/NT_X64_THREADS_MAKEFILE index eadd6163..e0a252b7 100644 --- a/NT_X64_THREADS_MAKEFILE +++ b/NT_X64_THREADS_MAKEFILE @@ -35,7 +35,7 @@ all: gc64.dll gctest.exe cord\de.exe test_cpp.exe # Disable crt security warnings, since unfortunately they warn about all sorts # of safe uses of strncpy. It would be nice to leave the rest enabled. .cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DALL_INTERIOR_POINTERS -DGC_DLL -DGC_THREADS -D_CRT_SECURE_NO_DEPRECATE $*.CPP /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DALL_INTERIOR_POINTERS -DGC_DLL -DGC_THREADS -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h -- cgit v1.2.1 From dea5a60fe7b05322e89ad2de72c56b6af105b979 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 14 Jun 2011 12:34:55 +0000 Subject: 2011-06-14 Ivan Maidanski * include/gc_version.h, configure.ac, doc/README: Change to version 7.2alpha6. * configure: Regenerate. --HG-- branch : bdwgc Conflicts: libatomic_ops/ChangeLog libatomic_ops/README libatomic_ops/configure libatomic_ops/configure.ac --- ChangeLog | 8 ++++++++ configure | 22 +++++++++++----------- configure.ac | 2 +- doc/README | 2 +- include/gc_version.h | 2 +- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 112224d6..11a07e25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +[7.2alpha6] + +2011-06-14 Ivan Maidanski + + * include/gc_version.h, configure.ac, doc/README: Change to + version 7.2alpha6. + * configure: Regenerate. + 2011-05-31 Ivan Maidanski * NT_STATIC_THREADS_MAKEFILE (.cpp.obj): Remove duplicate .cpp diff --git a/configure b/configure index 572544aa..9bf0ee20 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh -# From configure.ac Revision: 1.65 . +# From configure.ac Revision: 1.66 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for gc 7.2alpha5. +# Generated by GNU Autoconf 2.68 for gc 7.2alpha6. # # Report bugs to . # @@ -571,8 +571,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gc' PACKAGE_TARNAME='gc' -PACKAGE_VERSION='7.2alpha5' -PACKAGE_STRING='gc 7.2alpha5' +PACKAGE_VERSION='7.2alpha6' +PACKAGE_STRING='gc 7.2alpha6' PACKAGE_BUGREPORT='Hans.Boehm@hp.com' PACKAGE_URL='' @@ -1368,7 +1368,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gc 7.2alpha5 to adapt to many kinds of systems. +\`configure' configures gc 7.2alpha6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1439,7 +1439,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gc 7.2alpha5:";; + short | recursive ) echo "Configuration of gc 7.2alpha6:";; esac cat <<\_ACEOF @@ -1567,7 +1567,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gc configure 7.2alpha5 +gc configure 7.2alpha6 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2057,7 +2057,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gc $as_me 7.2alpha5, which was +It was created by gc $as_me 7.2alpha6, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3031,7 +3031,7 @@ fi # Define the identity of the package. PACKAGE='gc' - VERSION='7.2alpha5' + VERSION='7.2alpha6' cat >>confdefs.h <<_ACEOF @@ -17228,7 +17228,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gc $as_me 7.2alpha5, which was +This file was extended by gc $as_me 7.2alpha6, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17294,7 +17294,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gc config.status 7.2alpha5 +gc config.status 7.2alpha6 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index ca2813b5..aaf2b859 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Process this file with autoconf to produce configure. # Initialization # ============== -AC_INIT(gc,7.2alpha5,Hans.Boehm@hp.com) +AC_INIT(gc,7.2alpha6,Hans.Boehm@hp.com) ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)? AC_CONFIG_SRCDIR(gcj_mlc.c) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/README b/doc/README index e9252bc5..b7def03a 100644 --- a/doc/README +++ b/doc/README @@ -36,7 +36,7 @@ Public License, but is not needed by, nor linked into the collector library. It is included here only becuase the atomic_ops distribution is, for simplicity, included in its entirety. -This is version 7.2alpha5 of a conservative garbage collector for C and C++. +This is version 7.2alpha6 of a conservative garbage collector for C and C++. You might find a more recent version of this at diff --git a/include/gc_version.h b/include/gc_version.h index ee3bb22c..6c638ecb 100644 --- a/include/gc_version.h +++ b/include/gc_version.h @@ -23,7 +23,7 @@ /* it to keep the old-style build process working. */ #define GC_TMP_VERSION_MAJOR 7 #define GC_TMP_VERSION_MINOR 2 -#define GC_TMP_ALPHA_VERSION 5 +#define GC_TMP_ALPHA_VERSION 6 #ifndef GC_NOT_ALPHA # define GC_NOT_ALPHA 0xff -- cgit v1.2.1 From 739ef9386bcd18e58e718570a76938404a620698 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 14 Jun 2011 13:25:24 +0000 Subject: 2011-06-14 Ivan Maidanski * configure_atomic_ops.sh: Remove. * Makefile.direct (dist gc.tar): Remove configure_atomic_ops.sh. * Makefile.am (EXTRA_DIST): Add autogen.sh. * Makefile.in: Regenerate. * configure: Ditto. --HG-- branch : bdwgc --- ChangeLog | 8 ++++++++ Makefile.am | 2 +- Makefile.direct | 1 - Makefile.in | 14 +++++++------- configure | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11a07e25..ba2fa7c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ [7.2alpha6] +2011-06-14 Ivan Maidanski + + * configure_atomic_ops.sh: Remove. + * Makefile.direct (dist gc.tar): Remove configure_atomic_ops.sh. + * Makefile.am (EXTRA_DIST): Add autogen.sh. + * Makefile.in: Regenerate. + * configure: Ditto. + 2011-06-14 Ivan Maidanski * include/gc_version.h, configure.ac, doc/README: Change to diff --git a/Makefile.am b/Makefile.am index 319e116d..4de6e46f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -172,7 +172,7 @@ EXTRA_DIST += README.QUICK EXTRA_DIST += BCC_MAKEFILE NT_MAKEFILE \ OS2_MAKEFILE PCR-Makefile digimars.mak EMX_MAKEFILE \ Makefile.direct Makefile.dj Makefile.DLLs SMakefile.amiga \ - WCC_MAKEFILE build_atomic_ops.sh build_atomic_ops.sh.cygwin \ + WCC_MAKEFILE autogen.sh build_atomic_ops.sh build_atomic_ops.sh.cygwin \ NT_STATIC_THREADS_MAKEFILE NT_X64_STATIC_THREADS_MAKEFILE \ NT_X64_THREADS_MAKEFILE CMakeLists.txt tests/CMakeLists.txt diff --git a/Makefile.direct b/Makefile.direct index 99075fcd..707a94e2 100644 --- a/Makefile.direct +++ b/Makefile.direct @@ -418,7 +418,6 @@ gcname: $(srcdir)/extra/gcname.c $(srcdir)/include/gc_version.h dist gc.tar: $(SRCS) $(DOC_FILES) $(OTHER_FILES) add_gc_prefix gcname cp Makefile Makefile.old cp Makefile.direct Makefile - CC=$(CC) ./configure_atomic_ops.sh cd $(AO_SRC_DIR); $(MAKE) dist if test $(srcdir)/libatomic_ops = $(AO_SRC_DIR); \ then \ diff --git a/Makefile.in b/Makefile.in index 179a67b0..09dea13b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -556,13 +556,13 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ EXTRA_DIST = gc_cpp.cpp README.QUICK BCC_MAKEFILE NT_MAKEFILE \ OS2_MAKEFILE PCR-Makefile digimars.mak EMX_MAKEFILE \ Makefile.direct Makefile.dj Makefile.DLLs SMakefile.amiga \ - WCC_MAKEFILE build_atomic_ops.sh build_atomic_ops.sh.cygwin \ - NT_STATIC_THREADS_MAKEFILE NT_X64_STATIC_THREADS_MAKEFILE \ - NT_X64_THREADS_MAKEFILE CMakeLists.txt tests/CMakeLists.txt \ - extra/add_gc_prefix.c extra/gc.c extra/gcname.c \ - extra/if_mach.c extra/if_not_there.c hpux_test_and_clear.s \ - gc.mak extra/MacOS.c MacProjects.sit.hqx mach_dep.c \ - extra/setjmp_t.c extra/threadlibs.c extra/AmigaOS.c \ + WCC_MAKEFILE autogen.sh build_atomic_ops.sh \ + build_atomic_ops.sh.cygwin NT_STATIC_THREADS_MAKEFILE \ + NT_X64_STATIC_THREADS_MAKEFILE NT_X64_THREADS_MAKEFILE \ + CMakeLists.txt tests/CMakeLists.txt extra/add_gc_prefix.c \ + extra/gc.c extra/gcname.c extra/if_mach.c extra/if_not_there.c \ + hpux_test_and_clear.s gc.mak extra/MacOS.c MacProjects.sit.hqx \ + mach_dep.c extra/setjmp_t.c extra/threadlibs.c extra/AmigaOS.c \ Mac_files/datastart.c Mac_files/dataend.c \ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \ include/private/msvc_dbg.h extra/msvc_dbg.c libatomic_ops \ diff --git a/configure b/configure index 9bf0ee20..55e4f011 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 1.66 . +# From configure.ac Revision: 1.67 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for gc 7.2alpha6. # -- cgit v1.2.1 From 85ca714625602aeb11bb6f110d96b67ab5f6d2c4 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 14 Jun 2011 13:28:26 +0000 Subject: 2011-06-14 Ivan Maidanski * configure_atomic_ops.sh: Remove. --HG-- branch : bdwgc --- configure_atomic_ops.sh | 4 ---- 1 file changed, 4 deletions(-) delete mode 100755 configure_atomic_ops.sh diff --git a/configure_atomic_ops.sh b/configure_atomic_ops.sh deleted file mode 100755 index 932579f1..00000000 --- a/configure_atomic_ops.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -P=`pwd`/libatomic_ops-install -cd libatomic_ops -./configure --prefix=$P -- cgit v1.2.1 From 5317a31a242cf3f2d87dc45f5ecbfd83a2a5bd04 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 15 Jun 2011 11:41:30 +0000 Subject: 2011-06-15 Ivan Maidanski * include/gc_version.h, configure.ac, doc/README: Change to version 7.2alpha7. * configure: Regenerate. --HG-- branch : bdwgc Conflicts: libatomic_ops/ChangeLog libatomic_ops/README libatomic_ops/configure libatomic_ops/configure.ac --- ChangeLog | 6 ++++++ configure | 20 ++++++++++---------- configure.ac | 2 +- doc/README | 2 +- include/gc_version.h | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba2fa7c1..54fe9318 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-15 Ivan Maidanski + + * include/gc_version.h, configure.ac, doc/README: Change to + version 7.2alpha7. + * configure: Regenerate. + [7.2alpha6] 2011-06-14 Ivan Maidanski diff --git a/configure b/configure index 55e4f011..102c4e93 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac Revision: 1.67 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for gc 7.2alpha6. +# Generated by GNU Autoconf 2.68 for gc 7.2alpha7. # # Report bugs to . # @@ -571,8 +571,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gc' PACKAGE_TARNAME='gc' -PACKAGE_VERSION='7.2alpha6' -PACKAGE_STRING='gc 7.2alpha6' +PACKAGE_VERSION='7.2alpha7' +PACKAGE_STRING='gc 7.2alpha7' PACKAGE_BUGREPORT='Hans.Boehm@hp.com' PACKAGE_URL='' @@ -1368,7 +1368,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gc 7.2alpha6 to adapt to many kinds of systems. +\`configure' configures gc 7.2alpha7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1439,7 +1439,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gc 7.2alpha6:";; + short | recursive ) echo "Configuration of gc 7.2alpha7:";; esac cat <<\_ACEOF @@ -1567,7 +1567,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gc configure 7.2alpha6 +gc configure 7.2alpha7 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2057,7 +2057,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gc $as_me 7.2alpha6, which was +It was created by gc $as_me 7.2alpha7, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3031,7 +3031,7 @@ fi # Define the identity of the package. PACKAGE='gc' - VERSION='7.2alpha6' + VERSION='7.2alpha7' cat >>confdefs.h <<_ACEOF @@ -17228,7 +17228,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gc $as_me 7.2alpha6, which was +This file was extended by gc $as_me 7.2alpha7, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17294,7 +17294,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gc config.status 7.2alpha6 +gc config.status 7.2alpha7 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index aaf2b859..81899cff 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Process this file with autoconf to produce configure. # Initialization # ============== -AC_INIT(gc,7.2alpha6,Hans.Boehm@hp.com) +AC_INIT(gc,7.2alpha7,Hans.Boehm@hp.com) ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)? AC_CONFIG_SRCDIR(gcj_mlc.c) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/README b/doc/README index b7def03a..8ca035bd 100644 --- a/doc/README +++ b/doc/README @@ -36,7 +36,7 @@ Public License, but is not needed by, nor linked into the collector library. It is included here only becuase the atomic_ops distribution is, for simplicity, included in its entirety. -This is version 7.2alpha6 of a conservative garbage collector for C and C++. +This is version 7.2alpha7 of a conservative garbage collector for C and C++. You might find a more recent version of this at diff --git a/include/gc_version.h b/include/gc_version.h index 6c638ecb..4ea1a897 100644 --- a/include/gc_version.h +++ b/include/gc_version.h @@ -23,7 +23,7 @@ /* it to keep the old-style build process working. */ #define GC_TMP_VERSION_MAJOR 7 #define GC_TMP_VERSION_MINOR 2 -#define GC_TMP_ALPHA_VERSION 6 +#define GC_TMP_ALPHA_VERSION 7 #ifndef GC_NOT_ALPHA # define GC_NOT_ALPHA 0xff -- cgit v1.2.1 From 02fcd543879adfee64dc66ec1652f742e94a63a8 Mon Sep 17 00:00:00 2001 From: Johannes Totz Date: Thu, 23 Jun 2011 20:01:51 +0000 Subject: update tags --HG-- branch : bdwgc --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 454be6c2..34dd2d9a 100644 --- a/.hgtags +++ b/.hgtags @@ -2,6 +2,7 @@ 3c239e80bee0341c7834b5c5f85738c26da09f87 gc7_0 e0ac59e6cd2913a15a9262cacc21576804a4abae gc7_2alpha2 43c85b2e652869da9de1058eb3e94b79c755941a gc7_0alpha7 +24a2e5b43a289dc9ba38fbde2b602c79c632ce03 gc7_2alpha6 de9672597e74978f9220b7b54c618b33a6d5c507 gc7_0alpha9 664dc1f702d2a4665b13964252fb63df0c58c93e start 052dc64d52d33f2e8cf2a6514d1f6176af89da67 gc7_1 -- cgit v1.2.1 From 26ca46c1c1c6c6599788cc050e43c842050d32d2 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 30 Jun 2011 15:29:26 +0000 Subject: 2011-06-30 Ivan Maidanski * pthread_support.c (GC_segment_is_thread_stack): Replace '&' operator with '&&' one in conditional expressions. * specific.c (remove_specific): Dereference "entry" local variable only if it is non-NULL. * include/gc.h (GC_NEW): Refine the comment (about the returned value). --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ include/gc.h | 3 ++- pthread_support.c | 4 ++-- specific.c | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 54fe9318..f5423602 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-06-30 Ivan Maidanski + + * pthread_support.c (GC_segment_is_thread_stack): Replace '&' + operator with '&&' one in conditional expressions. + * specific.c (remove_specific): Dereference "entry" local variable + only if it is non-NULL. + * include/gc.h (GC_NEW): Refine the comment (about the returned + value). + 2011-06-15 Ivan Maidanski * include/gc_version.h, configure.ac, doc/README: Change to diff --git a/include/gc.h b/include/gc.h index 3e3f56e3..ae7d046f 100644 --- a/include/gc.h +++ b/include/gc.h @@ -717,7 +717,8 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */, /* The following are included because they are often convenient, and */ /* reduce the chance for a misspecified size argument. But calls may */ /* expand to something syntactically incorrect if t is a complicated */ -/* type expression. */ +/* type expression. Note that, unlike C++ new operator, these ones */ +/* may return NULL (if out of memory). */ #define GC_NEW(t) ((t*)GC_MALLOC(sizeof(t))) #define GC_NEW_ATOMIC(t) ((t*)GC_MALLOC_ATOMIC(sizeof(t))) #define GC_NEW_STUBBORN(t) ((t*)GC_MALLOC_STUBBORN(sizeof(t))) diff --git a/pthread_support.c b/pthread_support.c index 33e37924..f9af3029 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -652,9 +652,9 @@ STATIC void GC_remove_all_threads_but_me(void) GC_ASSERT(I_HOLD_LOCK()); # ifdef PARALLEL_MARK for (i = 0; i < GC_markers - 1; ++i) { - if (marker_sp[i] > lo & marker_sp[i] < hi) return TRUE; + if (marker_sp[i] > lo && marker_sp[i] < hi) return TRUE; # ifdef IA64 - if (marker_bsp[i] > lo & marker_bsp[i] < hi) return TRUE; + if (marker_bsp[i] > lo && marker_bsp[i] < hi) return TRUE; # endif } # endif diff --git a/specific.c b/specific.c index cbeb2331..98d86c31 100644 --- a/specific.c +++ b/specific.c @@ -82,8 +82,8 @@ void PREFIXED(remove_specific) (tsd * key) { } /* Invalidate qtid field, since qtids may be reused, and a later */ /* cache lookup could otherwise find this entry. */ - entry -> qtid = INVALID_QTID; if (entry != NULL) { + entry -> qtid = INVALID_QTID; *link = entry -> next; /* Atomic! concurrent accesses still work. */ /* They must, since readers don't lock. */ -- cgit v1.2.1 From 02f2aca716964205b28aa973b0c785d0fda490e5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 30 Jun 2011 15:43:44 +0000 Subject: 2011-06-30 Ivan Maidanski * dyn_load.c (GC_register_map_entries): Remove "count" local variable as unused. * gc_dlopen.c (disable_gc_for_dlopen): Define only if not USE_PROC_FOR_LIBRARIES. * malloc.c (calloc): Add parentheses around '&&' operator. * mark.c (GC_noop_sink): New global variable (instead of a static local variable inside GC_noop1). * mark.c (GC_noop1): Use GC_noop_sink variable (to prevent "variable set but not used" compiler warning). * include/private/gcconfig.h (USE_PROC_FOR_LIBRARIES): Define only if undefined yet. * tests/smash_test.c (main): Don't dereference "p" local variable if it is NULL. * tests/staticrootslib.c (main): Ditto. --HG-- branch : bdwgc --- ChangeLog | 17 +++++++++++++++++ dyn_load.c | 1 - gc_dlopen.c | 20 +++++++++++--------- include/private/gcconfig.h | 3 ++- malloc.c | 2 +- mark.c | 5 ++--- tests/smash_test.c | 2 +- tests/staticrootslib.c | 6 ++++-- 8 files changed, 38 insertions(+), 18 deletions(-) mode change 100755 => 100644 tests/staticrootslib.c diff --git a/ChangeLog b/ChangeLog index f5423602..ab7c4398 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-06-30 Ivan Maidanski + + * dyn_load.c (GC_register_map_entries): Remove "count" local + variable as unused. + * gc_dlopen.c (disable_gc_for_dlopen): Define only if not + USE_PROC_FOR_LIBRARIES. + * malloc.c (calloc): Add parentheses around '&&' operator. + * mark.c (GC_noop_sink): New global variable (instead of a static + local variable inside GC_noop1). + * mark.c (GC_noop1): Use GC_noop_sink variable (to prevent + "variable set but not used" compiler warning). + * include/private/gcconfig.h (USE_PROC_FOR_LIBRARIES): Define only + if undefined yet. + * tests/smash_test.c (main): Don't dereference "p" local variable + if it is NULL. + * tests/staticrootslib.c (main): Ditto. + 2011-06-30 Ivan Maidanski * pthread_support.c (GC_segment_is_thread_stack): Replace '&' diff --git a/dyn_load.c b/dyn_load.c index 563550db..28a74782 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -273,7 +273,6 @@ STATIC word GC_register_map_entries(char *maps) { char *prot; char *buf_ptr = maps; - int count; ptr_t start, end; unsigned int maj_dev; ptr_t least_ha, greatest_ha; diff --git a/gc_dlopen.c b/gc_dlopen.c index e466d65c..f76230ec 100644 --- a/gc_dlopen.c +++ b/gc_dlopen.c @@ -43,16 +43,18 @@ /* dlopen calls in either a multi-threaded environment, or if the */ /* library initialization code allocates substantial amounts of GC'ed */ /* memory. */ -static void disable_gc_for_dlopen(void) -{ - DCL_LOCK_STATE; - LOCK(); - while (GC_incremental && GC_collection_in_progress()) { - GC_collect_a_little_inner(1000); +#ifndef USE_PROC_FOR_LIBRARIES + static void disable_gc_for_dlopen(void) + { + DCL_LOCK_STATE; + LOCK(); + while (GC_incremental && GC_collection_in_progress()) { + GC_collect_a_little_inner(1000); + } + ++GC_dont_gc; + UNLOCK(); } - ++GC_dont_gc; - UNLOCK(); -} +#endif /* Redefine dlopen to guarantee mutual exclusion with */ /* GC_register_dynamic_libraries. Should probably happen for */ diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 81c77d65..d1695d92 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2253,7 +2253,8 @@ # define USE_MMAP_ANON #endif -#if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) +#if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \ + && !defined(USE_PROC_FOR_LIBRARIES) /* Nptl allocates thread stacks with mmap, which is fine. But it */ /* keeps a cache of thread stacks. Thread stacks contain the */ /* thread control blocks. These in turn contain a pointer to */ diff --git a/malloc.c b/malloc.c index d01f1e7f..80ef18d9 100644 --- a/malloc.c +++ b/malloc.c @@ -382,7 +382,7 @@ void * calloc(size_t n, size_t lb) GC_init_lib_bounds(); lib_bounds_set = TRUE; } - if (caller >= GC_libpthread_start && caller < GC_libpthread_end + if ((caller >= GC_libpthread_start && caller < GC_libpthread_end) || (caller >= GC_libld_start && caller < GC_libld_end)) return GC_malloc_uncollectable(n*lb); /* The two ranges are actually usually adjacent, so there may */ diff --git a/mark.c b/mark.c index fa67ef75..9a34082d 100644 --- a/mark.c +++ b/mark.c @@ -36,11 +36,10 @@ #endif /* Single argument version, robust against whole program analysis. */ +volatile word GC_noop_sink; GC_API void GC_CALL GC_noop1(word x) { - static volatile word sink; - - sink = x; + GC_noop_sink = x; } /* mark_proc GC_mark_procs[MAX_MARK_PROCS] = {0} -- declared in gc_priv.h */ diff --git a/tests/smash_test.c b/tests/smash_test.c index 86e081bd..0e8b1f08 100644 --- a/tests/smash_test.c +++ b/tests/smash_test.c @@ -22,7 +22,7 @@ int main(void) A[i] = p = GC_MALLOC(SIZE); if (i%3000 == 0) GC_gcollect(); - if (i%5678 == 0) p[SIZE + i/2000] = 42; + if (i%5678 == 0 && p != 0) p[SIZE + i/2000] = 42; } return 0; } diff --git a/tests/staticrootslib.c b/tests/staticrootslib.c old mode 100755 new mode 100644 index 16f3352b..2a8fcd49 --- a/tests/staticrootslib.c +++ b/tests/staticrootslib.c @@ -19,8 +19,10 @@ struct treenode * libsrl_mktree(int i) struct treenode * r = GC_MALLOC(sizeof(struct treenode)); if (0 == i) return 0; if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode)); - r -> x = libsrl_mktree(i-1); - r -> y = libsrl_mktree(i-1); + if (r) { + r -> x = libsrl_mktree(i-1); + r -> y = libsrl_mktree(i-1); + } return r; } -- cgit v1.2.1 From 17466786af4f462d95e49ef234a92429e7cd1be0 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 1 Jul 2011 09:53:45 +0000 Subject: 2011-07-01 Ivan Maidanski * win32_threads.c (CHECK_LOOKUP_MY_THREAD): New macro definition. * win32_threads.c (GC_reset_finalizer_nested, GC_check_finalizer_nested, GC_unregister_my_thread, GC_do_blocking_inner, GC_call_with_gc_active, GC_init_parallel): Insert CHECK_LOOKUP_MY_THREAD before dereferencing thread descriptor pointer (to instruct a LINT-like tool that it is ok to dereference the pointer). * win32_threads.c (GC_get_next_stack): Assert plast_stack_min is non-NULL if current_min is not ADDR_LIMIT (for a LINT-like tool). * win32_threads.c (GC_init_parallel): Define and use "me" local variable. * cord/cordtest.c (test_basics): Test CORD_substr() result is non-NULL. * cord/cordtest.c (test_extras): Test fopen() result is non-NULL. * cord/cordtest.c (test_basics, test_extras, test_printf, main): Replace the K&R-style function definition with the ANSI C one. * cord/cordtest.c: Expand all tabs to spaces; remove trailing spaces at EOLn. * include/private/gc_priv.h (ABORT): Define as abort() when checking the code with a LINT-like tool (Win32 only). * tests/test.c (FAIL): Ditto. * tests/test.c (CHECH_GCLIB_VERSION): New macro (to check that the version of libgc.so used at runtime matches that at compile time). * tests/test.c (GC_COND_INIT): Use CHECH_GCLIB_VERSION. * tests/test.c (CHECK_OUT_OF_MEMORY): New macro (to test malloc result for out of memory). * tests/test.c (cons, small_cons, small_cons_uncollectable, gcj_cons, reverse_test_inner, mktree, alloc8bytes, typed_test, run_one_test): Use CHECK_OUT_OF_MEMORY. --HG-- branch : bdwgc --- ChangeLog | 32 ++++++++++++++ cord/cordtest.c | 110 +++++++++++++++++++++++++--------------------- include/private/gc_priv.h | 2 +- tests/test.c | 79 ++++++++++++++++++--------------- win32_threads.c | 24 +++++++--- 5 files changed, 156 insertions(+), 91 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab7c4398..c85fb3b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2011-07-01 Ivan Maidanski + + * win32_threads.c (CHECK_LOOKUP_MY_THREAD): New macro definition. + * win32_threads.c (GC_reset_finalizer_nested, + GC_check_finalizer_nested, GC_unregister_my_thread, + GC_do_blocking_inner, GC_call_with_gc_active, GC_init_parallel): + Insert CHECK_LOOKUP_MY_THREAD before dereferencing thread + descriptor pointer (to instruct a LINT-like tool that it is ok to + dereference the pointer). + * win32_threads.c (GC_get_next_stack): Assert plast_stack_min is + non-NULL if current_min is not ADDR_LIMIT (for a LINT-like tool). + * win32_threads.c (GC_init_parallel): Define and use "me" local + variable. + * cord/cordtest.c (test_basics): Test CORD_substr() result is + non-NULL. + * cord/cordtest.c (test_extras): Test fopen() result is non-NULL. + * cord/cordtest.c (test_basics, test_extras, test_printf, main): + Replace the K&R-style function definition with the ANSI C one. + * cord/cordtest.c: Expand all tabs to spaces; remove + trailing spaces at EOLn. + * include/private/gc_priv.h (ABORT): Define as abort() when + checking the code with a LINT-like tool (Win32 only). + * tests/test.c (FAIL): Ditto. + * tests/test.c (CHECH_GCLIB_VERSION): New macro (to check that the + version of libgc.so used at runtime matches that at compile time). + * tests/test.c (GC_COND_INIT): Use CHECH_GCLIB_VERSION. + * tests/test.c (CHECK_OUT_OF_MEMORY): New macro (to test malloc + result for out of memory). + * tests/test.c (cons, small_cons, small_cons_uncollectable, + gcj_cons, reverse_test_inner, mktree, alloc8bytes, typed_test, + run_one_test): Use CHECK_OUT_OF_MEMORY. + 2011-06-30 Ivan Maidanski * dyn_load.c (GC_register_map_entries): Remove "count" local diff --git a/cord/cordtest.c b/cord/cordtest.c index 08333ca0..42c1fe61 100644 --- a/cord/cordtest.c +++ b/cord/cordtest.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED @@ -10,18 +10,18 @@ * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. */ -/* Boehm, August 24, 1994 11:58 am PDT */ -# include "gc.h" /* For GC_INIT() only */ + +# include "gc.h" /* For GC_INIT() only */ # include "cord.h" # include # include # include -/* This is a very incomplete test of the cord package. It knows about */ -/* a few internals of the package (e.g. when C strings are returned) */ -/* that real clients shouldn't rely on. */ +/* This is a very incomplete test of the cord package. It knows about */ +/* a few internals of the package (e.g. when C strings are returned) */ +/* that real clients shouldn't rely on. */ # define ABORT(string) \ -{ int x = 0; fprintf(stderr, "FAILED: %s\n", string); x = 1 / x; abort(); } + { int x = 0; fprintf(stderr, "FAILED: %s\n", string); x = 1 / x; abort(); } int count; @@ -48,60 +48,64 @@ char id_cord_fn(size_t i, void * client_data) return((char)i); } -void test_basics() +void test_basics(void) { CORD x = CORD_from_char_star("ab"); register int i; char c; CORD y; CORD_pos p; - + x = CORD_cat(x,x); if (!CORD_IS_STRING(x)) ABORT("short cord should usually be a string"); if (strcmp(x, "abab") != 0) ABORT("bad CORD_cat result"); - + for (i = 1; i < 16; i++) { x = CORD_cat(x,x); } x = CORD_cat(x,"c"); if (CORD_len(x) != 128*1024+1) ABORT("bad length"); - + count = 0; if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); - + count = 0; CORD_set_pos(p, x, 64*1024-1); while(CORD_pos_valid(p)) { - (void) test_fn(CORD_pos_fetch(p), (void *)13); - CORD_next(p); + (void) test_fn(CORD_pos_fetch(p), (void *)13); + CORD_next(p); } if (count != 64*1024 + 2) ABORT("Position based iteration failed"); - + y = CORD_substr(x, 1023, 5); + if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result"); - + y = CORD_substr(x, 1024, 8); + if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "abababab") != 0) ABORT("bad CORD_substr result"); - + y = CORD_substr(x, 128*1024-1, 8); + if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "bc") != 0) ABORT("bad CORD_substr result"); - + x = CORD_balance(x); if (CORD_len(x) != 128*1024+1) ABORT("bad length"); - + count = 0; if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); - + y = CORD_substr(x, 1023, 5); + if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result"); y = CORD_from_fn(id_cord_fn, 0, 13); @@ -109,23 +113,23 @@ void test_basics() CORD_set_pos(p, y, i); while(CORD_pos_valid(p)) { c = CORD_pos_fetch(p); - if(c != i) ABORT("Traversal of function node failed"); - CORD_next(p); i++; + if(c != i) ABORT("Traversal of function node failed"); + CORD_next(p); i++; } if (i != 13) ABORT("Bad apparent length for function node"); } -void test_extras() +void test_extras(void) { # if defined(__OS2__) || defined(__DJGPP__) -# define FNAME1 "tmp1" -# define FNAME2 "tmp2" +# define FNAME1 "tmp1" +# define FNAME2 "tmp2" # elif defined(AMIGA) -# define FNAME1 "T:tmp1" -# define FNAME2 "T:tmp2" +# define FNAME1 "T:tmp1" +# define FNAME2 "T:tmp2" # else -# define FNAME1 "/tmp/cord_test" -# define FNAME2 "/tmp/cord_test2" +# define FNAME1 "/tmp/cord_test" +# define FNAME2 "/tmp/cord_test2" # endif register int i; CORD y = "abcdefghijklmnopqrstuvwxyz0123456789"; @@ -133,7 +137,7 @@ void test_extras() CORD w, z; FILE *f; FILE *f1a, *f1b, *f2; - + w = CORD_cat(CORD_cat(y,y),y); z = CORD_catn(3,y,y,y); if (CORD_cmp(w,z) != 0) ABORT("CORD_catn comparison wrong"); @@ -148,12 +152,16 @@ void test_extras() if ((f = fopen(FNAME1, "w")) == 0) ABORT("open failed"); if (CORD_put(z,f) == EOF) ABORT("CORD_put failed"); if (fclose(f) == EOF) ABORT("fclose failed"); - w = CORD_from_file(f1a = fopen(FNAME1, "rb")); + f1a = fopen(FNAME1, "rb"); + if (!f1a) ABORT("Unable to open " FNAME1); + w = CORD_from_file(f1a); if (CORD_len(w) != CORD_len(z)) ABORT("file length wrong"); if (CORD_cmp(w,z) != 0) ABORT("file comparison wrong"); if (CORD_cmp(CORD_substr(w, 50*36+2, 36), y) != 0) - ABORT("file substr wrong"); - z = CORD_from_file_lazy(f1b = fopen(FNAME1, "rb")); + ABORT("file substr wrong"); + f1b = fopen(FNAME1, "rb"); + if (!f1b) ABORT("2nd open failed: " FNAME1); + z = CORD_from_file_lazy(f1b); if (CORD_cmp(w,z) != 0) ABORT("File conversions differ"); if (CORD_chr(w, 0, '9') != 37) ABORT("CORD_chr failed 1"); if (CORD_chr(w, 3, 'a') != 38) ABORT("CORD_chr failed 2"); @@ -169,46 +177,48 @@ void test_extras() # endif if (CORD_put(x,f) == EOF) ABORT("CORD_put failed"); if (fclose(f) == EOF) ABORT("fclose failed"); - w = CORD_from_file(f2 = fopen(FNAME2, "rb")); + f2 = fopen(FNAME2, "rb"); + if (!f2) ABORT("Unable to open " FNAME2); + w = CORD_from_file(f2); if (CORD_len(w) != CORD_len(x)) ABORT("file length wrong"); if (CORD_cmp(w,x) != 0) ABORT("file comparison wrong"); if (CORD_cmp(CORD_substr(w, 1000*36, 36), y) != 0) - ABORT("file substr wrong"); + ABORT("file substr wrong"); if (strcmp(CORD_to_char_star(CORD_substr(w, 1000*36, 36)), y) != 0) - ABORT("char * file substr wrong"); + ABORT("char * file substr wrong"); if (strcmp(CORD_substr(w, 1000*36, 2), "ab") != 0) - ABORT("short file substr wrong"); + ABORT("short file substr wrong"); if (CORD_str(x,1,"9a") != 35) ABORT("CORD_str failed 1"); if (CORD_str(x,0,"9abcdefghijk") != 35) ABORT("CORD_str failed 2"); if (CORD_str(x,0,"9abcdefghijx") != CORD_NOT_FOUND) - ABORT("CORD_str failed 3"); + ABORT("CORD_str failed 3"); if (CORD_str(x,0,"9>") != CORD_NOT_FOUND) ABORT("CORD_str failed 4"); if (remove(FNAME1) != 0) { - /* On some systems, e.g. OS2, this may fail if f1 is still open. */ - if ((fclose(f1a) == EOF) & (fclose(f1b) == EOF)) - ABORT("fclose(f1) failed"); - if (remove(FNAME1) != 0) ABORT("remove 1 failed"); + /* On some systems, e.g. OS2, this may fail if f1 is still open. */ + if ((fclose(f1a) == EOF) & (fclose(f1b) == EOF)) + ABORT("fclose(f1) failed"); + if (remove(FNAME1) != 0) ABORT("remove 1 failed"); } if (remove(FNAME2) != 0) { - if (fclose(f2) == EOF) ABORT("fclose(f2) failed"); - if (remove(FNAME2) != 0) ABORT("remove 2 failed"); + if (fclose(f2) == EOF) ABORT("fclose(f2) failed"); + if (remove(FNAME2) != 0) ABORT("remove 2 failed"); } } -void test_printf() +void test_printf(void) { CORD result; char result2[200]; long l; short s; CORD x; - + if (CORD_sprintf(&result, "%7.2f%ln", 3.14159F, &l) != 7) - ABORT("CORD_sprintf failed 1"); + ABORT("CORD_sprintf failed 1"); if (CORD_cmp(result, " 3.14") != 0)ABORT("CORD_sprintf goofed 1"); if (l != 7) ABORT("CORD_sprintf goofed 2"); if (CORD_sprintf(&result, "%-7.2s%hn%c%s", "abcd", &s, 'x', "yz") != 10) - ABORT("CORD_sprintf failed 2"); + ABORT("CORD_sprintf failed 2"); if (CORD_cmp(result, "ab xyz") != 0)ABORT("CORD_sprintf goofed 3"); if (s != 7) ABORT("CORD_sprintf goofed 4"); x = "abcdefghij"; @@ -216,12 +226,12 @@ void test_printf() x = CORD_cat(x,x); x = CORD_cat(x,x); if (CORD_sprintf(&result, "->%-120.78r!\n", x) != 124) - ABORT("CORD_sprintf failed 3"); + ABORT("CORD_sprintf failed 3"); (void) sprintf(result2, "->%-120.78s!\n", CORD_to_char_star(x)); if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5"); } -int main() +int main(void) { # ifdef THINK_C printf("cordtest:\n"); diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index eb40fdcd..daf2069c 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -431,7 +431,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define DebugBreak() _exit(-1) /* there is no abort() in WinCE */ # endif # ifdef SMALL_CONFIG -# if defined(MSWIN32) || defined(MSWINCE) +# if (defined(MSWIN32) && !defined(LINT2)) || defined(MSWINCE) # define ABORT(msg) DebugBreak() # else # define ABORT(msg) abort() diff --git a/tests/test.c b/tests/test.c index c486714a..809853c2 100644 --- a/tests/test.c +++ b/tests/test.c @@ -81,16 +81,30 @@ # include +#define CHECH_GCLIB_VERSION \ + if (GC_get_version() != ((GC_VERSION_MAJOR<<16) \ + | (GC_VERSION_MINOR<<8) \ + | GC_ALPHA_VERSION)) { \ + GC_printf("libgc version mismatch\n"); \ + exit(1); \ + } + /* Call GC_INIT only on platforms on which we think we really need it, */ /* so that we can test automatic initialization on the rest. */ #if defined(CYGWIN32) || defined (AIX) || defined(DARWIN) \ || defined(THREAD_LOCAL_ALLOC) \ || (defined(MSWINCE) && !defined(GC_WINMAIN_REDIRECT)) -# define GC_COND_INIT() GC_INIT() +# define GC_COND_INIT() GC_INIT(); CHECH_GCLIB_VERSION #else -# define GC_COND_INIT() +# define GC_COND_INIT() CHECH_GCLIB_VERSION #endif +#define CHECK_OUT_OF_MEMORY(p) \ + if ((p) == NULL) { \ + GC_printf("Out of memory\n"); \ + exit(1); \ + } + /* Allocation Statistics. Incremented without synchronization. */ /* FIXME: We should be using synchronization. */ int stubborn_count = 0; @@ -139,7 +153,7 @@ int realloc_count = 0; #else /* !AMIGA_FASTALLOC */ -# ifdef PCR +# if defined(PCR) || defined(LINT2) # define FAIL (void)abort() # else # define FAIL ABORT("Test failed") @@ -186,10 +200,7 @@ sexpr cons (sexpr x, sexpr y) stubborn_count++; r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra); - if (r == 0) { - GC_printf("Out of memory\n"); - exit(1); - } + CHECK_OUT_OF_MEMORY(r); for (p = (int *)r; ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) { if (*p) { @@ -262,10 +273,7 @@ sexpr small_cons (sexpr x, sexpr y) collectable_count++; r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); - if (r == 0) { - GC_printf("Out of memory\n"); - exit(1); - } + CHECK_OUT_OF_MEMORY(r); r -> sexpr_car = x; r -> sexpr_cdr = y; return(r); @@ -277,10 +285,7 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) uncollectable_count++; r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); - if (r == 0) { - GC_printf("Out of memory\n"); - exit(1); - } + CHECK_OUT_OF_MEMORY(r); r -> sexpr_car = x; r -> sexpr_cdr = (sexpr)(~(GC_word)y); return(r); @@ -297,10 +302,7 @@ sexpr gcj_cons(sexpr x, sexpr y) r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR) + sizeof(struct fake_vtable*), &gcj_class_struct2); - if (r == 0) { - GC_printf("Out of memory\n"); - exit(1); - } + CHECK_OUT_OF_MEMORY(r); result = (sexpr)(r + 1); result -> sexpr_car = x; result -> sexpr_cdr = y; @@ -562,16 +564,19 @@ void *GC_CALLBACK reverse_test_inner(void *data) f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr)); realloc_count++; f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr)); + CHECK_OUT_OF_MEMORY(f); f[5] = ints(1,17); collectable_count++; g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr)); realloc_count++; g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr)); + CHECK_OUT_OF_MEMORY(g); g[799] = ints(1,18); collectable_count++; h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr)); realloc_count++; h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr)); + CHECK_OUT_OF_MEMORY(h); # ifdef GC_GCJ_SUPPORT h[1999] = gcj_ints(1,200); for (i = 0; i < 51; ++i) @@ -709,19 +714,14 @@ tn * mktree(int n) collectable_count++; # if defined(MACOS) /* get around static data limitations. */ - if (!live_indicators) - live_indicators = - (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word)); if (!live_indicators) { - GC_printf("Out of memory\n"); - exit(1); + live_indicators = + (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word)); + CHECK_OUT_OF_MEMORY(live_indicators); } # endif if (n == 0) return(0); - if (result == 0) { - GC_printf("Out of memory\n"); - exit(1); - } + CHECK_OUT_OF_MEMORY(result); result -> level = n; result -> lchild = mktree(n-1); result -> rchild = mktree(n-1); @@ -827,6 +827,7 @@ void * alloc8bytes(void) if (my_free_list_ptr == 0) { uncollectable_count++; my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *); + CHECK_OUT_OF_MEMORY(my_free_list_ptr); if (pthread_setspecific(fl_key, my_free_list_ptr) != 0) { GC_printf("pthread_setspecific failed\n"); FAIL; @@ -835,10 +836,7 @@ void * alloc8bytes(void) my_free_list = *my_free_list_ptr; if (my_free_list == 0) { my_free_list = GC_malloc_many(8); - if (my_free_list == 0) { - GC_printf("alloc8bytes out of memory\n"); - FAIL; - } + CHECK_OUT_OF_MEMORY(my_free_list); } *my_free_list_ptr = GC_NEXT(my_free_list); GC_NEXT(my_free_list) = 0; @@ -942,6 +940,7 @@ void typed_test(void) for (i = 0; i < 4000; i++) { collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1); + CHECK_OUT_OF_MEMORY(new); if (0 != new[0] || 0 != new[1]) { GC_printf("Bad initialization by GC_malloc_explicitly_typed\n"); FAIL; @@ -951,17 +950,20 @@ void typed_test(void) old = new; collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2); + CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; old = new; collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3); + CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; old = new; collectable_count++; new = (GC_word *) GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word), d1); + CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; old = new; @@ -973,11 +975,12 @@ void typed_test(void) new = (GC_word *) GC_calloc_explicitly_typed(1001, 3 * sizeof(GC_word), d2); - if (0 != new[0] || 0 != new[1]) { + if (new && (0 != new[0] || 0 != new[1])) { GC_printf("Bad initialization by GC_malloc_explicitly_typed\n"); FAIL; } } + CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; old = new; @@ -1151,8 +1154,14 @@ void run_one_test(void) # endif /* DBG_HDRS_ALL */ /* Test floating point alignment */ collectable_count += 2; - *(double *)GC_MALLOC(sizeof(double)) = 1.0; - *(double *)GC_MALLOC(sizeof(double)) = 1.0; + { + double *dp = GC_MALLOC(sizeof(double)); + CHECK_OUT_OF_MEMORY(dp); + *dp = 1.0; + dp = GC_MALLOC(sizeof(double)); + CHECK_OUT_OF_MEMORY(dp); + *dp = 1.0; + } /* Test size 0 allocation a bit more */ { size_t i; diff --git a/win32_threads.c b/win32_threads.c index 47dc39c1..0c841107 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -529,11 +529,19 @@ STATIC GC_thread GC_lookup_thread_inner(DWORD thread_id) } } +#ifdef LINT2 +# define CHECK_LOOKUP_MY_THREAD(me) \ + if (!(me)) ABORT("GC_lookup_thread_inner(GetCurrentThreadId) failed") +#else +# define CHECK_LOOKUP_MY_THREAD(me) /* empty */ +#endif + /* Called by GC_finalize() (in case of an allocation failure observed). */ /* GC_reset_finalizer_nested() is the same as in pthread_support.c. */ GC_INNER void GC_reset_finalizer_nested(void) { GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId()); + CHECK_LOOKUP_MY_THREAD(me); me->finalizer_nested = 0; } @@ -546,7 +554,9 @@ GC_INNER void GC_reset_finalizer_nested(void) GC_INNER unsigned char *GC_check_finalizer_nested(void) { GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId()); - unsigned nesting_level = me->finalizer_nested; + unsigned nesting_level; + CHECK_LOOKUP_MY_THREAD(me); + nesting_level = me->finalizer_nested; if (nesting_level) { /* We are inside another GC_invoke_finalizers(). */ /* Skip some implicitly-called GC_invoke_finalizers() */ @@ -765,6 +775,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) LOCK(); # if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS) me = GC_lookup_thread_inner(thread_id); + CHECK_LOOKUP_MY_THREAD(me); GC_ASSERT(!KNOWN_FINISHED(me)); # endif # if defined(THREAD_LOCAL_ALLOC) @@ -800,6 +811,7 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) LOCK(); me = GC_lookup_thread_inner(thread_id); + CHECK_LOOKUP_MY_THREAD(me); GC_ASSERT(me -> thread_blocked_sp == NULL); # ifdef IA64 me -> backing_store_ptr = stack_ptr; @@ -826,7 +838,7 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, LOCK(); /* This will block if the world is stopped. */ me = GC_lookup_thread_inner(GetCurrentThreadId()); - + CHECK_LOOKUP_MY_THREAD(me); /* Adjust our stack base value (this could happen unless */ /* GC_get_stack_base() was used which returned GC_SUCCESS). */ GC_ASSERT(me -> stack_base != NULL); @@ -1462,7 +1474,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, return; } - GC_ASSERT(current_min > start); + GC_ASSERT(current_min > start && plast_stack_min != NULL); # ifdef MSWINCE if (GC_dont_query_stack_min) { *lo = GC_wince_evaluate_stack_min(current_min); @@ -2633,6 +2645,7 @@ GC_INNER void GC_thr_init(void) GC_INNER void GC_init_parallel(void) { # if defined(THREAD_LOCAL_ALLOC) + GC_thread me; DCL_LOCK_STATE; # endif @@ -2651,8 +2664,9 @@ GC_INNER void GC_init_parallel(void) /* Initialize thread local free lists if used. */ # if defined(THREAD_LOCAL_ALLOC) LOCK(); - GC_init_thread_local( - &GC_lookup_thread_inner(GetCurrentThreadId())->tlfs); + me = GC_lookup_thread_inner(GetCurrentThreadId()); + CHECK_LOOKUP_MY_THREAD(me); + GC_init_thread_local(&me->tlfs); UNLOCK(); # endif } -- cgit v1.2.1 From d57c457306c7673f73a04d9cfef56ed14c0d98e3 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 4 Jul 2011 13:29:55 +0000 Subject: 2011-07-04 Ivan Maidanski (mostly really Andy Wingo) * configure.ac (GC_THREADS): Refine the comment. * configure.ac (GC_WIN32_PTHREADS): Add template. * configure.ac (cygwin, win32): Define GC_WIN32_THREADS instead of GC_THREADS. * configure.ac (pthreads): Add mingw target (GC_WIN32_PTHREADS). * configure: Regenerate. * include/private/config.h.in: Ditto. * include/private/gc_locks.h (GC_WIN32_PTHREADS): Remove nested test for the macro; add comment. --HG-- branch : bdwgc --- ChangeLog | 12 ++++++++++++ configure | 24 +++++++++++++++++++----- configure.ac | 24 ++++++++++++++++++------ include/private/config.h.in | 7 +++++-- include/private/gc_locks.h | 23 +++++++++-------------- 5 files changed, 63 insertions(+), 27 deletions(-) mode change 100755 => 100644 include/private/config.h.in diff --git a/ChangeLog b/ChangeLog index c85fb3b0..d0c9bab8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-07-04 Ivan Maidanski (mostly really Andy Wingo) + + * configure.ac (GC_THREADS): Refine the comment. + * configure.ac (GC_WIN32_PTHREADS): Add template. + * configure.ac (cygwin, win32): Define GC_WIN32_THREADS instead of + GC_THREADS. + * configure.ac (pthreads): Add mingw target (GC_WIN32_PTHREADS). + * configure: Regenerate. + * include/private/config.h.in: Ditto. + * include/private/gc_locks.h (GC_WIN32_PTHREADS): Remove nested + test for the macro; add comment. + 2011-07-01 Ivan Maidanski * win32_threads.c (CHECK_LOOKUP_MY_THREAD): New macro definition. diff --git a/configure b/configure index 102c4e93..486a8e71 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 1.67 . +# From configure.ac Revision: 1.68 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for gc 7.2alpha7. # @@ -4964,6 +4964,7 @@ fi + @@ -5062,7 +5063,8 @@ if test "x$ac_cv_lib_pthread_pthread_self" = xyes; then : fi case "$host" in - x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*) + x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* \ + | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*) $as_echo "#define GC_LINUX_THREADS 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h @@ -5178,7 +5180,7 @@ $as_echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;} ;; *-*-cygwin*) - $as_echo "#define GC_THREADS 1" >>confdefs.h + $as_echo "#define GC_WIN32_THREADS 1" >>confdefs.h if test "${enable_parallel_mark}" = yes; then $as_echo "#define PARALLEL_MARK 1" >>confdefs.h @@ -5191,6 +5193,18 @@ $as_echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;} THREADDLLIBS="" win32_threads=true ;; + *-*-mingw*) + $as_echo "#define GC_WIN32_PTHREADS 1" >>confdefs.h + + # Using win32-pthreads + if test "${enable_parallel_mark}" = yes; then + $as_echo "#define PARALLEL_MARK 1" >>confdefs.h + + fi + $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h + + THREADDLLIBS="-lpthread" + ;; *-*-darwin*) $as_echo "#define GC_DARWIN_THREADS 1" >>confdefs.h @@ -5235,7 +5249,7 @@ $as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; esac ;; win32) - $as_echo "#define GC_THREADS 1" >>confdefs.h + $as_echo "#define GC_WIN32_THREADS 1" >>confdefs.h if test "${enable_parallel_mark}" = yes; then $as_echo "#define PARALLEL_MARK 1" >>confdefs.h @@ -5252,7 +5266,7 @@ $as_echo "#define EMPTY_GETENV_RESULTS 1" >>confdefs.h THREADS=dgux386 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $THREADDLLIBS" >&5 $as_echo "$THREADDLLIBS" >&6; } - # Use pthread GCC switch + # Use pthread GCC switch THREADDLLIBS=-pthread if test "${enable_parallel_mark}" = yes; then $as_echo "#define PARALLEL_MARK 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 81899cff..f66ce6bd 100644 --- a/configure.ac +++ b/configure.ac @@ -78,7 +78,8 @@ AH_TEMPLATE([USE_COMPILER_TLS], [Define to use of compiler-support for thread-local variables.]) dnl Thread selection macros. -AH_TEMPLATE([GC_THREADS], [Define to support threads.]) +AH_TEMPLATE([GC_THREADS], [Define to support platform-specific \ + threads.]) AH_TEMPLATE([GC_AIX_THREADS], [Define to support IBM AIX threads.]) AH_TEMPLATE([GC_DARWIN_THREADS], [Define to support Darwin pthreads.]) AH_TEMPLATE([GC_FREEBSD_THREADS], [Define to support FreeBSD pthreads.]) @@ -90,7 +91,8 @@ AH_TEMPLATE([GC_NETBSD_THREADS], [Define to support NetBSD pthreads.]) AH_TEMPLATE([GC_OPENBSD_THREADS], [Define to support OpenBSD pthreads.]) AH_TEMPLATE([GC_OSF1_THREADS], [Define to support Tru64 pthreads.]) AH_TEMPLATE([GC_SOLARIS_THREADS], [Define to support Solaris pthreads.]) -AH_TEMPLATE([GC_WIN32_THREADS], [Define to support win32 threads.]) +AH_TEMPLATE([GC_WIN32_THREADS], [Define to support Win32 threads.]) +AH_TEMPLATE([GC_WIN32_PTHREADS], [Define to support win32-pthreads.]) dnl System header feature requests. AH_TEMPLATE([_POSIX_C_SOURCE], [The POSIX feature macro.]) @@ -110,7 +112,8 @@ case "$THREADS" in THREADS=posix AC_CHECK_LIB(pthread, pthread_self, THREADDLLIBS="-lpthread",,) case "$host" in - x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*) + x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* \ + | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*) AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(_REENTRANT) if test "${enable_parallel_mark}" = yes; then @@ -190,7 +193,7 @@ case "$THREADS" in AC_DEFINE(GC_IRIX_THREADS) ;; *-*-cygwin*) - AC_DEFINE(GC_THREADS) + AC_DEFINE(GC_WIN32_THREADS) if test "${enable_parallel_mark}" = yes; then AC_DEFINE(PARALLEL_MARK) fi @@ -200,6 +203,15 @@ case "$THREADS" in THREADDLLIBS="" win32_threads=true ;; + *-*-mingw*) + AC_DEFINE(GC_WIN32_PTHREADS) + # Using win32-pthreads + if test "${enable_parallel_mark}" = yes; then + AC_DEFINE(PARALLEL_MARK) + fi + AC_DEFINE(THREAD_LOCAL_ALLOC) + THREADDLLIBS="-lpthread" + ;; *-*-darwin*) AC_DEFINE(GC_DARWIN_THREADS) AC_DEFINE(THREAD_LOCAL_ALLOC) @@ -236,7 +248,7 @@ case "$THREADS" in esac ;; win32) - AC_DEFINE(GC_THREADS) + AC_DEFINE(GC_WIN32_THREADS) if test "${enable_parallel_mark}" = yes; then AC_DEFINE(PARALLEL_MARK) AC_DEFINE(THREAD_LOCAL_ALLOC) @@ -248,7 +260,7 @@ case "$THREADS" in dgux386) THREADS=dgux386 AC_MSG_RESULT($THREADDLLIBS) - # Use pthread GCC switch + # Use pthread GCC switch THREADDLLIBS=-pthread if test "${enable_parallel_mark}" = yes; then AC_DEFINE(PARALLEL_MARK) diff --git a/include/private/config.h.in b/include/private/config.h.in old mode 100755 new mode 100644 index 6af87d14..a14c0f34 --- a/include/private/config.h.in +++ b/include/private/config.h.in @@ -69,7 +69,7 @@ /* Define to support Solaris pthreads. */ #undef GC_SOLARIS_THREADS -/* Define to support threads. */ +/* Define to support platform-specific threads. */ #undef GC_THREADS /* See doc/README.macros. */ @@ -81,7 +81,10 @@ /* The minor version number of this GC release. */ #undef GC_VERSION_MINOR -/* Define to support win32 threads. */ +/* Define to support win32-pthreads. */ +#undef GC_WIN32_PTHREADS + +/* Define to support Win32 threads. */ #undef GC_WIN32_THREADS /* Define to 1 if you have the header file. */ diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h index b38384cf..113b4aea 100644 --- a/include/private/gc_locks.h +++ b/include/private/gc_locks.h @@ -99,20 +99,15 @@ # define THREAD_EQUAL(id1, id2) ((id1) == (id2)) # define NUMERIC_THREAD_ID_UNIQUE # else -# if defined(GC_WIN32_PTHREADS) -# define NUMERIC_THREAD_ID(id) ((unsigned long)(id.p)) - /* Using documented internal details of win32_pthread library. */ - /* Faster than pthread_equal(). Should not change with */ - /* future versions of win32_pthread library. */ -# define THREAD_EQUAL(id1, id2) ((id1.p == id2.p) && (id1.x == id2.x)) -# undef NUMERIC_THREAD_ID_UNIQUE -# else - /* Generic definitions that always work, but will result in */ - /* poor performance and weak assertion checking. */ -# define NUMERIC_THREAD_ID(id) 1l -# define THREAD_EQUAL(id1, id2) pthread_equal(id1, id2) -# undef NUMERIC_THREAD_ID_UNIQUE -# endif +# define NUMERIC_THREAD_ID(id) ((unsigned long)(id.p)) + /* Using documented internal details of win32-pthread library. */ + /* Faster than pthread_equal(). Should not change with */ + /* future versions of win32-pthread library. */ +# define THREAD_EQUAL(id1, id2) ((id1.p == id2.p) && (id1.x == id2.x)) +# undef NUMERIC_THREAD_ID_UNIQUE + /* Generic definitions based on pthread_equal() always work but */ + /* will result in poor performance (as NUMERIC_THREAD_ID is */ + /* defined to just a constant) and weak assertion checking. */ # endif # define NO_THREAD ((unsigned long)(-1l)) /* != NUMERIC_THREAD_ID(pthread_self()) for any thread */ -- cgit v1.2.1 From 74c25bba2bb94f7747329d7119e5d854c685aea8 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 4 Jul 2011 14:56:16 +0000 Subject: 2011-07-04 Ivan Maidanski * include/private/gcconfig.h (etext): Don't define if unused (NetBSD). * include/private/gcconfig.h (GC_data_start, DATASTART): Define for NetBSD/amd64 if ELF. * include/private/gcconfig.h (SEARCH_FOR_DATA_START): Don't define for NetBSD/amd64 if ELF. --HG-- branch : bdwgc --- ChangeLog | 9 +++++++++ include/private/gcconfig.h | 10 +++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index d0c9bab8..112d7de6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-07-04 Ivan Maidanski + + * include/private/gcconfig.h (etext): Don't define if unused + (NetBSD). + * include/private/gcconfig.h (GC_data_start, DATASTART): Define + for NetBSD/amd64 if ELF. + * include/private/gcconfig.h (SEARCH_FOR_DATA_START): Don't define + for NetBSD/amd64 if ELF. + 2011-07-04 Ivan Maidanski (mostly really Andy Wingo) * configure.ac (GC_THREADS): Refine the comment. diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index d1695d92..a3600f11 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -878,7 +878,6 @@ # define ALIGNMENT 4 # define OS_TYPE "NETBSD" # define HEURISTIC2 - extern char etext[]; extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING @@ -1529,7 +1528,6 @@ # define ALIGNMENT 4 # define HEURISTIC2 # ifdef __ELF__ - extern int etext[]; extern ptr_t GC_data_start; # define DATASTART GC_data_start # define NEED_FIND_LIMIT @@ -2171,12 +2169,14 @@ # endif # ifdef NETBSD # define OS_TYPE "NETBSD" +# define HEURISTIC2 # ifdef __ELF__ + extern ptr_t GC_data_start; +# define DATASTART GC_data_start # define DYNAMIC_LOADING +# else +# define SEARCH_FOR_DATA_START # endif -# define HEURISTIC2 - extern char etext[]; -# define SEARCH_FOR_DATA_START # endif # ifdef SOLARIS # define OS_TYPE "SOLARIS" -- cgit v1.2.1 From fbb8881c0d8d17cf7e985ded43e02c74841e8079 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 5 Jul 2011 13:50:09 +0000 Subject: 2011-07-05 Ivan Maidanski * dyn_load.c (GC_register_dynamic_libraries): Remove duplicate call of GC_FirstDLOpenedLinkMap (twice). * dyn_load.c (GC_register_main_static_data): Add comment. * cord/cordbscs.c (CORD_riter): Check for empty string passed (do not call CORD_riter4 if CORD_len() returned zero). * cord/cordbscs.c (CORD_init_min_len): Replace the K&R-style function definition with the ANSI C one. * cord/cordbscs.c: Expand all tabs to spaces; remove trailing spaces at EOLn. * tests/threadkey_test.c (on_thread_exit_inner): Check GC_pthread_create() result. --HG-- branch : bdwgc --- ChangeLog | 14 + cord/cordbscs.c | 718 +++++++++++++++++++++++++------------------------ dyn_load.c | 8 +- tests/threadkey_test.c | 7 +- 4 files changed, 382 insertions(+), 365 deletions(-) diff --git a/ChangeLog b/ChangeLog index 112d7de6..34085005 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-05 Ivan Maidanski + + * dyn_load.c (GC_register_dynamic_libraries): Remove duplicate + call of GC_FirstDLOpenedLinkMap (twice). + * dyn_load.c (GC_register_main_static_data): Add comment. + * cord/cordbscs.c (CORD_riter): Check for empty string passed (do + not call CORD_riter4 if CORD_len() returned zero). + * cord/cordbscs.c (CORD_init_min_len): Replace the K&R-style + function definition with the ANSI C one. + * cord/cordbscs.c: Expand all tabs to spaces; remove + trailing spaces at EOLn. + * tests/threadkey_test.c (on_thread_exit_inner): Check + GC_pthread_create() result. + 2011-07-04 Ivan Maidanski * include/private/gcconfig.h (etext): Don't define if unused diff --git a/cord/cordbscs.c b/cord/cordbscs.c index d83f4067..924bf445 100644 --- a/cord/cordbscs.c +++ b/cord/cordbscs.c @@ -19,64 +19,64 @@ # include # include -/* An implementation of the cord primitives. These are the only */ -/* Functions that understand the representation. We perform only */ -/* minimal checks on arguments to these functions. Out of bounds */ -/* arguments to the iteration functions may result in client functions */ -/* invoked on garbage data. In most cases, client functions should be */ -/* programmed defensively enough that this does not result in memory */ -/* smashes. */ +/* An implementation of the cord primitives. These are the only */ +/* Functions that understand the representation. We perform only */ +/* minimal checks on arguments to these functions. Out of bounds */ +/* arguments to the iteration functions may result in client functions */ +/* invoked on garbage data. In most cases, client functions should be */ +/* programmed defensively enough that this does not result in memory */ +/* smashes. */ typedef void (* oom_fn)(void); oom_fn CORD_oom_fn = (oom_fn) 0; # define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \ - ABORT("Out of memory\n"); } + ABORT("Out of memory\n"); } # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); } typedef unsigned long word; typedef union { struct Concatenation { - char null; - char header; - char depth; /* concatenation nesting depth. */ - unsigned char left_len; - /* Length of left child if it is sufficiently */ - /* short; 0 otherwise. */ -# define MAX_LEFT_LEN 255 - word len; - CORD left; /* length(left) > 0 */ - CORD right; /* length(right) > 0 */ + char null; + char header; + char depth; /* concatenation nesting depth. */ + unsigned char left_len; + /* Length of left child if it is sufficiently */ + /* short; 0 otherwise. */ +# define MAX_LEFT_LEN 255 + word len; + CORD left; /* length(left) > 0 */ + CORD right; /* length(right) > 0 */ } concatenation; struct Function { - char null; - char header; - char depth; /* always 0 */ - char left_len; /* always 0 */ - word len; - CORD_fn fn; - void * client_data; + char null; + char header; + char depth; /* always 0 */ + char left_len; /* always 0 */ + word len; + CORD_fn fn; + void * client_data; } function; struct Generic { - char null; - char header; - char depth; - char left_len; - word len; + char null; + char header; + char depth; + char left_len; + word len; } generic; char string[1]; } CordRep; # define CONCAT_HDR 1 - + # define FN_HDR 4 # define SUBSTR_HDR 6 - /* Substring nodes are a special case of function nodes. */ - /* The client_data field is known to point to a substr_args */ - /* structure, and the function is either CORD_apply_access_fn */ - /* or CORD_index_access_fn. */ + /* Substring nodes are a special case of function nodes. */ + /* The client_data field is known to point to a substr_args */ + /* structure, and the function is either CORD_apply_access_fn */ + /* or CORD_index_access_fn. */ /* The following may be applied only to function and concatenation nodes: */ #define IS_CONCATENATION(s) (((CordRep *)s)->generic.header == CONCAT_HDR) @@ -90,26 +90,26 @@ typedef union { #define GEN_LEN(s) (CORD_IS_STRING(s) ? strlen(s) : LEN(s)) #define LEFT_LEN(c) ((c) -> left_len != 0? \ - (c) -> left_len \ - : (CORD_IS_STRING((c) -> left) ? \ - (c) -> len - GEN_LEN((c) -> right) \ - : LEN((c) -> left))) + (c) -> left_len \ + : (CORD_IS_STRING((c) -> left) ? \ + (c) -> len - GEN_LEN((c) -> right) \ + : LEN((c) -> left))) #define SHORT_LIMIT (sizeof(CordRep) - 1) - /* Cords shorter than this are C strings */ + /* Cords shorter than this are C strings */ -/* Dump the internal representation of x to stdout, with initial */ -/* indentation level n. */ +/* Dump the internal representation of x to stdout, with initial */ +/* indentation level n. */ void CORD_dump_inner(CORD x, unsigned n) { register size_t i; - + for (i = 0; i < (size_t)n; i++) { fputs(" ", stdout); } if (x == 0) { - fputs("NIL\n", stdout); + fputs("NIL\n", stdout); } else if (CORD_IS_STRING(x)) { for (i = 0; i <= SHORT_LIMIT; i++) { if (x[i] == '\0') break; @@ -119,14 +119,14 @@ void CORD_dump_inner(CORD x, unsigned n) putchar('\n'); } else if (IS_CONCATENATION(x)) { register struct Concatenation * conc = - &(((CordRep *)x) -> concatenation); + &(((CordRep *)x) -> concatenation); printf("Concatenation: %p (len: %d, depth: %d)\n", x, (int)(conc -> len), (int)(conc -> depth)); CORD_dump_inner(conc -> left, n+1); CORD_dump_inner(conc -> right, n+1); } else /* function */{ register struct Function * func = - &(((CordRep *)x) -> function); + &(((CordRep *)x) -> function); if (IS_SUBSTR(x)) printf("(Substring) "); printf("Function: %p (len: %d): ", x, (int)(func -> len)); for (i = 0; i < 20 && i < func -> len; i++) { @@ -137,7 +137,7 @@ void CORD_dump_inner(CORD x, unsigned n) } } -/* Dump the internal representation of x to stdout */ +/* Dump the internal representation of x to stdout */ void CORD_dump(CORD x) { CORD_dump_inner(x, 0); @@ -149,7 +149,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) register size_t result_len; register size_t lenx; register int depth; - + if (x == CORD_EMPTY) return(y); if (leny == 0) return(x); if (CORD_IS_STRING(x)) { @@ -157,7 +157,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) result_len = lenx + leny; if (result_len <= SHORT_LIMIT) { register char * result = GC_MALLOC_ATOMIC(result_len+1); - + if (result == 0) OUT_OF_MEMORY; memcpy(result, x, lenx); memcpy(result + lenx, y, leny); @@ -167,35 +167,35 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) depth = 1; } } else { - register CORD right; - register CORD left; - register char * new_right; - register size_t right_len; - - lenx = LEN(x); - + register CORD right; + register CORD left; + register char * new_right; + register size_t right_len; + + lenx = LEN(x); + if (leny <= SHORT_LIMIT/2 - && IS_CONCATENATION(x) + && IS_CONCATENATION(x) && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) { /* Merge y into right part of x. */ if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) { - right_len = lenx - LEN(left); + right_len = lenx - LEN(left); } else if (((CordRep *)x) -> concatenation.left_len != 0) { right_len = lenx - ((CordRep *)x) -> concatenation.left_len; } else { - right_len = strlen(right); + right_len = strlen(right); } result_len = right_len + leny; /* length of new_right */ if (result_len <= SHORT_LIMIT) { - new_right = GC_MALLOC_ATOMIC(result_len + 1); - memcpy(new_right, right, right_len); - memcpy(new_right + right_len, y, leny); - new_right[result_len] = '\0'; - y = new_right; - leny = result_len; - x = left; - lenx -= right_len; - /* Now fall through to concatenate the two pieces: */ + new_right = GC_MALLOC_ATOMIC(result_len + 1); + memcpy(new_right, right, right_len); + memcpy(new_right + right_len, y, leny); + new_right[result_len] = '\0'; + y = new_right; + leny = result_len; + x = left; + lenx -= right_len; + /* Now fall through to concatenate the two pieces: */ } if (CORD_IS_STRING(x)) { depth = 1; @@ -209,21 +209,21 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) } { /* The general case; lenx, result_len is known: */ - register struct Concatenation * result; - - result = GC_NEW(struct Concatenation); - if (result == 0) OUT_OF_MEMORY; - result->header = CONCAT_HDR; - result->depth = depth; - if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; - result->len = result_len; - result->left = x; - result->right = y; - if (depth >= MAX_DEPTH) { - return(CORD_balance((CORD)result)); - } else { - return((CORD) result); - } + register struct Concatenation * result; + + result = GC_NEW(struct Concatenation); + if (result == 0) OUT_OF_MEMORY; + result->header = CONCAT_HDR; + result->depth = depth; + if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; + result->len = result_len; + result->left = x; + result->right = y; + if (depth >= MAX_DEPTH) { + return(CORD_balance((CORD)result)); + } else { + return((CORD) result); + } } } @@ -233,7 +233,7 @@ CORD CORD_cat(CORD x, CORD y) register size_t result_len; register int depth; register size_t lenx; - + if (x == CORD_EMPTY) return(y); if (y == CORD_EMPTY) return(x); if (CORD_IS_STRING(y)) { @@ -243,28 +243,28 @@ CORD CORD_cat(CORD x, CORD y) depth = DEPTH(y) + 1; } else { register int depthy = DEPTH(y); - + lenx = LEN(x); depth = DEPTH(x) + 1; if (depthy >= depth) depth = depthy + 1; } result_len = lenx + LEN(y); { - register struct Concatenation * result; - - result = GC_NEW(struct Concatenation); - if (result == 0) OUT_OF_MEMORY; - result->header = CONCAT_HDR; - result->depth = depth; - if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; - result->len = result_len; - result->left = x; - result->right = y; - if (depth >= MAX_DEPTH) { - return(CORD_balance((CORD)result)); - } else { - return((CORD) result); - } + register struct Concatenation * result; + + result = GC_NEW(struct Concatenation); + if (result == 0) OUT_OF_MEMORY; + result->header = CONCAT_HDR; + result->depth = depth; + if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; + result->len = result_len; + result->left = x; + result->right = y; + if (depth >= MAX_DEPTH) { + return(CORD_balance((CORD)result)); + } else { + return((CORD) result); + } } } @@ -278,7 +278,7 @@ CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) register size_t i; char buf[SHORT_LIMIT+1]; register char c; - + for (i = 0; i < len; i++) { c = (*fn)(i, client_data); if (c == '\0') goto gen_case; @@ -293,25 +293,25 @@ CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) } gen_case: { - register struct Function * result; - - result = GC_NEW(struct Function); - if (result == 0) OUT_OF_MEMORY; - result->header = FN_HDR; - /* depth is already 0 */ - result->len = len; - result->fn = fn; - result->client_data = client_data; - return((CORD) result); + register struct Function * result; + + result = GC_NEW(struct Function); + if (result == 0) OUT_OF_MEMORY; + result->header = FN_HDR; + /* depth is already 0 */ + result->len = len; + result->fn = fn; + result->client_data = client_data; + return((CORD) result); } } size_t CORD_len(CORD x) { if (x == 0) { - return(0); + return(0); } else { - return(GEN_LEN(x)); + return(GEN_LEN(x)); } } @@ -323,7 +323,7 @@ struct substr_args { char CORD_index_access_fn(size_t i, void * client_data) { register struct substr_args *descr = (struct substr_args *)client_data; - + return(((char *)(descr->sa_cord))[i + descr->sa_index]); } @@ -331,19 +331,19 @@ char CORD_apply_access_fn(size_t i, void * client_data) { register struct substr_args *descr = (struct substr_args *)client_data; register struct Function * fn_cord = &(descr->sa_cord->function); - + return((*(fn_cord->fn))(i + descr->sa_index, fn_cord->client_data)); } -/* A version of CORD_substr that simply returns a function node, thus */ -/* postponing its work. The fourth argument is a function that may */ -/* be used for efficient access to the ith character. */ -/* Assumes i >= 0 and i + n < length(x). */ +/* A version of CORD_substr that simply returns a function node, thus */ +/* postponing its work. The fourth argument is a function that may */ +/* be used for efficient access to the ith character. */ +/* Assumes i >= 0 and i + n < length(x). */ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f) { register struct substr_args * sa = GC_NEW(struct substr_args); CORD result; - + if (sa == 0) OUT_OF_MEMORY; sa->sa_cord = (CordRep *)x; sa->sa_index = i; @@ -353,9 +353,9 @@ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f) } # define SUBSTR_LIMIT (10 * SHORT_LIMIT) - /* Substrings of function nodes and flat strings shorter than */ - /* this are flat strings. Othewise we use a functional */ - /* representation, which is significantly slower to access. */ + /* Substrings of function nodes and flat strings shorter than */ + /* this are flat strings. Othewise we use a functional */ + /* representation, which is significantly slower to access. */ /* A version of CORD_substr that assumes i >= 0, n > 0, and i + n < length(x).*/ CORD CORD_substr_checked(CORD x, size_t i, size_t n) @@ -365,56 +365,56 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n) return(CORD_substr_closure(x, i, n, CORD_index_access_fn)); } else { register char * result = GC_MALLOC_ATOMIC(n+1); - + if (result == 0) OUT_OF_MEMORY; strncpy(result, x+i, n); result[n] = '\0'; return(result); } } else if (IS_CONCATENATION(x)) { - register struct Concatenation * conc - = &(((CordRep *)x) -> concatenation); - register size_t left_len; - register size_t right_len; - - left_len = LEFT_LEN(conc); - right_len = conc -> len - left_len; - if (i >= left_len) { - if (n == right_len) return(conc -> right); - return(CORD_substr_checked(conc -> right, i - left_len, n)); - } else if (i+n <= left_len) { - if (n == left_len) return(conc -> left); - return(CORD_substr_checked(conc -> left, i, n)); - } else { - /* Need at least one character from each side. */ - register CORD left_part; - register CORD right_part; - register size_t left_part_len = left_len - i; - - if (i == 0) { - left_part = conc -> left; - } else { - left_part = CORD_substr_checked(conc -> left, i, left_part_len); - } - if (i + n == right_len + left_len) { - right_part = conc -> right; - } else { - right_part = CORD_substr_checked(conc -> right, 0, - n - left_part_len); - } - return(CORD_cat(left_part, right_part)); - } + register struct Concatenation * conc + = &(((CordRep *)x) -> concatenation); + register size_t left_len; + register size_t right_len; + + left_len = LEFT_LEN(conc); + right_len = conc -> len - left_len; + if (i >= left_len) { + if (n == right_len) return(conc -> right); + return(CORD_substr_checked(conc -> right, i - left_len, n)); + } else if (i+n <= left_len) { + if (n == left_len) return(conc -> left); + return(CORD_substr_checked(conc -> left, i, n)); + } else { + /* Need at least one character from each side. */ + register CORD left_part; + register CORD right_part; + register size_t left_part_len = left_len - i; + + if (i == 0) { + left_part = conc -> left; + } else { + left_part = CORD_substr_checked(conc -> left, i, left_part_len); + } + if (i + n == right_len + left_len) { + right_part = conc -> right; + } else { + right_part = CORD_substr_checked(conc -> right, 0, + n - left_part_len); + } + return(CORD_cat(left_part, right_part)); + } } else /* function */ { if (n > SUBSTR_LIMIT) { if (IS_SUBSTR(x)) { - /* Avoid nesting substring nodes. */ - register struct Function * f = &(((CordRep *)x) -> function); - register struct substr_args *descr = - (struct substr_args *)(f -> client_data); - - return(CORD_substr_closure((CORD)descr->sa_cord, - i + descr->sa_index, - n, f -> fn)); + /* Avoid nesting substring nodes. */ + register struct Function * f = &(((CordRep *)x) -> function); + register struct substr_args *descr = + (struct substr_args *)(f -> client_data); + + return(CORD_substr_closure((CORD)descr->sa_cord, + i + descr->sa_index, + n, f -> fn)); } else { return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); } @@ -426,13 +426,13 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n) register char c; register int j; register int lim = i + n; - + for (j = i; j < lim; j++) { - c = (*(f -> fn))(j, f -> client_data); - if (c == '\0') { - return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); - } - *p++ = c; + c = (*(f -> fn))(j, f -> client_data); + if (c == '\0') { + return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); + } + *p++ = c; } *p = '\0'; result = GC_MALLOC_ATOMIC(n+1); @@ -446,59 +446,59 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n) CORD CORD_substr(CORD x, size_t i, size_t n) { register size_t len = CORD_len(x); - + if (i >= len || n <= 0) return(0); - /* n < 0 is impossible in a correct C implementation, but */ - /* quite possible under SunOS 4.X. */ + /* n < 0 is impossible in a correct C implementation, but */ + /* quite possible under SunOS 4.X. */ if (i + n > len) n = len - i; # ifndef __STDC__ if (i < 0) ABORT("CORD_substr: second arg. negative"); - /* Possible only if both client and C implementation are buggy. */ - /* But empirically this happens frequently. */ + /* Possible only if both client and C implementation are buggy. */ + /* But empirically this happens frequently. */ # endif return(CORD_substr_checked(x, i, n)); } -/* See cord.h for definition. We assume i is in range. */ +/* See cord.h for definition. We assume i is in range. */ int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1, - CORD_batched_iter_fn f2, void * client_data) + CORD_batched_iter_fn f2, void * client_data) { if (x == 0) return(0); if (CORD_IS_STRING(x)) { - register const char *p = x+i; - - if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big"); + register const char *p = x+i; + + if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big"); if (f2 != CORD_NO_FN) { return((*f2)(p, client_data)); } else { - while (*p) { + while (*p) { if ((*f1)(*p, client_data)) return(1); p++; - } - return(0); + } + return(0); } } else if (IS_CONCATENATION(x)) { - register struct Concatenation * conc - = &(((CordRep *)x) -> concatenation); - - - if (i > 0) { - register size_t left_len = LEFT_LEN(conc); - - if (i >= left_len) { - return(CORD_iter5(conc -> right, i - left_len, f1, f2, - client_data)); - } - } - if (CORD_iter5(conc -> left, i, f1, f2, client_data)) { - return(1); - } - return(CORD_iter5(conc -> right, 0, f1, f2, client_data)); + register struct Concatenation * conc + = &(((CordRep *)x) -> concatenation); + + + if (i > 0) { + register size_t left_len = LEFT_LEN(conc); + + if (i >= left_len) { + return(CORD_iter5(conc -> right, i - left_len, f1, f2, + client_data)); + } + } + if (CORD_iter5(conc -> left, i, f1, f2, client_data)) { + return(1); + } + return(CORD_iter5(conc -> right, 0, f1, f2, client_data)); } else /* function */ { register struct Function * f = &(((CordRep *)x) -> function); register size_t j; register size_t lim = f -> len; - + for (j = i; j < lim; j++) { if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) { return(1); @@ -507,7 +507,7 @@ int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1, return(0); } } - + #undef CORD_iter int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data) { @@ -518,36 +518,36 @@ int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data) { if (x == 0) return(0); if (CORD_IS_STRING(x)) { - register const char *p = x + i; - register char c; - - for(;;) { - c = *p; - if (c == '\0') ABORT("2nd arg to CORD_riter4 too big"); + register const char *p = x + i; + register char c; + + for(;;) { + c = *p; + if (c == '\0') ABORT("2nd arg to CORD_riter4 too big"); if ((*f1)(c, client_data)) return(1); - if (p == x) break; + if (p == x) break; p--; - } - return(0); + } + return(0); } else if (IS_CONCATENATION(x)) { - register struct Concatenation * conc - = &(((CordRep *)x) -> concatenation); - register CORD left_part = conc -> left; - register size_t left_len; - - left_len = LEFT_LEN(conc); - if (i >= left_len) { - if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) { - return(1); - } - return(CORD_riter4(left_part, left_len - 1, f1, client_data)); - } else { - return(CORD_riter4(left_part, i, f1, client_data)); - } + register struct Concatenation * conc + = &(((CordRep *)x) -> concatenation); + register CORD left_part = conc -> left; + register size_t left_len; + + left_len = LEFT_LEN(conc); + if (i >= left_len) { + if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) { + return(1); + } + return(CORD_riter4(left_part, left_len - 1, f1, client_data)); + } else { + return(CORD_riter4(left_part, i, f1, client_data)); + } } else /* function */ { register struct Function * f = &(((CordRep *)x) -> function); register size_t j; - + for (j = i; ; j--) { if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) { return(1); @@ -559,7 +559,9 @@ int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data) int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data) { - return(CORD_riter4(x, CORD_len(x) - 1, f1, client_data)); + size_t len = CORD_len(x); + if (len == 0) return(0); + return(CORD_riter4(x, len - 1, f1, client_data)); } /* @@ -579,7 +581,7 @@ int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data) typedef struct { CORD c; - size_t len; /* Actual length of c */ + size_t len; /* Actual length of c */ } ForestElement; static size_t min_len [ MAX_DEPTH ]; @@ -589,24 +591,24 @@ static int min_len_init = 0; int CORD_max_len; typedef ForestElement Forest [ MAX_DEPTH ]; - /* forest[i].len >= fib(i+1) */ - /* The string is the concatenation */ - /* of the forest in order of DECREASING */ - /* indices. */ + /* forest[i].len >= fib(i+1) */ + /* The string is the concatenation */ + /* of the forest in order of DECREASING */ + /* indices. */ void CORD_init_min_len() { register int i; register size_t last, previous, current; - + min_len[0] = previous = 1; min_len[1] = last = 2; for (i = 2; i < MAX_DEPTH; i++) { - current = last + previous; - if (current < last) /* overflow */ current = last; - min_len[i] = current; - previous = last; - last = current; + current = last + previous; + if (current < last) /* overflow */ current = last; + min_len[i] = current; + previous = last; + last = current; } CORD_max_len = last - 1; min_len_init = 1; @@ -616,48 +618,48 @@ void CORD_init_min_len() void CORD_init_forest(ForestElement * forest, size_t max_len) { register int i; - + for (i = 0; i < MAX_DEPTH; i++) { - forest[i].c = 0; - if (min_len[i] > max_len) return; + forest[i].c = 0; + if (min_len[i] > max_len) return; } ABORT("Cord too long"); } -/* Add a leaf to the appropriate level in the forest, cleaning */ -/* out lower levels as necessary. */ -/* Also works if x is a balanced tree of concatenations; however */ -/* in this case an extra concatenation node may be inserted above x; */ -/* This node should not be counted in the statement of the invariants. */ +/* Add a leaf to the appropriate level in the forest, cleaning */ +/* out lower levels as necessary. */ +/* Also works if x is a balanced tree of concatenations; however */ +/* in this case an extra concatenation node may be inserted above x; */ +/* This node should not be counted in the statement of the invariants. */ void CORD_add_forest(ForestElement * forest, CORD x, size_t len) { register int i = 0; register CORD sum = CORD_EMPTY; register size_t sum_len = 0; - + while (len > min_len[i + 1]) { - if (forest[i].c != 0) { - sum = CORD_cat(forest[i].c, sum); - sum_len += forest[i].len; - forest[i].c = 0; - } + if (forest[i].c != 0) { + sum = CORD_cat(forest[i].c, sum); + sum_len += forest[i].len; + forest[i].c = 0; + } i++; } - /* Sum has depth at most 1 greter than what would be required */ - /* for balance. */ + /* Sum has depth at most 1 greter than what would be required */ + /* for balance. */ sum = CORD_cat(sum, x); sum_len += len; - /* If x was a leaf, then sum is now balanced. To see this */ - /* consider the two cases in which forest[i-1] either is or is */ - /* not empty. */ + /* If x was a leaf, then sum is now balanced. To see this */ + /* consider the two cases in which forest[i-1] either is or is */ + /* not empty. */ while (sum_len >= min_len[i]) { - if (forest[i].c != 0) { - sum = CORD_cat(forest[i].c, sum); - sum_len += forest[i].len; - /* This is again balanced, since sum was balanced, and has */ - /* allowable depth that differs from i by at most 1. */ - forest[i].c = 0; - } + if (forest[i].c != 0) { + sum = CORD_cat(forest[i].c, sum); + sum_len += forest[i].len; + /* This is again balanced, since sum was balanced, and has */ + /* allowable depth that differs from i by at most 1. */ + forest[i].c = 0; + } i++; } i--; @@ -670,37 +672,37 @@ CORD CORD_concat_forest(ForestElement * forest, size_t expected_len) register int i = 0; CORD sum = 0; size_t sum_len = 0; - + while (sum_len != expected_len) { - if (forest[i].c != 0) { - sum = CORD_cat(forest[i].c, sum); - sum_len += forest[i].len; - } + if (forest[i].c != 0) { + sum = CORD_cat(forest[i].c, sum); + sum_len += forest[i].len; + } i++; } return(sum); } -/* Insert the frontier of x into forest. Balanced subtrees are */ -/* treated as leaves. This potentially adds one to the depth */ -/* of the final tree. */ +/* Insert the frontier of x into forest. Balanced subtrees are */ +/* treated as leaves. This potentially adds one to the depth */ +/* of the final tree. */ void CORD_balance_insert(CORD x, size_t len, ForestElement * forest) { register int depth; - + if (CORD_IS_STRING(x)) { CORD_add_forest(forest, x, len); } else if (IS_CONCATENATION(x) && ((depth = DEPTH(x)) >= MAX_DEPTH || len < min_len[depth])) { - register struct Concatenation * conc - = &(((CordRep *)x) -> concatenation); - size_t left_len = LEFT_LEN(conc); - - CORD_balance_insert(conc -> left, left_len, forest); - CORD_balance_insert(conc -> right, len - left_len, forest); + register struct Concatenation * conc + = &(((CordRep *)x) -> concatenation); + size_t left_len = LEFT_LEN(conc); + + CORD_balance_insert(conc -> left, left_len, forest); + CORD_balance_insert(conc -> right, len - left_len, forest); } else /* function or balanced */ { - CORD_add_forest(forest, x, len); + CORD_add_forest(forest, x, len); } } @@ -709,7 +711,7 @@ CORD CORD_balance(CORD x) { Forest forest; register size_t len; - + if (x == 0) return(0); if (CORD_IS_STRING(x)) return(x); if (!min_len_init) CORD_init_min_len(); @@ -720,13 +722,13 @@ CORD CORD_balance(CORD x) } -/* Position primitives */ +/* Position primitives */ /* Private routines to deal with the hard cases only: */ -/* P contains a prefix of the path to cur_pos. Extend it to a full */ -/* path and set up leaf info. */ -/* Return 0 if past the end of cord, 1 o.w. */ +/* P contains a prefix of the path to cur_pos. Extend it to a full */ +/* path and set up leaf info. */ +/* Return 0 if past the end of cord, 1 o.w. */ void CORD__extend_path(register CORD_pos p) { register struct CORD_pe * current_pe = &(p[0].path[p[0].path_len]); @@ -734,25 +736,25 @@ void CORD__extend_path(register CORD_pos p) register size_t pos = p[0].cur_pos; register size_t top_pos = current_pe -> pe_start_pos; register size_t top_len = GEN_LEN(top); - + /* Fill in the rest of the path. */ while(!CORD_IS_STRING(top) && IS_CONCATENATION(top)) { - register struct Concatenation * conc = - &(((CordRep *)top) -> concatenation); - register size_t left_len; - - left_len = LEFT_LEN(conc); - current_pe++; - if (pos >= top_pos + left_len) { - current_pe -> pe_cord = top = conc -> right; - current_pe -> pe_start_pos = top_pos = top_pos + left_len; - top_len -= left_len; - } else { - current_pe -> pe_cord = top = conc -> left; - current_pe -> pe_start_pos = top_pos; - top_len = left_len; - } - p[0].path_len++; + register struct Concatenation * conc = + &(((CordRep *)top) -> concatenation); + register size_t left_len; + + left_len = LEFT_LEN(conc); + current_pe++; + if (pos >= top_pos + left_len) { + current_pe -> pe_cord = top = conc -> right; + current_pe -> pe_start_pos = top_pos = top_pos + left_len; + top_len -= left_len; + } else { + current_pe -> pe_cord = top = conc -> left; + current_pe -> pe_start_pos = top_pos; + top_len = left_len; + } + p[0].path_len++; } /* Fill in leaf description for fast access. */ if (CORD_IS_STRING(top)) { @@ -771,7 +773,7 @@ char CORD__pos_fetch(register CORD_pos p) struct CORD_pe * pe = &((p)[0].path[(p)[0].path_len]); CORD leaf = pe -> pe_cord; register struct Function * f = &(((CordRep *)leaf) -> function); - + if (!IS_FUNCTION(leaf)) ABORT("CORD_pos_fetch: bad leaf"); return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data)); } @@ -781,48 +783,48 @@ void CORD__next(register CORD_pos p) register size_t cur_pos = p[0].cur_pos + 1; register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]); register CORD leaf = current_pe -> pe_cord; - + /* Leaf is not a string or we're at end of leaf */ p[0].cur_pos = cur_pos; if (!CORD_IS_STRING(leaf)) { - /* Function leaf */ - register struct Function * f = &(((CordRep *)leaf) -> function); - register size_t start_pos = current_pe -> pe_start_pos; - register size_t end_pos = start_pos + f -> len; - - if (cur_pos < end_pos) { - /* Fill cache and return. */ - register size_t i; - register size_t limit = cur_pos + FUNCTION_BUF_SZ; - register CORD_fn fn = f -> fn; - register void * client_data = f -> client_data; - - if (limit > end_pos) { - limit = end_pos; - } - for (i = cur_pos; i < limit; i++) { - p[0].function_buf[i - cur_pos] = - (*fn)(i - start_pos, client_data); - } - p[0].cur_start = cur_pos; - p[0].cur_leaf = p[0].function_buf; - p[0].cur_end = limit; - return; - } + /* Function leaf */ + register struct Function * f = &(((CordRep *)leaf) -> function); + register size_t start_pos = current_pe -> pe_start_pos; + register size_t end_pos = start_pos + f -> len; + + if (cur_pos < end_pos) { + /* Fill cache and return. */ + register size_t i; + register size_t limit = cur_pos + FUNCTION_BUF_SZ; + register CORD_fn fn = f -> fn; + register void * client_data = f -> client_data; + + if (limit > end_pos) { + limit = end_pos; + } + for (i = cur_pos; i < limit; i++) { + p[0].function_buf[i - cur_pos] = + (*fn)(i - start_pos, client_data); + } + p[0].cur_start = cur_pos; + p[0].cur_leaf = p[0].function_buf; + p[0].cur_end = limit; + return; + } } - /* End of leaf */ - /* Pop the stack until we find two concatenation nodes with the */ - /* same start position: this implies we were in left part. */ + /* End of leaf */ + /* Pop the stack until we find two concatenation nodes with the */ + /* same start position: this implies we were in left part. */ { - while (p[0].path_len > 0 - && current_pe[0].pe_start_pos != current_pe[-1].pe_start_pos) { - p[0].path_len--; - current_pe--; - } - if (p[0].path_len == 0) { - p[0].path_len = CORD_POS_INVALID; + while (p[0].path_len > 0 + && current_pe[0].pe_start_pos != current_pe[-1].pe_start_pos) { + p[0].path_len--; + current_pe--; + } + if (p[0].path_len == 0) { + p[0].path_len = CORD_POS_INVALID; return; - } + } } p[0].path_len--; CORD__extend_path(p); @@ -831,26 +833,26 @@ void CORD__next(register CORD_pos p) void CORD__prev(register CORD_pos p) { register struct CORD_pe * pe = &(p[0].path[p[0].path_len]); - + if (p[0].cur_pos == 0) { p[0].path_len = CORD_POS_INVALID; return; } p[0].cur_pos--; if (p[0].cur_pos >= pe -> pe_start_pos) return; - - /* Beginning of leaf */ - - /* Pop the stack until we find two concatenation nodes with the */ - /* different start position: this implies we were in right part. */ + + /* Beginning of leaf */ + + /* Pop the stack until we find two concatenation nodes with the */ + /* different start position: this implies we were in right part. */ { - register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]); - - while (p[0].path_len > 0 - && current_pe[0].pe_start_pos == current_pe[-1].pe_start_pos) { - p[0].path_len--; - current_pe--; - } + register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]); + + while (p[0].path_len > 0 + && current_pe[0].pe_start_pos == current_pe[-1].pe_start_pos) { + p[0].path_len--; + current_pe--; + } } p[0].path_len--; CORD__extend_path(p); @@ -866,7 +868,7 @@ void CORD__prev(register CORD_pos p) char CORD_pos_fetch(register CORD_pos p) { if (p[0].cur_start <= p[0].cur_pos && p[0].cur_pos < p[0].cur_end) { - return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]); + return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]); } else { return(CORD__pos_fetch(p)); } @@ -875,18 +877,18 @@ char CORD_pos_fetch(register CORD_pos p) void CORD_next(CORD_pos p) { if (p[0].cur_pos < p[0].cur_end - 1) { - p[0].cur_pos++; + p[0].cur_pos++; } else { - CORD__next(p); + CORD__next(p); } } void CORD_prev(CORD_pos p) { if (p[0].cur_end != 0 && p[0].cur_pos > p[0].cur_start) { - p[0].cur_pos--; + p[0].cur_pos--; } else { - CORD__prev(p); + CORD__prev(p); } } @@ -908,8 +910,8 @@ int CORD_pos_valid(CORD_pos p) void CORD_set_pos(CORD_pos p, CORD x, size_t i) { if (x == CORD_EMPTY) { - p[0].path_len = CORD_POS_INVALID; - return; + p[0].path_len = CORD_POS_INVALID; + return; } p[0].path[0].pe_cord = x; p[0].path[0].pe_start_pos = 0; diff --git a/dyn_load.c b/dyn_load.c index 28a74782..982ec379 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -185,8 +185,7 @@ GC_FirstDLOpenedLinkMap(void) # ifndef USE_PROC_FOR_LIBRARIES GC_INNER void GC_register_dynamic_libraries(void) { - struct link_map *lm = GC_FirstDLOpenedLinkMap(); - + struct link_map *lm; for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) { ElfW(Ehdr) * e; @@ -521,7 +520,7 @@ GC_INNER GC_bool GC_register_main_static_data(void) /* zero (otherwise a compiler might issue a warning). */ return FALSE; # else - return (dl_iterate_phdr == 0); + return (dl_iterate_phdr == 0); /* implicit conversion to function ptr */ # endif } @@ -667,8 +666,7 @@ GC_INNER void GC_register_dynamic_libraries(void) return; } # endif - lm = GC_FirstDLOpenedLinkMap(); - for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) + for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) { ElfW(Ehdr) * e; ElfW(Phdr) * p; diff --git a/tests/threadkey_test.c b/tests/threadkey_test.c index bf3f51ea..d080a7ba 100644 --- a/tests/threadkey_test.c +++ b/tests/threadkey_test.c @@ -45,11 +45,14 @@ void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg) { int res = GC_register_my_thread (sb); pthread_t t; + int creation_res; /* Used to suppress a warning about */ + /* unchecked pthread_create() result. */ - GC_pthread_create (&t, NULL, entry, NULL); + creation_res = GC_pthread_create (&t, NULL, entry, NULL); if (res == GC_SUCCESS) GC_unregister_my_thread (); - return NULL; + + return (void*)(GC_word)creation_res; } void on_thread_exit (void *v) -- cgit v1.2.1 From 889e3da89529cdf2fd35c7134ff4180876e765b5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 5 Jul 2011 16:35:22 +0000 Subject: 2011-07-05 Ivan Maidanski * malloc.c (GC_init_lib_bounds): Call GC_init (to ensure GC is initialized before doing GC_text_mapping). * misc.c (GC_init): Add a check for GC_init recursion in case of malloc is redirected (abort with the corresponding message). * pthread.c (GC_thr_init): Place GC_add_roots_inner call into "else" branch to prevent "local variable might be uninitialized" compiler warning; add comment. --HG-- branch : bdwgc --- ChangeLog | 10 ++++++++++ malloc.c | 1 + misc.c | 8 ++++++++ pthread_support.c | 4 +++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 34085005..5370f518 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-07-05 Ivan Maidanski + + * malloc.c (GC_init_lib_bounds): Call GC_init (to ensure GC is + initialized before doing GC_text_mapping). + * misc.c (GC_init): Add a check for GC_init recursion in case of + malloc is redirected (abort with the corresponding message). + * pthread.c (GC_thr_init): Place GC_add_roots_inner call into + "else" branch to prevent "local variable might be uninitialized" + compiler warning; add comment. + 2011-07-05 Ivan Maidanski * dyn_load.c (GC_register_dynamic_libraries): Remove duplicate diff --git a/malloc.c b/malloc.c index 80ef18d9..aeda6936 100644 --- a/malloc.c +++ b/malloc.c @@ -354,6 +354,7 @@ void * malloc(size_t lb) STATIC void GC_init_lib_bounds(void) { if (GC_libpthread_start != 0) return; + GC_init(); /* if not called yet */ if (!GC_text_mapping("libpthread-", &GC_libpthread_start, &GC_libpthread_end)) { WARN("Failed to find libpthread.so text mapping: Expect crash\n", 0); diff --git a/misc.c b/misc.c index 34bb570e..c2d5cab3 100644 --- a/misc.c +++ b/misc.c @@ -663,6 +663,14 @@ GC_API void GC_CALL GC_init(void) IF_CANCEL(int cancel_state;) if (GC_is_initialized) return; +# ifdef REDIRECT_MALLOC + { + static GC_bool init_started = FALSE; + if (init_started) + ABORT("Redirected malloc() called during GC init"); + init_started = TRUE; + } +# endif # ifdef GC_INITIAL_HEAP_SIZE initial_heap_sz = divHBLKSZ(GC_INITIAL_HEAP_SIZE); diff --git a/pthread_support.c b/pthread_support.c index f9af3029..7e7e2914 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -906,8 +906,10 @@ GC_INNER void GC_thr_init(void) if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start, &main_thread_end)) { ABORT("Failed to find mapping for main thread thread locals"); + } else { + /* main_thread_start and main_thread_end are initialized. */ + GC_add_roots_inner(main_thread_start, main_thread_end, FALSE); } - GC_add_roots_inner(main_thread_start, main_thread_end, FALSE); } # endif /* Add the initial thread, so we can stop it. */ -- cgit v1.2.1 From 3691f1b6a2a0e6fc31dd03d136fa318321f6c8db Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 5 Jul 2011 17:53:24 +0000 Subject: 2011-07-05 Ivan Maidanski * misc.c (GC_init): Use HOTTER_THAN (instead of STACK_GROWS_DOWN) for GC_stackbottom assertion. * os_dep.c (GC_enclosing_mapping): Define only if IA64 or INCLUDE_LINUX_THREAD_DESCR; make GC_INNER. * pthread_support.c (GC_enclosing_mapping): Declare (only if INCLUDE_LINUX_THREAD_DESCR). * os_dep.c (GC_get_main_stack_base): Don't call pthread_getattr_np if REDIRECT_MALLOC as the former is observed to call redirected malloc (while GC is not initialized yet) on some Linux platforms. * include/private/gc_priv.h (MAX_HEAP_SECTS): Don't use a smaller value for SMALL_CONFIG if USE_PROC_FOR_LIBRARIES defined. --HG-- branch : bdwgc --- ChangeLog | 14 ++++++++++++ include/private/gc_priv.h | 2 +- misc.c | 10 +++------ os_dep.c | 56 +++++++++++++++++++++++++---------------------- pthread_support.c | 2 ++ 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5370f518..5776b929 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-05 Ivan Maidanski + + * misc.c (GC_init): Use HOTTER_THAN (instead of STACK_GROWS_DOWN) + for GC_stackbottom assertion. + * os_dep.c (GC_enclosing_mapping): Define only if IA64 or + INCLUDE_LINUX_THREAD_DESCR; make GC_INNER. + * pthread_support.c (GC_enclosing_mapping): Declare (only if + INCLUDE_LINUX_THREAD_DESCR). + * os_dep.c (GC_get_main_stack_base): Don't call pthread_getattr_np + if REDIRECT_MALLOC as the former is observed to call redirected + malloc (while GC is not initialized yet) on some Linux platforms. + * include/private/gc_priv.h (MAX_HEAP_SECTS): Don't use a smaller + value for SMALL_CONFIG if USE_PROC_FOR_LIBRARIES defined. + 2011-07-05 Ivan Maidanski * malloc.c (GC_init_lib_bounds): Call GC_init (to ensure GC is diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index daf2069c..d3d14ca3 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -952,7 +952,7 @@ struct roots { # else # define MAX_HEAP_SECTS 768 /* Separately added heap sections. */ # endif -# elif defined(SMALL_CONFIG) +# elif defined(SMALL_CONFIG) && !defined(USE_PROC_FOR_LIBRARIES) # define MAX_HEAP_SECTS 128 /* Roughly 256MB (128*2048*1K) */ # elif CPP_WORDSZ > 32 # define MAX_HEAP_SECTS 1024 /* Roughly 8GB */ diff --git a/misc.c b/misc.c index c2d5cab3..ab3fef99 100644 --- a/misc.c +++ b/misc.c @@ -914,8 +914,8 @@ GC_API void GC_CALL GC_init(void) # if defined(NETBSD) && defined(__ELF__) GC_init_netbsd_elf(); # endif -# if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \ - || defined(GC_SOLARIS_THREADS) +# if !defined(THREADS) || defined(GC_PTHREADS) \ + || defined(GC_WIN32_THREADS) || defined(GC_SOLARIS_THREADS) if (GC_stackbottom == 0) { GC_stackbottom = GC_get_main_stack_base(); # if (defined(LINUX) || defined(HPUX)) && defined(IA64) @@ -937,11 +937,7 @@ GC_API void GC_CALL GC_init(void) GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); # ifndef THREADS -# ifdef STACK_GROWS_DOWN - GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom); -# else - GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom); -# endif + GC_ASSERT(!((word)GC_stackbottom HOTTER_THAN (word)(&dummy))); # endif # if !defined(_AUX_SOURCE) || defined(__GNUC__) GC_STATIC_ASSERT((word)(-1) > (word)0); diff --git a/os_dep.c b/os_dep.c index 73b49396..2d73340a 100644 --- a/os_dep.c +++ b/os_dep.c @@ -349,34 +349,37 @@ GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end, return p; } -/* Try to read the backing store base from /proc/self/maps. */ -/* Return the bounds of the writable mapping with a 0 major device, */ -/* which includes the address passed as data. */ -/* Return FALSE if there is no such mapping. */ -GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp) -{ - char *prot; - ptr_t my_start, my_end; - unsigned int maj_dev; - char *maps = GC_get_maps(); - char *buf_ptr = maps; +#if defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR) + /* Try to read the backing store base from /proc/self/maps. */ + /* Return the bounds of the writable mapping with a 0 major device, */ + /* which includes the address passed as data. */ + /* Return FALSE if there is no such mapping. */ + GC_INNER GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, + ptr_t *endp) + { + char *prot; + ptr_t my_start, my_end; + unsigned int maj_dev; + char *maps = GC_get_maps(); + char *buf_ptr = maps; - if (0 == maps) return(FALSE); - for (;;) { - buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end, - &prot, &maj_dev, 0); - - if (buf_ptr == NULL) return FALSE; - if (prot[1] == 'w' && maj_dev == 0) { - if (my_end > addr && my_start <= addr) { - *startp = my_start; - *endp = my_end; - return TRUE; - } + if (0 == maps) return(FALSE); + for (;;) { + buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end, + &prot, &maj_dev, 0); + + if (buf_ptr == NULL) return FALSE; + if (prot[1] == 'w' && maj_dev == 0) { + if (my_end > addr && my_start <= addr) { + *startp = my_start; + *endp = my_end; + return TRUE; + } + } } + return FALSE; } - return FALSE; -} +#endif /* IA64 || INCLUDE_LINUX_THREAD_DESCR */ #if defined(REDIRECT_MALLOC) /* Find the text(code) mapping for the library whose name, after */ @@ -1144,7 +1147,8 @@ GC_INNER word GC_page_size = 0; { ptr_t result; /* also used as "dummy" to get the approx. sp value */ # if defined(LINUX) && !defined(NACL) \ - && (defined(USE_GET_STACKBASE_FOR_MAIN) || defined(THREADS)) + && (defined(USE_GET_STACKBASE_FOR_MAIN) \ + || (defined(THREADS) && !defined(REDIRECT_MALLOC))) pthread_attr_t attr; void *stackaddr; size_t size; diff --git a/pthread_support.c b/pthread_support.c index 7e7e2914..bcdfebd1 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -879,6 +879,8 @@ STATIC void GC_fork_child_proc(void) #ifdef INCLUDE_LINUX_THREAD_DESCR __thread int GC_dummy_thread_local; + GC_INNER GC_bool GC_enclosing_mapping(ptr_t addr, + ptr_t *startp, ptr_t *endp); #endif /* We hold the allocation lock. */ -- cgit v1.2.1 From 76a3e39e357ab9ad1de7fa182a31129af67d6de4 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 14 Jul 2011 13:43:13 +0000 Subject: 2011-07-14 Ivan Maidanski * new_hblk.c (GC_build_fl): Adjust "h" local variable cast type when setting obj_link (to prevent compiler warning); reformat the comment. * tests/test.c (reverse_test_inner): Use proper type when touching "b" and "c" local variables (to prevent compiler warning). --HG-- branch : bdwgc --- ChangeLog | 8 ++++++++ new_hblk.c | 10 ++++------ tests/test.c | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5776b929..362cd633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-07-14 Ivan Maidanski + + * new_hblk.c (GC_build_fl): Adjust "h" local variable cast type + when setting obj_link (to prevent compiler warning); reformat the + comment. + * tests/test.c (reverse_test_inner): Use proper type when touching + "b" and "c" local variables (to prevent compiler warning). + 2011-07-05 Ivan Maidanski * misc.c (GC_init): Use HOTTER_THAN (instead of STACK_GROWS_DOWN) diff --git a/new_hblk.c b/new_hblk.c index 6e2dca56..1366b131 100644 --- a/new_hblk.c +++ b/new_hblk.c @@ -158,12 +158,10 @@ GC_INNER ptr_t GC_build_fl(struct hblk *h, size_t sz, GC_bool clear, } p -= sz; /* p now points to last object */ - /* - * put p (which is now head of list of objects in *h) as first - * pointer in the appropriate free list for this size. - */ - obj_link(h -> hb_body) = list; - return ((ptr_t)p); + /* Put p (which is now head of list of objects in *h) as first */ + /* pointer in the appropriate free list for this size. */ + *(ptr_t *)h = list; + return ((ptr_t)p); } /* diff --git a/tests/test.c b/tests/test.c index 809853c2..fa2eda17 100644 --- a/tests/test.c +++ b/tests/test.c @@ -638,8 +638,8 @@ void *GC_CALLBACK reverse_test_inner(void *data) # ifndef THREADS a = 0; # endif - *(volatile void **)&b = 0; - *(volatile void **)&c = 0; + *(sexpr volatile *)&b = 0; + *(sexpr volatile *)&c = 0; return 0; } -- cgit v1.2.1 From 70238fe7905bd7c6a1706dbe047658a2313012e7 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 14 Jul 2011 17:20:58 +0000 Subject: 2011-07-14 Ivan Maidanski * .cvsignore: Add more auto-generated files. --HG-- branch : bdwgc --- .cvsignore | 37 +++++++++++++++++++++++++++++++++---- ChangeLog | 4 ++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.cvsignore b/.cvsignore index 3692f0bb..0ab95f24 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,20 +1,49 @@ +*.bsc +*.csm +*.dll +*.err +*.exe +*.exp +*.la +*.lb1 +*.lib +*.lnk *.lo +*.map +*.o +*.obj +*.out +*.pdb +*.rbj +*.res +*.sbr +*.stackdump +*.sym +*.tmp +.deps .libs Makefile +add_gc_prefix bdw-gc.pc config.log config.status +cordtest +core +de +gc-* +gcname gctest hugetest +if_mach +if_not_there initsecondarythread leaktest -libcord.la -libgc.la -libstaticrootslib.la libtool middletest +setjmp_test smashtest staticrootstest +test_cpp threadkey_test threadleaktest -test_cpp +threadlibs diff --git a/ChangeLog b/ChangeLog index 362cd633..82980884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-14 Ivan Maidanski + + * .cvsignore: Add more auto-generated files. + 2011-07-14 Ivan Maidanski * new_hblk.c (GC_build_fl): Adjust "h" local variable cast type -- cgit v1.2.1 From 6859feb53580bb4ae6f558767a0e7572cbf72a69 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 26 Jul 2011 08:03:10 +0000 Subject: 2011-07-26 Ivan Maidanski * tests/realloc_test.c: New file. * tests/tests.am (TESTS, check_PROGRAMS): Add realloc_test. * .cvsignore: Add realloc_test. * configure: Regenerate. * Makefile.in: Ditto. --HG-- branch : bdwgc --- .cvsignore | 1 + ChangeLog | 8 ++++++++ Makefile.in | 44 +++++++++++++++++++++++++++++++++++--------- configure | 2 +- tests/realloc_test.c | 34 ++++++++++++++++++++++++++++++++++ tests/tests.am | 5 +++++ 6 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 tests/realloc_test.c diff --git a/.cvsignore b/.cvsignore index 0ab95f24..b7324ef5 100644 --- a/.cvsignore +++ b/.cvsignore @@ -40,6 +40,7 @@ initsecondarythread leaktest libtool middletest +realloc_test setjmp_test smashtest staticrootstest diff --git a/ChangeLog b/ChangeLog index 82980884..a96ab000 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-07-26 Ivan Maidanski + + * tests/realloc_test.c: New file. + * tests/tests.am (TESTS, check_PROGRAMS): Add realloc_test. + * .cvsignore: Add realloc_test. + * configure: Regenerate. + * Makefile.in: Ditto. + 2011-07-14 Ivan Maidanski * .cvsignore: Add more auto-generated files. diff --git a/Makefile.in b/Makefile.in index 09dea13b..29d41ea0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -96,8 +96,9 @@ target_triplet = @target@ @USE_INTERNAL_LIBATOMIC_OPS_TRUE@ -I$(top_srcdir)/libatomic_ops/src check_PROGRAMS = gctest$(EXEEXT) leaktest$(EXEEXT) middletest$(EXEEXT) \ - smashtest$(EXEEXT) hugetest$(EXEEXT) staticrootstest$(EXEEXT) \ - $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) + smashtest$(EXEEXT) hugetest$(EXEEXT) realloc_test$(EXEEXT) \ + staticrootstest$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \ + $(am__EXEEXT_3) # C Library: Architecture Dependent # --------------------------------- @@ -237,6 +238,9 @@ leaktest_DEPENDENCIES = $(am__DEPENDENCIES_2) am_middletest_OBJECTS = middle.$(OBJEXT) middletest_OBJECTS = $(am_middletest_OBJECTS) middletest_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_realloc_test_OBJECTS = realloc_test.$(OBJEXT) +realloc_test_OBJECTS = $(am_realloc_test_OBJECTS) +realloc_test_DEPENDENCIES = $(am__DEPENDENCIES_2) am_smashtest_OBJECTS = smash_test.$(OBJEXT) smashtest_OBJECTS = $(am_smashtest_OBJECTS) smashtest_DEPENDENCIES = $(am__DEPENDENCIES_2) @@ -300,15 +304,16 @@ SOURCES = $(libcord_la_SOURCES) $(libgc_la_SOURCES) \ $(libgccpp_la_SOURCES) $(libstaticrootslib_la_SOURCES) \ $(gctest_SOURCES) $(hugetest_SOURCES) \ $(initsecondarythread_SOURCES) $(leaktest_SOURCES) \ - $(middletest_SOURCES) $(smashtest_SOURCES) \ - $(staticrootstest_SOURCES) $(test_cpp_SOURCES) \ - $(threadkey_test_SOURCES) $(threadleaktest_SOURCES) \ - $(tracetest_SOURCES) + $(middletest_SOURCES) $(realloc_test_SOURCES) \ + $(smashtest_SOURCES) $(staticrootstest_SOURCES) \ + $(test_cpp_SOURCES) $(threadkey_test_SOURCES) \ + $(threadleaktest_SOURCES) $(tracetest_SOURCES) DIST_SOURCES = $(libcord_la_SOURCES) $(am__libgc_la_SOURCES_DIST) \ $(EXTRA_libgc_la_SOURCES) $(am__libgccpp_la_SOURCES_DIST) \ $(libstaticrootslib_la_SOURCES) $(gctest_SOURCES) \ $(hugetest_SOURCES) $(am__initsecondarythread_SOURCES_DIST) \ - $(leaktest_SOURCES) $(middletest_SOURCES) $(smashtest_SOURCES) \ + $(leaktest_SOURCES) $(middletest_SOURCES) \ + $(realloc_test_SOURCES) $(smashtest_SOURCES) \ $(staticrootstest_SOURCES) $(am__test_cpp_SOURCES_DIST) \ $(am__threadkey_test_SOURCES_DIST) \ $(am__threadleaktest_SOURCES_DIST) \ @@ -601,8 +606,9 @@ dist_noinst_HEADERS = include/private/gc_hdrs.h \ include/ec.h include/javaxfc.h check_LTLIBRARIES = libstaticrootslib.la TESTS = gctest$(EXEEXT) leaktest$(EXEEXT) middletest$(EXEEXT) \ - smashtest$(EXEEXT) hugetest$(EXEEXT) staticrootstest$(EXEEXT) \ - $(am__append_7) $(am__append_9) $(am__append_11) + smashtest$(EXEEXT) hugetest$(EXEEXT) realloc_test$(EXEEXT) \ + staticrootstest$(EXEEXT) $(am__append_7) $(am__append_9) \ + $(am__append_11) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = bdw-gc.pc libgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \ @@ -670,6 +676,8 @@ smashtest_SOURCES = tests/smash_test.c smashtest_LDADD = $(test_ldadd) hugetest_SOURCES = tests/huge_test.c hugetest_LDADD = $(test_ldadd) +realloc_test_SOURCES = tests/realloc_test.c +realloc_test_LDADD = $(test_ldadd) staticrootstest_SOURCES = tests/staticrootstest.c staticrootstest_LDADD = $(test_ldadd) libstaticrootslib.la libstaticrootslib_la_SOURCES = tests/staticrootslib.c @@ -857,6 +865,9 @@ leaktest$(EXEEXT): $(leaktest_OBJECTS) $(leaktest_DEPENDENCIES) middletest$(EXEEXT): $(middletest_OBJECTS) $(middletest_DEPENDENCIES) @rm -f middletest$(EXEEXT) $(LINK) $(middletest_OBJECTS) $(middletest_LDADD) $(LIBS) +realloc_test$(EXEEXT): $(realloc_test_OBJECTS) $(realloc_test_DEPENDENCIES) + @rm -f realloc_test$(EXEEXT) + $(LINK) $(realloc_test_OBJECTS) $(realloc_test_LDADD) $(LIBS) smashtest$(EXEEXT): $(smashtest_OBJECTS) $(smashtest_DEPENDENCIES) @rm -f smashtest$(EXEEXT) $(LINK) $(smashtest_OBJECTS) $(smashtest_LDADD) $(LIBS) @@ -920,6 +931,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pthread_support.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptr_chck.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/real_malloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reclaim.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smash_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sparc_mach_dep.Plo@am__quote@ @@ -1090,6 +1102,20 @@ middle.obj: tests/middle.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o middle.obj `if test -f 'tests/middle.c'; then $(CYGPATH_W) 'tests/middle.c'; else $(CYGPATH_W) '$(srcdir)/tests/middle.c'; fi` +realloc_test.o: tests/realloc_test.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT realloc_test.o -MD -MP -MF $(DEPDIR)/realloc_test.Tpo -c -o realloc_test.o `test -f 'tests/realloc_test.c' || echo '$(srcdir)/'`tests/realloc_test.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/realloc_test.Tpo $(DEPDIR)/realloc_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/realloc_test.c' object='realloc_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o realloc_test.o `test -f 'tests/realloc_test.c' || echo '$(srcdir)/'`tests/realloc_test.c + +realloc_test.obj: tests/realloc_test.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT realloc_test.obj -MD -MP -MF $(DEPDIR)/realloc_test.Tpo -c -o realloc_test.obj `if test -f 'tests/realloc_test.c'; then $(CYGPATH_W) 'tests/realloc_test.c'; else $(CYGPATH_W) '$(srcdir)/tests/realloc_test.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/realloc_test.Tpo $(DEPDIR)/realloc_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/realloc_test.c' object='realloc_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o realloc_test.obj `if test -f 'tests/realloc_test.c'; then $(CYGPATH_W) 'tests/realloc_test.c'; else $(CYGPATH_W) '$(srcdir)/tests/realloc_test.c'; fi` + smash_test.o: tests/smash_test.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT smash_test.o -MD -MP -MF $(DEPDIR)/smash_test.Tpo -c -o smash_test.o `test -f 'tests/smash_test.c' || echo '$(srcdir)/'`tests/smash_test.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/smash_test.Tpo $(DEPDIR)/smash_test.Po diff --git a/configure b/configure index 486a8e71..7f975b40 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 1.68 . +# From configure.ac Revision: 1.69 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for gc 7.2alpha7. # diff --git a/tests/realloc_test.c b/tests/realloc_test.c new file mode 100644 index 00000000..370ba466 --- /dev/null +++ b/tests/realloc_test.c @@ -0,0 +1,34 @@ + +#include +#include +#include "gc.h" + +#define COUNT 10000000 + +int main(void) { + int i; + unsigned long last_heap_size = 0; + + GC_INIT(); + + for (i = 0; i < COUNT; i++) { + int **p = GC_MALLOC(sizeof(int *)); + int *q = GC_MALLOC_ATOMIC(sizeof(int)); + + if (*p != 0) { + fprintf(stderr, "GC_malloc returned garbage\n"); + exit(1); + } + + *p = GC_REALLOC(q, 2 * sizeof(int)); + + if (i % 10 == 0) { + unsigned long heap_size = (unsigned long)GC_get_heap_size(); + if (heap_size != last_heap_size) { + printf("Heap size: %lu\n", heap_size); + last_heap_size = heap_size; + } + } + } + return 0; +} diff --git a/tests/tests.am b/tests/tests.am index 2ef84ba6..f3505749 100644 --- a/tests/tests.am +++ b/tests/tests.am @@ -45,6 +45,11 @@ check_PROGRAMS += hugetest hugetest_SOURCES = tests/huge_test.c hugetest_LDADD = $(test_ldadd) +TESTS += realloc_test$(EXEEXT) +check_PROGRAMS += realloc_test +realloc_test_SOURCES = tests/realloc_test.c +realloc_test_LDADD = $(test_ldadd) + TESTS += staticrootstest$(EXEEXT) check_PROGRAMS += staticrootstest staticrootstest_SOURCES = tests/staticrootstest.c -- cgit v1.2.1