📄 test.c
字号:
/* Harder to test under Windows without a gc.h declaration. */ { size_t i; extern void *GC_memalign(); GC_malloc(17); for (i = sizeof(GC_word); i < 512; i *= 2) { GC_word result = (GC_word) GC_memalign(i, 17); if (result % i != 0 || result == 0 || *(int *)result != 0) FAIL; } }# endif# ifndef ALL_INTERIOR_POINTERS# 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)) {# endif (void)GC_printf("GC_is_valid_displacement produced wrong failure indication\n"); FAIL; }# endif# 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;# ifdef GC_GCJ_SUPPORT GC_REGISTER_DISPLACEMENT(sizeof(struct fake_vtable *)); GC_init_gcj_malloc(0, (void *)fake_gcj_mark_proc);# endif /* Make sure that fn arguments are visible to the collector. */# ifdef __STDC__ uniq( GC_malloc(12), GC_malloc(12), GC_malloc(12), (GC_gcollect(),GC_malloc(12)), GC_malloc(12), GC_malloc(12), GC_malloc(12), (GC_gcollect(),GC_malloc(12)), GC_malloc(12), GC_malloc(12), GC_malloc(12), (GC_gcollect(),GC_malloc(12)), GC_malloc(12), GC_malloc(12), GC_malloc(12), (GC_gcollect(),GC_malloc(12)), GC_malloc(12), GC_malloc(12), GC_malloc(12), (GC_gcollect(),GC_malloc(12)), (void *)0);# endif /* GC_malloc(0) must return NULL or something we can deallocate. */ GC_free(GC_malloc(0)); GC_free(GC_malloc_atomic(0)); GC_free(GC_malloc(0)); GC_free(GC_malloc_atomic(0)); /* Repeated list reversal test. */ reverse_test();# ifdef PRINTSTATS GC_printf("-------------Finished reverse_test\n");# endif# ifndef DBG_HDRS_ALL typed_test();# ifdef PRINTSTATS GC_printf("-------------Finished typed_test\n");# endif# endif /* DBG_HDRS_ALL */ tree_test(); LOCK(); n_tests++; UNLOCK();# if defined(THREADS) && defined(HANDLE_FORK) if (fork() == 0) { GC_gcollect(); tiny_reverse_test(0); GC_gcollect(); GC_printf("Finished a child process\n"); exit(0); }# endif /* GC_printf("Finished %x\n", pthread_self()); */}void check_heap_stats(){ size_t max_heap_sz; int i; int still_live; int late_finalize_count = 0; # ifdef VERY_SMALL_CONFIG /* these are something of a guess */ if (sizeof(char *) > 4) { max_heap_sz = 4500000; } else { max_heap_sz = 2800000; }# else if (sizeof(char *) > 4) { max_heap_sz = 19000000; } else { max_heap_sz = 11000000; }# endif# ifdef GC_DEBUG max_heap_sz *= 2;# ifdef SAVE_CALL_CHAIN max_heap_sz *= 3;# ifdef SAVE_CALL_COUNT max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4;# endif# endif# endif /* Garbage collect repeatedly so that all inaccessible objects */ /* can be finalized. */ while (GC_collect_a_little()) { } for (i = 0; i < 16; i++) { GC_gcollect(); late_finalize_count += GC_invoke_finalizers(); } (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);# ifdef FINALIZE_ON_DEMAND if (finalized_count != late_finalize_count) { (void)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"); FAIL; } else { (void)GC_printf("finalization is probably ok\n"); } still_live = 0; for (i = 0; i < MAX_FINALIZED; i++) { if (live_indicators[i] != 0) { still_live++; } } 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); if (i > 10) { GC_printf("\tVery suspicious!\n"); } else { GC_printf("\tSlightly suspicious, but probably OK.\n"); } } (void)GC_printf("Total number of bytes allocated is %lu\n", (unsigned long) (GC_bytes_allocd + GC_bytes_allocd_before_gc)); (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# ifdef VERY_SMALL_CONFIG < 2700000*n_tests) {# else < 33500000*n_tests) {# endif (void)GC_printf("Incorrect execution - missed some allocations\n"); FAIL; } if (GC_get_heap_size() > max_heap_sz*n_tests) { (void)GC_printf("Unexpected heap growth - collector may be broken\n"); FAIL; } (void)GC_printf("Collector appears to work\n");}#if defined(MACOS)void SetMinimumStack(long minSize){ long newApplLimit; if (minSize > LMGetDefltStack()) { newApplLimit = (long) GetApplLimit() - (minSize - LMGetDefltStack()); SetApplLimit((Ptr) newApplLimit); MaxApplZone(); }}#define cMinStackSpace (512L * 1024L)#endif#ifdef __STDC__ void warn_proc(char *msg, GC_word p)#else void warn_proc(msg, p) char *msg; GC_word p;#endif{ GC_printf(msg, (unsigned long)p); /*FAIL;*/}#if !defined(PCR) \ && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \ || defined(LINT)#if defined(MSWIN32) && !defined(__MINGW32__) int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPTSTR cmd, int n)#else int main()#endif{# if defined(DJGPP) int dummy;# endif n_tests = 0; # if defined(DJGPP) /* No good way to determine stack base from library; do it */ /* manually on this platform. */ GC_stackbottom = (void *)(&dummy);# endif# if defined(MACOS) /* 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");# endif GC_INIT(); /* Only needed on a few platforms. */ (void) GC_set_warn_proc(warn_proc);# if (defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(GWW_VDB)) \ && !defined(MAKE_BACK_GRAPH) && !defined(NO_INCREMENTAL) GC_enable_incremental(); (void) GC_printf("Switched to incremental mode\n");# if defined(MPROTECT_VDB) (void)GC_printf("Emulating dirty bits with mprotect/signals\n");# else# ifdef PROC_VDB (void)GC_printf("Reading dirty bits from /proc\n");# else (void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n");# endif# endif# endif run_one_test(); check_heap_stats();# ifndef MSWINCE (void)fflush(stdout);# endif# ifdef LINT /* Entry points we should be testing, but aren't. */ /* Some can be tested by defining GC_DEBUG at the top of this file */ /* This is a bit SunOS4 specific. */ GC_noop(GC_expand_hp, GC_add_roots, GC_clear_roots, GC_register_disappearing_link, GC_register_finalizer_ignore_self, GC_debug_register_displacement, GC_print_obj, GC_debug_change_stubborn, GC_debug_end_stubborn_change, GC_debug_malloc_uncollectable, GC_debug_free, GC_debug_realloc, GC_generic_malloc_words_small, GC_init, GC_make_closure, GC_debug_invoke_finalizer, GC_page_was_ever_dirty, GC_is_fresh, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_max_heap_size, GC_get_bytes_since_gc, GC_get_total_bytes, GC_pre_incr, GC_post_incr);# endif# ifdef MSWIN32 GC_win32_free_heap();# endif return(0);}# endif#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)DWORD __stdcall thr_run_one_test(void *arg){ run_one_test(); return 0;}#ifdef MSWINCEHANDLE win_created_h;HWND win_handle;LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ LRESULT ret = 0; switch (uMsg) { case WM_HIBERNATE: GC_printf("Received WM_HIBERNATE, calling GC_gcollect\n"); GC_gcollect(); break; case WM_CLOSE: GC_printf("Received WM_CLOSE, closing window\n"); DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: ret = DefWindowProc(hwnd, uMsg, wParam, lParam); break; } return ret;}DWORD __stdcall thr_window(void *arg){ WNDCLASS win_class = { CS_NOCLOSE, window_proc, 0, 0, GetModuleHandle(NULL), NULL, NULL, (HBRUSH)(COLOR_APPWORKSPACE+1), NULL, L"GCtestWindow" }; MSG msg; if (!RegisterClass(&win_class)) FAIL; win_handle = CreateWindowEx( 0, L"GCtestWindow", L"GCtest", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); if (win_handle == NULL) FAIL; SetEvent(win_created_h); ShowWindow(win_handle, SW_SHOW); UpdateWindow(win_handle); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0;}#endif#define NTEST 2# ifdef MSWINCEint APIENTRY GC_WinMain(HINSTANCE instance, HINSTANCE prev, LPWSTR cmd, int n)# elseint APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)# endif{# if NTEST > 0 HANDLE h[NTEST]; int i;# endif# ifdef MSWINCE HANDLE win_thr_h;# endif DWORD thread_id;# ifdef GC_DLL GC_use_DllMain(); /* Test with implicit thread registration if possible. */ GC_printf("Using DllMain to track threads\n");# endif GC_INIT();# ifndef NO_INCREMENTAL GC_enable_incremental();# endif InitializeCriticalSection(&incr_cs); (void) GC_set_warn_proc(warn_proc);# ifdef MSWINCE win_created_h = CreateEvent(NULL, FALSE, FALSE, NULL); if (win_created_h == (HANDLE)NULL) { (void)GC_printf("Event creation failed %\n", 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", GetLastError()); FAIL; } if (WaitForSingleObject(win_created_h, INFINITE) != WAIT_OBJECT_0) FAIL; CloseHandle(win_created_h);# endif# if NTEST > 0 for (i = 0; i < NTEST; 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", GetLastError()); FAIL; } }# endif /* NTEST > 0 */ run_one_test();# if NTEST > 0 for (i = 0; i < NTEST; i++) { if (WaitForSingleObject(h[i], INFINITE) != WAIT_OBJECT_0) { (void)GC_printf("Thread wait failed %d\n", GetLastError()); FAIL; } }# endif /* NTEST > 0 */# ifdef MSWINCE PostMessage(win_handle, WM_CLOSE, 0, 0); if (WaitForSingleObject(win_thr_h, INFINITE) != WAIT_OBJECT_0) FAIL;# endif check_heap_stats(); return(0);}#endif /* GC_WIN32_THREADS */#ifdef PCRtest(){ PCR_Th_T * th1; PCR_Th_T * th2; int code; n_tests = 0; /* GC_enable_incremental(); */ (void) GC_set_warn_proc(warn_proc); th1 = PCR_Th_Fork(run_one_test, 0); th2 = PCR_Th_Fork(run_one_test, 0); 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"); } if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever) != PCR_ERes_okay || code != 0) { (void)GC_printf("Thread 2 failed\n"); } check_heap_stats(); return(0);}#endif#if defined(GC_PTHREADS)void * thr_run_one_test(void * arg){ run_one_test(); return(0);}#ifdef GC_DEBUG# define GC_free GC_debug_free#endifint main(){ pthread_t th1; pthread_t th2; pthread_attr_t attr; int code;# ifdef GC_IRIX_THREADS /* Force a larger stack to be preallocated */ /* Since the initial cant always grow later. */ *((volatile char *)&code - 1024*1024) = 0; /* Require 1 Mb */# endif /* GC_IRIX_THREADS */# if defined(GC_HPUX_THREADS) /* 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"); }# endif /* GC_HPUX_THREADS */# ifdef PTW32_STATIC_LIB pthread_win32_process_attach_np (); pthread_win32_thread_attach_np ();# endif GC_INIT(); pthread_attr_init(&attr);# if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \ || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) pthread_attr_setstacksize(&attr, 1000000);# endif n_tests = 0;# if (defined(MPROTECT_VDB)) \ && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) \ && !defined(MAKE_BACK_GRAPH) && !defined(USE_PROC_FOR_LIBRARIES) \ && !defined(NO_INCREMENTAL) GC_enable_incremental(); (void) GC_printf("Switched to incremental mode\n");# if defined(MPROTECT_VDB) (void)GC_printf("Emulating dirty bits with mprotect/signals\n");# else# ifdef PROC_VDB (void)GC_printf("Reading dirty bits from /proc\n");# else (void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n");# endif# endif# endif (void) GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { (void)GC_printf("Key creation failed %d\n", code); FAIL; } if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) { (void)GC_printf("Thread 1 creation failed %d\n", code); FAIL; } if ((code = pthread_create(&th2, &attr, thr_run_one_test, 0)) != 0) { (void)GC_printf("Thread 2 creation failed %d\n", code); FAIL; } run_one_test(); if ((code = pthread_join(th1, 0)) != 0) { (void)GC_printf("Thread 1 failed %d\n", code); FAIL; } if (pthread_join(th2, 0) != 0) { (void)GC_printf("Thread 2 failed %d\n", code); FAIL; } check_heap_stats(); (void)fflush(stdout); pthread_attr_destroy(&attr); GC_printf("Completed %d collections\n", GC_gc_no);# ifdef PTW32_STATIC_LIB pthread_win32_thread_detach_np (); pthread_win32_process_detach_np ();# endif return(0);}#endif /* GC_PTHREADS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -