diff options
Diffstat (limited to 'tests/gctest.c')
-rw-r--r-- | tests/gctest.c | 351 |
1 files changed, 216 insertions, 135 deletions
diff --git a/tests/gctest.c b/tests/gctest.c index 709d65cd..03dcd585 100644 --- a/tests/gctest.c +++ b/tests/gctest.c @@ -41,6 +41,7 @@ # undef GC_NO_THREAD_REDIRECTS #endif #include "gc.h" +#include "gc/javaxfc.h" #ifndef NTHREADS /* Number of additional threads to fork. */ # define NTHREADS 5 /* Excludes main thread, which also runs a test. */ @@ -360,7 +361,7 @@ struct fake_vtable gcj_class_struct2 = struct GC_ms_entry * fake_gcj_mark_proc(word * addr, struct GC_ms_entry *mark_stack_ptr, struct GC_ms_entry *mark_stack_limit, - word env ) + word env) { sexpr x; if (1 == env) { @@ -379,7 +380,6 @@ struct GC_ms_entry * fake_gcj_mark_proc(word * addr, #endif /* GC_GCJ_SUPPORT */ - sexpr small_cons (sexpr x, sexpr y) { sexpr r = GC_NEW(struct SEXPR); @@ -635,15 +635,27 @@ void check_marks_int_list(sexpr x) # define TINY_REVERSE_UPPER_VALUE 10 # endif -# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) - DWORD __stdcall -# else + void tiny_reverse_test_inner(void) + { + int i; + + for (i = 0; i < 5; ++i) { + check_ints(reverse(reverse(ints(1, TINY_REVERSE_UPPER_VALUE))), + 1, TINY_REVERSE_UPPER_VALUE); + } + } + +# if defined(GC_PTHREADS) void* +# elif !defined(MSWINCE) && !defined(MSWIN_XBOX1) && !defined(NO_CRT) \ + && !defined(NO_TEST_ENDTHREADEX) +# define TEST_ENDTHREADEX + unsigned __stdcall +# else + DWORD __stdcall # endif tiny_reverse_test(void *p_resumed) { - int i; - # if defined(GC_ENABLE_SUSPEND_THREAD) && !defined(GC_OSF1_THREADS) \ && defined(SIGNAL_BASED_STOP_WORLD) if (p_resumed != NULL) { @@ -654,15 +666,38 @@ void check_marks_int_list(sexpr x) # else (void)p_resumed; # endif - - for (i = 0; i < 5; ++i) { - check_ints(reverse(reverse(ints(1, TINY_REVERSE_UPPER_VALUE))), - 1, TINY_REVERSE_UPPER_VALUE); - } + tiny_reverse_test_inner(); # if defined(GC_ENABLE_SUSPEND_THREAD) /* Force collection from a thread. */ GC_gcollect(); # endif +# if defined(GC_PTHREADS) && !defined(GC_NO_PTHREAD_CANCEL) + { + static volatile AO_t tiny_cancel_cnt = 0; + + if (AO_fetch_and_add1(&tiny_cancel_cnt) % 3 == 0 + && GC_pthread_cancel(pthread_self()) != 0) { + GC_printf("pthread_cancel failed\n"); + FAIL; + } + } +# endif +# if defined(GC_PTHREADS) && defined(GC_HAVE_PTHREAD_EXIT) \ + || (defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)) + { + static volatile AO_t tiny_exit_cnt = 0; + + if ((AO_fetch_and_add1(&tiny_exit_cnt) & 1) == 0) { +# ifdef TEST_ENDTHREADEX + GC_endthreadex(0); +# elif defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) + GC_ExitThread(0); +# else + GC_pthread_exit(p_resumed); +# endif + } + } +# endif return 0; } @@ -675,7 +710,7 @@ void check_marks_int_list(sexpr x) static volatile AO_t forked_cnt = 0; volatile AO_t *p_resumed = NULL; - if ((AO_fetch_and_add1(&forked_cnt) % 2) == 0) { + if (AO_fetch_and_add1(&forked_cnt) % 2 == 0) { p_resumed = GC_NEW(AO_t); CHECK_OUT_OF_MEMORY(p_resumed); AO_fetch_and_add1(&collectable_count); @@ -731,12 +766,22 @@ void check_marks_int_list(sexpr x) # elif defined(GC_WIN32_THREADS) void fork_a_thread(void) { - DWORD thread_id; HANDLE h; - h = CreateThread((SECURITY_ATTRIBUTES *)NULL, (word)0, - tiny_reverse_test, NULL, (DWORD)0, &thread_id); +# ifdef TEST_ENDTHREADEX + unsigned thread_id; + + h = (HANDLE)GC_beginthreadex(NULL /* security */, + 0 /* stack_size */, tiny_reverse_test, + NULL /* arglist */, 0 /* initflag */, + &thread_id); +# else + DWORD thread_id; + + h = CreateThread((SECURITY_ATTRIBUTES *)NULL, (word)0, + tiny_reverse_test, NULL, (DWORD)0, &thread_id); /* Explicitly specify types of the */ /* arguments to test the prototype. */ +# endif if (h == (HANDLE)NULL) { GC_printf("Small thread creation failed, errcode= %d\n", (int)GetLastError()); @@ -949,19 +994,27 @@ typedef struct treenode { int finalized_count = 0; int dropped_something = 0; -void GC_CALLBACK finalizer(void * obj, void * client_data) -{ - tn * t = (tn *)obj; +#ifndef GC_NO_FINALIZATION + void GC_CALLBACK finalizer(void *obj, void *client_data) + { + tn *t = (tn *)obj; + + FINALIZER_LOCK(); + if ((int)(GC_word)client_data != t -> level) { + GC_printf("Wrong finalization data - collector is broken\n"); + FAIL; + } + finalized_count++; + t -> level = -1; /* detect duplicate finalization immediately */ + FINALIZER_UNLOCK(); + } - FINALIZER_LOCK(); - if ((int)(GC_word)client_data != t -> level) { - GC_printf("Wrong finalization data - collector is broken\n"); - FAIL; + void GC_CALLBACK dummy_finalizer(void *obj, void *client_data) + { + UNUSED_ARG(obj); + UNUSED_ARG(client_data); } - finalized_count++; - t -> level = -1; /* detect duplicate finalization immediately */ - FINALIZER_UNLOCK(); -} +#endif /* !GC_NO_FINALIZATION */ # define MAX_FINALIZED ((NTHREADS+1)*4000) @@ -1031,25 +1084,25 @@ tn * mktree(int n) GC_REGISTER_FINALIZER((void *)result, finalizer, (void *)(GC_word)n, (GC_finalization_proc *)0, (void * *)0); if (my_index >= MAX_FINALIZED) { - GC_printf("live_indicators overflowed\n"); - FAIL; + GC_printf("live_indicators overflowed\n"); + FAIL; } live_indicators[my_index] = 13; if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( - (void * *)(&(live_indicators[my_index])), result) != 0) { - GC_printf("GC_general_register_disappearing_link failed\n"); - FAIL; + (void **)(&(live_indicators[my_index])), result) != 0) { + GC_printf("GC_general_register_disappearing_link failed\n"); + FAIL; } if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])), - (void **)(&(live_indicators[my_index]))) != GC_SUCCESS) { - GC_printf("GC_move_disappearing_link(link,link) failed\n"); - FAIL; + (void **)(&(live_indicators[my_index]))) != GC_SUCCESS) { + GC_printf("GC_move_disappearing_link(link,link) failed\n"); + FAIL; } *new_link = (void *)live_indicators[my_index]; if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])), new_link) != GC_SUCCESS) { - GC_printf("GC_move_disappearing_link(new_link) failed\n"); - FAIL; + GC_printf("GC_move_disappearing_link(new_link) failed\n"); + FAIL; } /* Note: if other thread is performing fork at this moment, */ /* then the stack of the current thread is dropped (together */ @@ -1057,18 +1110,18 @@ tn * mktree(int n) /* GC_dl_hashtbl entry with the link equal to new_link will be */ /* removed when a collection occurs (as expected). */ if (GC_unregister_disappearing_link(new_link) == 0) { - GC_printf("GC_unregister_disappearing_link failed\n"); - FAIL; + GC_printf("GC_unregister_disappearing_link failed\n"); + FAIL; } if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])), new_link) != GC_NOT_FOUND) { - GC_printf("GC_move_disappearing_link(new_link) failed 2\n"); - FAIL; + GC_printf("GC_move_disappearing_link(new_link) failed 2\n"); + FAIL; } if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( - (void * *)(&(live_indicators[my_index])), result) != 0) { - GC_printf("GC_general_register_disappearing_link failed 2\n"); - FAIL; + (void **)(&(live_indicators[my_index])), result) != 0) { + GC_printf("GC_general_register_disappearing_link failed 2\n"); + FAIL; } # ifndef GC_LONG_REFS_NOT_NEEDED if (GC_REGISTER_LONG_LINK(&live_long_refs[my_index], result) != 0) { @@ -1434,8 +1487,9 @@ void * GC_CALLBACK set_stackbottom(void *cd) void run_one_test(void) { + char *x; # ifndef DBG_HDRS_ALL - char *x, *y; + char *y; char **z; # endif # ifndef NO_CLOCK @@ -1555,7 +1609,8 @@ void run_one_test(void) GC_printf("GC_is_valid_displacement produced incorrect result\n"); FAIL; } - { + + { size_t i; void *p; @@ -1574,7 +1629,9 @@ void run_one_test(void) FAIL; } } - } + (void)GC_posix_memalign(&p, 64, 1); + AO_fetch_and_add1(&collectable_count); + } # ifndef GC_NO_VALLOC { void *p = GC_valloc(78); @@ -1609,6 +1666,49 @@ void run_one_test(void) } # endif # endif /* DBG_HDRS_ALL */ + x = GC_STRNDUP("abc", 1); + CHECK_OUT_OF_MEMORY(x); + AO_fetch_and_add1(&atomic_count); + if (strlen(x) != 1) { + GC_printf("GC_strndup unexpected result\n"); + FAIL; + } +# ifdef GC_REQUIRE_WCSDUP + { + static const wchar_t ws[] = { 'a', 'b', 'c', 0 }; + void *p = GC_WCSDUP(ws); + + CHECK_OUT_OF_MEMORY(p); + AO_fetch_and_add1(&atomic_count); + } +# endif +# ifndef GC_NO_FINALIZATION + if (!GC_get_find_leak()) { + void **p = (void **)GC_MALLOC_ATOMIC(sizeof(void*)); + + CHECK_OUT_OF_MEMORY(p); + AO_fetch_and_add1(&atomic_count); + *p = x; + if (GC_register_disappearing_link(p) != 0) { + GC_printf("GC_register_disappearing_link failed\n"); + FAIL; + } + if (GC_get_java_finalization()) { + GC_finalization_proc ofn = 0; + void *ocd = NULL; + + GC_REGISTER_FINALIZER_UNREACHABLE(p, dummy_finalizer, NULL, + &ofn, &ocd); + if (ofn != 0 || ocd != NULL) { + GC_printf("GC_register_finalizer_unreachable unexpected result\n"); + FAIL; + } + } +# ifndef GC_TOGGLE_REFS_NOT_NEEDED + (void)GC_toggleref_add(p, 1); +# endif + } +# endif /* Test floating point alignment */ { double *dp = GC_NEW(double); @@ -1620,6 +1720,9 @@ void run_one_test(void) CHECK_OUT_OF_MEMORY(dp); AO_fetch_and_add1(&collectable_count); *dp = 1.0; +# ifndef NO_DEBUGGING + (void)GC_count_set_marks_in_hblk(dp); +# endif } /* Test size 0 allocation a bit more */ { @@ -1707,7 +1810,7 @@ void run_one_test(void) if (print_stats) GC_log_printf("Starting tiny reverse test, pid= %ld\n", (long)child_pid); - tiny_reverse_test(0); + tiny_reverse_test_inner(); GC_gcollect(); # endif if (print_stats) @@ -1761,6 +1864,9 @@ void run_one_test(void) # endif /* Run reverse_test a second time, so we hopefully notice corruption. */ reverse_test(); +# ifndef NO_DEBUGGING + (void)GC_is_tmp_root((/* no volatile */ void *)&atomic_count); +# endif # ifndef NO_CLOCK if (print_stats) { GET_TIME(reverse_time); @@ -2066,7 +2172,6 @@ void enable_incremental_mode(void) } #if defined(CPPCHECK) -# include "gc/javaxfc.h" /* for GC_finalize_all */ # define UNTESTED(sym) GC_noop1((word)&sym) #endif @@ -2161,15 +2266,6 @@ void enable_incremental_mode(void) # endif # if defined(CPPCHECK) /* Entry points we should be testing, but aren't. */ -# ifndef GC_DEBUG - UNTESTED(GC_debug_generic_or_special_malloc); - UNTESTED(GC_debug_register_displacement); - UNTESTED(GC_post_incr); - UNTESTED(GC_pre_incr); -# ifdef GC_GCJ_SUPPORT - UNTESTED(GC_debug_gcj_malloc); -# endif -# endif # ifdef AMIGA # ifdef GC_AMIGA_FASTALLOC UNTESTED(GC_amiga_get_mem); @@ -2182,57 +2278,16 @@ void enable_incremental_mode(void) UNTESTED(GC_MacTemporaryNewPtr); # endif UNTESTED(GC_abort_on_oom); - UNTESTED(GC_debug_strndup); UNTESTED(GC_deinit); - UNTESTED(GC_strndup); - UNTESTED(GC_posix_memalign); - UNTESTED(GC_new_proc); - UNTESTED(GC_clear_roots); - UNTESTED(GC_exclude_static_roots); - UNTESTED(GC_register_describe_type_fn); - UNTESTED(GC_register_has_static_roots_callback); # ifndef NO_DEBUGGING - UNTESTED(GC_count_set_marks_in_hblk); UNTESTED(GC_dump); UNTESTED(GC_dump_regions); - UNTESTED(GC_is_tmp_root); UNTESTED(GC_print_free_list); # endif -# ifdef TRACE_BUF - UNTESTED(GC_print_trace); -# endif -# ifndef GC_NO_FINALIZATION - UNTESTED(GC_debug_register_finalizer_unreachable); - UNTESTED(GC_register_disappearing_link); - UNTESTED(GC_should_invoke_finalizers); -# ifndef JAVA_FINALIZATION_NOT_NEEDED - UNTESTED(GC_finalize_all); -# endif -# ifndef GC_TOGGLE_REFS_NOT_NEEDED - UNTESTED(GC_toggleref_add); -# endif -# endif -# if !defined(OS2) && !defined(MACOS) && !defined(GC_ANDROID_LOG) \ - && !defined(MSWIN32) && !defined(MSWINCE) - UNTESTED(GC_set_log_fd); -# endif -# ifndef REDIRECT_MALLOC_IN_HEADER -# ifdef REDIRECT_MALLOC -# ifndef strndup - UNTESTED(strndup); -# endif -# ifndef strdup - UNTESTED(strdup); -# endif -# endif -# ifdef REDIRECT_REALLOC - UNTESTED(realloc); -# endif -# endif /* !REDIRECT_MALLOC_IN_HEADER */ -# ifdef GC_REQUIRE_WCSDUP - UNTESTED(GC_wcsdup); - UNTESTED(GC_debug_wcsdup); -# endif +# endif +# if !defined(GC_ANDROID_LOG) && !defined(MACOS) && !defined(OS2) \ + && !defined(MSWIN32) && !defined(MSWINCE) + GC_set_log_fd(2); # endif # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) GC_win32_free_heap(); @@ -2415,13 +2470,6 @@ DWORD __stdcall thr_window(void *arg) # endif run_single_threaded_test(); check_heap_stats(); -# if defined(CPPCHECK) && defined(GC_WIN32_THREADS) - UNTESTED(GC_ExitThread); -# if !defined(MSWINCE) && !defined(CYGWIN32) - UNTESTED(GC_beginthreadex); - UNTESTED(GC_endthreadex); -# endif -# endif return 0; } @@ -2471,6 +2519,21 @@ void * thr_run_one_test(void *arg) return 0; } +void GC_CALLBACK describe_norm_type(void *p, char *out_buf) +{ + UNUSED_ARG(p); + BCOPY("NORMAL", out_buf, sizeof("NORMAL")); +} + +int GC_CALLBACK has_static_roots(const char *dlpi_name, + void *section_start, size_t section_size) +{ + UNUSED_ARG(dlpi_name); + UNUSED_ARG(section_start); + UNUSED_ARG(section_size); + return 1; +} + #ifdef GC_DEBUG # define GC_free GC_debug_free #endif @@ -2496,8 +2559,8 @@ int main(void) } # endif /* GC_HPUX_THREADS */ # ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np (); - pthread_win32_thread_attach_np (); + pthread_win32_process_attach_np(); + pthread_win32_thread_attach_np(); # endif # if defined(GC_DARWIN_THREADS) && !defined(GC_NO_THREADS_DISCOVERY) \ && !defined(DARWIN_DONT_PARSE_STACK) && !defined(THREAD_LOCAL_ALLOC) @@ -2539,6 +2602,16 @@ int main(void) FAIL; } set_print_procs(); + + /* Minimal testing of some API functions. */ + GC_exclude_static_roots((void *)&atomic_count, + (void *)((word)&atomic_count + sizeof(atomic_count))); + GC_register_has_static_roots_callback(has_static_roots); + GC_register_describe_type_fn(GC_I_NORMAL, describe_norm_type); +# ifdef GC_GCJ_SUPPORT + (void)GC_new_proc(fake_gcj_mark_proc); +# endif + # if NTHREADS > 0 for (i = 0; i < NTHREADS; ++i) { if ((code = pthread_create(th+i, &attr, thr_run_one_test, 0)) != 0) { @@ -2561,6 +2634,9 @@ int main(void) run_one_test(); # endif run_single_threaded_test(); +# ifdef TRACE_BUF + GC_print_trace(0); +# endif check_heap_stats(); (void)fflush(stdout); (void)pthread_attr_destroy(&attr); @@ -2613,31 +2689,36 @@ int main(void) # endif # if defined(CPPCHECK) UNTESTED(GC_register_altstack); - UNTESTED(GC_stop_world_external); - UNTESTED(GC_start_world_external); -# ifndef GC_NO_DLOPEN - UNTESTED(GC_dlopen); -# endif -# ifndef GC_NO_PTHREAD_CANCEL - UNTESTED(GC_pthread_cancel); -# endif -# ifdef GC_HAVE_PTHREAD_EXIT - UNTESTED(GC_pthread_exit); -# endif -# ifndef GC_NO_PTHREAD_SIGMASK - UNTESTED(GC_pthread_sigmask); -# endif -# ifdef NO_TEST_HANDLE_FORK - UNTESTED(GC_atfork_child); - UNTESTED(GC_atfork_parent); - UNTESTED(GC_atfork_prepare); - UNTESTED(GC_set_handle_fork); - UNTESTED(GC_start_mark_threads); -# endif # endif /* CPPCHECK */ + +# if !defined(GC_NO_DLOPEN) && !defined(DARWIN) \ + && !defined(GC_WIN32_THREADS) + { + void *h = GC_dlopen("libc.so", 0); + if (h != NULL) dlclose(h); + } +# endif +# ifndef GC_NO_PTHREAD_SIGMASK + { + sigset_t blocked; + + if (GC_pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0 + || GC_pthread_sigmask(SIG_BLOCK, &blocked, NULL) != 0) { + GC_printf("pthread_sigmask failed\n"); + FAIL; + } + } +# endif + GC_stop_world_external(); + GC_start_world_external(); +# if !defined(GC_NO_FINALIZATION) && !defined(JAVA_FINALIZATION_NOT_NEEDED) + GC_finalize_all(); +# endif + GC_clear_roots(); + # ifdef PTW32_STATIC_LIB - pthread_win32_thread_detach_np (); - pthread_win32_process_detach_np (); + pthread_win32_thread_detach_np(); + pthread_win32_process_detach_np(); # endif return 0; } |