📄 test.c
字号:
void check_ints(list, low, up)sexpr list;int low, up;{ if ((int)(GC_word)(car(car(list))) != low) { (void)GC_printf0( "List reversal produced incorrect list - collector is broken\n"); FAIL; } if (low == up) { if (cdr(list) != nil) { (void)GC_printf0("List too long - collector is broken\n"); FAIL; } } else { check_ints(cdr(list), low+1, up); }}# define UNCOLLECTABLE_CDR(x) (sexpr)(~(unsigned long)(cdr(x)))void check_uncollectable_ints(list, low, up)sexpr list;int low, up;{ if ((int)(GC_word)(car(car(list))) != low) { (void)GC_printf0( "Uncollectable list corrupted - collector is broken\n"); FAIL; } if (low == up) { if (UNCOLLECTABLE_CDR(list) != nil) { (void)GC_printf0("Uncollectable list too long - collector is broken\n"); FAIL; } } else { check_uncollectable_ints(UNCOLLECTABLE_CDR(list), low+1, up); }}/* Not used, but useful for debugging: */void print_int_list(x)sexpr x;{ if (is_nil(x)) { (void)GC_printf0("NIL\n"); } else { (void)GC_printf1("(%ld)", (long)(car(car(x)))); if (!is_nil(cdr(x))) { (void)GC_printf0(", "); (void)print_int_list(cdr(x)); } else { (void)GC_printf0("\n"); } }}/* * A tiny list reversal test to check thread creation. */#ifdef THREADS# if defined(GC_WIN32_THREADS) && !defined(CYGWIN32) DWORD __stdcall tiny_reverse_test(void * arg)# else void * tiny_reverse_test(void * arg)# endif{ int i; for (i = 0; i < 5; ++i) { check_ints(reverse(reverse(ints(1,10))), 1, 10);# ifdef THREAD_LOCAL_ALLOC check_ints(local_reverse(local_reverse(local_ints(1,10))), 1, 10);# endif } return 0;}# if defined(GC_PTHREADS) void fork_a_thread() { pthread_t t; int code; if ((code = pthread_create(&t, 0, tiny_reverse_test, 0)) != 0) { (void)GC_printf1("Small thread creation failed %lu\n", (unsigned long)code); FAIL; } if ((code = pthread_join(t, 0)) != 0) { (void)GC_printf1("Small thread join failed %lu\n", (unsigned long)code); FAIL; } }# elif defined(GC_WIN32_THREADS) void fork_a_thread() { DWORD thread_id; HANDLE h; h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id); if (h == (HANDLE)NULL) { (void)GC_printf1("Small thread creation failed %lu\n", (unsigned long)GetLastError()); FAIL; } if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) { (void)GC_printf1("Small thread wait failed %lu\n", (unsigned long)GetLastError()); FAIL; } }/* # elif defined(GC_SOLARIS_THREADS) */# else# define fork_a_thread()# endif#else# define fork_a_thread()#endif /* Try to force a to be strangely aligned */struct { char dummy; sexpr aa;} A;#define a A.aa/* * Repeatedly reverse lists built out of very different sized cons cells. * Check that we didn't lose anything. */void reverse_test(){ int i; sexpr b; sexpr c; sexpr d; sexpr e; sexpr *f, *g, *h;# if defined(MSWIN32) || defined(MACOS) /* Win32S only allows 128K stacks */# define BIG 1000# 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# endif A.dummy = 17; a = ints(1, 49); b = ints(1, 50); c = ints(1, BIG); d = uncollectable_ints(1, 100); e = uncollectable_ints(1, 1); /* Check that realloc updates object descriptors correctly */ collectable_count++; f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr)); realloc_count++; f = (sexpr *)GC_REALLOC((GC_PTR)f, 6 * sizeof(sexpr)); f[5] = ints(1,17); collectable_count++; g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr)); realloc_count++; g = (sexpr *)GC_REALLOC((GC_PTR)g, 800 * sizeof(sexpr)); g[799] = ints(1,18); collectable_count++; h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr)); realloc_count++; h = (sexpr *)GC_REALLOC((GC_PTR)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));# ifdef THREAD_LOCAL_ALLOC a = local_reverse(local_reverse(a));# endif# if !defined(AT_END) && !defined(THREADS) /* This is not thread safe, since realloc explicitly deallocates */ if (i & 1) { a = (sexpr)GC_REALLOC((GC_PTR)a, 500); } else { a = (sexpr)GC_REALLOC((GC_PTR)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_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) static mutex_t incr_lock; mutex_lock(&incr_lock);# endif# if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock);# else# ifdef GC_WIN32_THREADS EnterCriticalSection(&incr_cs);# endif# endif if ((int)(GC_word)client_data != t -> level) { (void)GC_printf0("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_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) mutex_unlock(&incr_lock);# endif# if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock);# else# ifdef GC_WIN32_THREADS LeaveCriticalSection(&incr_cs);# endif# 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(n)int n;{# ifdef THREAD_LOCAL_ALLOC tn * result = (tn *)GC_LOCAL_MALLOC(sizeof(tn));# else tn * result = (tn *)GC_MALLOC(sizeof(tn));# endif collectable_count++;# ifdef THREAD_LOCAL_ALLOC /* Minimally exercise thread local allocation */ { char * result = (char *)GC_LOCAL_MALLOC_ATOMIC(17); memset(result, 'a', 17); }# endif /* THREAD_LOCAL_ALLOC */# 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_printf0("Out of memory\n"); exit(1); }# endif if (n == 0) return(0); if (result == 0) { (void)GC_printf0("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_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) static mutex_t incr_lock; mutex_lock(&incr_lock);# endif# if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock);# else# ifdef GC_WIN32_THREADS EnterCriticalSection(&incr_cs);# endif# 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_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) mutex_unlock(&incr_lock);# endif# if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock);# else# ifdef GC_WIN32_THREADS LeaveCriticalSection(&incr_cs);# endif# endif } GC_REGISTER_FINALIZER((GC_PTR)result, finalizer, (GC_PTR)(GC_word)n, (GC_finalization_proc *)0, (GC_PTR *)0); if (my_index >= MAX_FINALIZED) { GC_printf0("live_indicators overflowed\n"); FAIL; } live_indicators[my_index] = 13; if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( (GC_PTR *)(&(live_indicators[my_index])), (GC_PTR)result) != 0) { GC_printf0("GC_general_register_disappearing_link failed\n"); FAIL; } if (GC_unregister_disappearing_link( (GC_PTR *) (&(live_indicators[my_index]))) == 0) { GC_printf0("GC_unregister_disappearing_link failed\n"); FAIL; } if (GC_GENERAL_REGISTER_DISAPPEARING_LINK( (GC_PTR *)(&(live_indicators[my_index])), (GC_PTR)result) != 0) { GC_printf0("GC_general_register_disappearing_link failed 2\n"); FAIL; } } return(result);}void chktree(t,n)tn *t;int n;{ if (n == 0 && t != 0) { (void)GC_printf0("Clobbered a leaf - collector is broken\n"); FAIL; } if (n == 0) return; if (t -> level != n) { (void)GC_printf1("Lost a node at level %lu - collector is broken\n", (unsigned long)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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -