📄 test.c
字号:
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));# ifdef GC_GCJ_SUPPORT h[1999] = gcj_ints(1,200); for (i = 0; i < 51; ++i) h[1999] = gcj_reverse(h[1999]); /* Leave it as the reveresed list for now. */# else 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); } /* Superficially test interior pointer recognition on stack */ c = (sexpr)((char *)c + sizeof(char *)); d = (sexpr)((char *)d + sizeof(char *));# ifdef __STDC__ GC_FREE((void *)e);# else GC_FREE((char *)e);# endif check_ints(b,1,50); check_ints(a,1,49); for (i = 0; i < 50; i++) { check_ints(b,1,50); b = reverse(reverse(b)); } check_ints(b,1,50); check_ints(a,1,49); for (i = 0; i < 60; i++) { if (i % 10 == 0) fork_a_thread(); /* This maintains the invariant that a always points to a list of */ /* 49 integers. Thus this is thread safe without locks, */ /* assuming atomic pointer assignments. */ a = reverse(reverse(a));# if !defined(AT_END) && !defined(THREADS) /* This is not thread safe, since realloc explicitly deallocates */ if (i & 1) { a = (sexpr)GC_REALLOC((void *)a, 500); } else { a = (sexpr)GC_REALLOC((void *)a, 8200); }# endif } check_ints(a,1,49); check_ints(b,1,50); 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); check_ints(g[799], 1,18);# ifdef GC_GCJ_SUPPORT h[1999] = gcj_reverse(h[1999]);# endif check_ints(h[1999], 1,200);# ifndef THREADS a = 0;# endif b = c = 0;}#undef a/* * The rest of this builds balanced binary trees, checks that they don't * disappear, and tests finalization. */typedef struct treenode { int level; struct treenode * lchild; struct treenode * rchild;} tn;int finalizable_count = 0;int finalized_count = 0;volatile int dropped_something = 0;# ifdef __STDC__ void finalizer(void * obj, void * client_data)# else void finalizer(obj, client_data) char * obj; char * client_data;# endif{ tn * t = (tn *)obj;# ifdef PCR PCR_ThCrSec_EnterSys();# endif# if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock);# elif defined(GC_WIN32_THREADS) EnterCriticalSection(&incr_cs);# endif if ((int)(GC_word)client_data != t -> level) { (void)GC_printf("Wrong finalization data - collector is broken\n"); FAIL; } finalized_count++; t -> level = -1; /* detect duplicate finalization immediately */# ifdef PCR PCR_ThCrSec_ExitSys();# endif# if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock);# elif defined(GC_WIN32_THREADS) LeaveCriticalSection(&incr_cs);# endif}size_t counter = 0;# define MAX_FINALIZED 8000# if !defined(MACOS) GC_FAR GC_word live_indicators[MAX_FINALIZED] = {0};#else /* Too big for THINK_C. have to allocate it dynamically. */ GC_word *live_indicators = 0;#endifint live_indicators_count = 0;tn * mktree(int n){ tn * result = (tn *)GC_MALLOC(sizeof(tn)); 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) { (void)GC_printf("Out of memory\n"); exit(1); }# endif if (n == 0) return(0); if (result == 0) { (void)GC_printf("Out of memory\n"); exit(1); } result -> level = n; result -> lchild = mktree(n-1); result -> rchild = mktree(n-1); if (counter++ % 17 == 0 && n >= 2) { tn * tmp = result -> lchild -> rchild; result -> lchild -> rchild = result -> rchild -> lchild; result -> rchild -> lchild = tmp; } if (counter++ % 119 == 0) { int my_index; {# ifdef PCR PCR_ThCrSec_EnterSys();# endif# if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock);# elif defined(GC_WIN32_THREADS) EnterCriticalSection(&incr_cs);# endif /* Losing a count here causes erroneous report of failure. */ finalizable_count++; my_index = live_indicators_count++;# ifdef PCR PCR_ThCrSec_ExitSys();# endif# if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock);# elif defined(GC_WIN32_THREADS) LeaveCriticalSection(&incr_cs);# endif } 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; } live_indicators[my_index] = 13; if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( (void * *)(&(live_indicators[my_index])), (void *)result) != 0) { GC_printf("GC_general_register_disappearing_link failed\n"); FAIL; } if (GC_unregister_disappearing_link( (void * *) (&(live_indicators[my_index]))) == 0) { GC_printf("GC_unregister_disappearing_link failed\n"); FAIL; } if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( (void * *)(&(live_indicators[my_index])), (void *)result) != 0) { GC_printf("GC_general_register_disappearing_link failed 2\n"); FAIL; } GC_reachable_here(result); } return(result);}void chktree(tn *t, int n){ if (n == 0 && t != 0) { (void)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); FAIL; } if (counter++ % 373 == 0) { collectable_count++; (void) GC_MALLOC(counter%5001); } chktree(t -> lchild, n-1); if (counter++ % 73 == 0) { collectable_count++; (void) GC_MALLOC(counter%373); } chktree(t -> rchild, n-1);}#if defined(GC_PTHREADS)pthread_key_t fl_key;void * alloc8bytes(){# if defined(SMALL_CONFIG) || defined(GC_DEBUG) collectable_count++; return(GC_MALLOC(8));# else void ** my_free_list_ptr; void * my_free_list; my_free_list_ptr = (void **)pthread_getspecific(fl_key); if (my_free_list_ptr == 0) { 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"); FAIL; } } my_free_list = *my_free_list_ptr; 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"); FAIL; } } *my_free_list_ptr = GC_NEXT(my_free_list); GC_NEXT(my_free_list) = 0; collectable_count++; return(my_free_list);# endif}#else# define alloc8bytes() GC_MALLOC_ATOMIC(8)#endifvoid alloc_small(int n){ int i; for (i = 0; i < n; i += 8) { atomic_count++; if (alloc8bytes() == 0) { (void)GC_printf("Out of memory\n"); FAIL; } }}# if defined(THREADS) && defined(GC_DEBUG)# ifdef VERY_SMALL_CONFIG# define TREE_HEIGHT 12# else# define TREE_HEIGHT 15# endif# else# ifdef VERY_SMALL_CONFIG# define TREE_HEIGHT 13# else# define TREE_HEIGHT 16# endif# endifvoid tree_test(){ tn * root; int i; root = mktree(TREE_HEIGHT);# ifndef VERY_SMALL_CONFIG alloc_small(5000000);# endif chktree(root, TREE_HEIGHT); if (finalized_count && ! dropped_something) { (void)GC_printf("Premature finalization - collector is broken\n"); FAIL; } dropped_something = 1; GC_noop(root); /* Root needs to remain live until */ /* dropped_something is set. */ root = mktree(TREE_HEIGHT); chktree(root, TREE_HEIGHT); for (i = TREE_HEIGHT; i >= 0; i--) { root = mktree(i); chktree(root, i); }# ifndef VERY_SMALL_CONFIG alloc_small(5000000);# endif}unsigned n_tests = 0;GC_word bm_huge[10] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00ffffff,};/* A very simple test of explicitly typed allocation */void typed_test(){ GC_word * old, * new; GC_word bm3 = 0x3; GC_word bm2 = 0x2; GC_word bm_large = 0xf7ff7fff; GC_descr d1 = GC_make_descriptor(&bm3, 2); GC_descr d2 = GC_make_descriptor(&bm2, 2); GC_descr d3 = GC_make_descriptor(&bm_large, 32); GC_descr d4 = GC_make_descriptor(bm_huge, 320); GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4); int i; # ifndef LINT (void)GC_make_descriptor(&bm_large, 32);# endif collectable_count++; old = 0; for (i = 0; i < 4000; i++) { collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1); if (0 != new[0] || 0 != new[1]) { GC_printf("Bad initialization by GC_malloc_explicitly_typed\n"); FAIL; } new[0] = 17; new[1] = (GC_word)old; old = new; collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2); new[0] = 17; new[1] = (GC_word)old; old = new; collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3); 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); new[0] = 17; new[1] = (GC_word)old; old = new; collectable_count++; if (i & 0xff) { new = (GC_word *) GC_calloc_explicitly_typed(7, 3 * sizeof(GC_word), d2); } else { new = (GC_word *) GC_calloc_explicitly_typed(1001, 3 * sizeof(GC_word), d2); if (0 != new[0] || 0 != new[1]) { GC_printf("Bad initialization by GC_malloc_explicitly_typed\n"); FAIL; } } new[0] = 17; new[1] = (GC_word)old; old = new; } for (i = 0; i < 20000; i++) { if (new[0] != 17) { (void)GC_printf("typed alloc failed at %lu\n", (unsigned long)i); FAIL; } new[0] = 0; old = new; new = (GC_word *)(old[1]); } GC_gcollect(); GC_noop(x);}int fail_count = 0;#ifndef __STDC__/*ARGSUSED*/void fail_proc1(x)void * x;{ fail_count++;}#else/*ARGSUSED*/void fail_proc1(void * x){ fail_count++;} static void uniq(void *p, ...) { va_list a; void *q[100]; int n = 0, i, j; q[n++] = p; va_start(a,p); for (;(q[n] = va_arg(a,void *));n++) ; va_end(a); for (i=0; i<n; i++) for (j=0; j<i; j++) if (q[i] == q[j]) { GC_printf( "Apparently failed to mark from some function arguments.\n" "Perhaps GC_push_regs was configured incorrectly?\n" ); FAIL; }}#endif /* __STDC__ */#ifdef THREADS# define TEST_FAIL_COUNT(n) 1#else # define TEST_FAIL_COUNT(n) (fail_count >= (n))#endifvoid run_one_test(){ char *x;# ifdef LINT char *y = 0;# else char *y = (char *)(size_t)fail_proc1;# endif DCL_LOCK_STATE; # ifdef FIND_LEAK (void)GC_printf( "This test program is not designed for leak detection mode\n"); (void)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) { (void)GC_printf("GC_size produced unexpected results\n"); FAIL; } collectable_count += 1; if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) { (void)GC_printf("GC_malloc(0) failed: GC_size returns %ld\n", (unsigned long)GC_size(GC_malloc(0))); FAIL; } collectable_count += 1; if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) { (void)GC_printf("GC_malloc_uncollectable(0) failed\n"); FAIL; } GC_is_valid_displacement_print_proc = fail_proc1; GC_is_visible_print_proc = fail_proc1; collectable_count += 1; x = GC_malloc(16); if (GC_base(x + 13) != x) { (void)GC_printf("GC_base(heap ptr) produced incorrect result\n"); FAIL; }# ifndef PCR if (GC_base(y) != 0) { (void)GC_printf("GC_base(fn_ptr) produced incorrect result\n"); FAIL; }# endif if (GC_same_obj(x+5, x) != x + 5) { (void)GC_printf("GC_same_obj produced incorrect result\n"); FAIL; } if (GC_is_visible(y) != y || GC_is_visible(x) != x) { (void)GC_printf("GC_is_visible produced incorrect result\n"); FAIL; } if (!TEST_FAIL_COUNT(1)) {# if!(defined(RS6000) || defined(POWERPC) || defined(IA64)) || defined(M68K) /* ON RS6000s function pointers point to a descriptor in the */ /* data segment, so there should have been no failures. */ /* The same applies to IA64. Something similar seems to */ /* be going on with NetBSD/M68K. */ (void)GC_printf("GC_is_visible produced wrong failure indication\n"); FAIL;# endif } if (GC_is_valid_displacement(y) != y || GC_is_valid_displacement(x) != x || GC_is_valid_displacement(x + 3) != x + 3) { (void)GC_printf( "GC_is_valid_displacement produced incorrect result\n"); FAIL; }# if defined(__STDC__) && !defined(MSWIN32) && !defined(MSWINCE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -