📄 test.c
字号:
/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996 by Silicon Graphics. All rights reserved. * * 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. *//* An incomplete test for the garbage collector. *//* Some more obscure entry points are not tested at all. *//* This must be compiled with the same flags used to build the *//* GC. It uses GC internals to allow more precise results *//* checking for some of the tests. */# undef GC_BUILD#if defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)# define GC_DEBUG#endif# if defined(mips) && defined(SYSTYPE_BSD43) /* MIPS RISCOS 4 */# else# include <stdlib.h># endif# include <stdio.h># ifdef _WIN32_WCE# include <winbase.h># define assert ASSERT# else# include <assert.h> /* Not normally used, but handy for debugging. */# endif# include <assert.h> /* Not normally used, but handy for debugging. */# include "gc.h"# include "gc_typed.h"# ifdef THREAD_LOCAL_ALLOC# include "gc_local_alloc.h"# endif# include "private/gc_priv.h" /* For output, locking, MIN_WORDS, */ /* and some statistics. */# include "private/gcconfig.h"# if defined(MSWIN32) || defined(MSWINCE)# include <windows.h># endif# ifdef PCR# include "th/PCR_ThCrSec.h"# include "th/PCR_Th.h"# undef GC_printf0# define GC_printf0 printf# undef GC_printf1# define GC_printf1 printf# endif# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)# include <thread.h># include <synch.h># endif# if defined(GC_PTHREADS)# include <pthread.h># endif# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) static CRITICAL_SECTION incr_cs;# endif#ifdef __STDC__# include <stdarg.h>#endif/* Allocation Statistics */int stubborn_count = 0;int uncollectable_count = 0;int collectable_count = 0;int atomic_count = 0;int realloc_count = 0;#if defined(GC_AMIGA_FASTALLOC) && defined(AMIGA) extern void GC_amiga_free_all_mem(void); void Amiga_Fail(void){GC_amiga_free_all_mem();abort();}# define FAIL (void)Amiga_Fail() void *GC_amiga_gctest_malloc_explicitly_typed(size_t lb, GC_descr d){ void *ret=GC_malloc_explicitly_typed(lb,d); if(ret==NULL){ if(!GC_dont_gc){ GC_gcollect(); ret=GC_malloc_explicitly_typed(lb,d); } if(ret==NULL){ GC_printf0("Out of memory, (typed allocations are not directly " "supported with the GC_AMIGA_FASTALLOC option.)\n"); FAIL; } } return ret; } void *GC_amiga_gctest_calloc_explicitly_typed(size_t a,size_t lb, GC_descr d){ void *ret=GC_calloc_explicitly_typed(a,lb,d); if(ret==NULL){ if(!GC_dont_gc){ GC_gcollect(); ret=GC_calloc_explicitly_typed(a,lb,d); } if(ret==NULL){ GC_printf0("Out of memory, (typed allocations are not directly " "supported with the GC_AMIGA_FASTALLOC option.)\n"); FAIL; } } return ret; }# define GC_malloc_explicitly_typed(a,b) GC_amiga_gctest_malloc_explicitly_typed(a,b) # define GC_calloc_explicitly_typed(a,b,c) GC_amiga_gctest_calloc_explicitly_typed(a,b,c) #else /* !AMIGA_FASTALLOC */# ifdef PCR# define FAIL (void)abort()# else# ifdef MSWINCE# define FAIL DebugBreak()# else# define FAIL GC_abort("Test failed");# endif# endif#endif /* !AMIGA_FASTALLOC *//* AT_END may be defined to exercise the interior pointer test *//* if the collector is configured with ALL_INTERIOR_POINTERS. *//* As it stands, this test should succeed with either *//* configuration. In the FIND_LEAK configuration, it should *//* find lots of leaks, since we free almost nothing. */struct SEXPR { struct SEXPR * sexpr_car; struct SEXPR * sexpr_cdr;};typedef struct SEXPR * sexpr;# define INT_TO_SEXPR(x) ((sexpr)(unsigned long)(x))# undef nil# define nil (INT_TO_SEXPR(0))# define car(x) ((x) -> sexpr_car)# define cdr(x) ((x) -> sexpr_cdr)# define is_nil(x) ((x) == nil)int extra_count = 0; /* Amount of space wasted in cons node *//* Silly implementation of Lisp cons. Intentionally wastes lots of space *//* to test collector. */# ifdef VERY_SMALL_CONFIG# define cons small_cons# elsesexpr cons (x, y)sexpr x;sexpr y;{ register sexpr r; register int *p; register int my_extra = extra_count; stubborn_count++; r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra); if (r == 0) { (void)GC_printf0("Out of memory\n"); exit(1); } for (p = (int *)r; ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) { if (*p) { (void)GC_printf1("Found nonzero at 0x%lx - allocator is broken\n", (unsigned long)p); FAIL; } *p = 13; }# ifdef AT_END r = (sexpr)((char *)r + (my_extra & ~7));# endif r -> sexpr_car = x; r -> sexpr_cdr = y; my_extra++; if ( my_extra >= 5000 ) { extra_count = 0; } else { extra_count = my_extra; } GC_END_STUBBORN_CHANGE((char *)r); return(r);}# endif#ifdef GC_GCJ_SUPPORT#include "gc_mark.h"#include "gc_gcj.h"/* The following struct emulates the vtable in gcj. *//* This assumes the default value of MARK_DESCR_OFFSET. */struct fake_vtable { void * dummy; /* class pointer in real gcj. */ size_t descr;};struct fake_vtable gcj_class_struct1 = { 0, sizeof(struct SEXPR) + sizeof(struct fake_vtable *) }; /* length based descriptor. */struct fake_vtable gcj_class_struct2 = { 0, (3l << (CPP_WORDSZ - 3)) | GC_DS_BITMAP}; /* Bitmap based descriptor. */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 ){ sexpr x; if (1 == env) { /* Object allocated with debug allocator. */ addr = (word *)GC_USR_PTR_FROM_BASE(addr); } x = (sexpr)(addr + 1); /* Skip the vtable pointer. */ mark_stack_ptr = GC_MARK_AND_PUSH( (GC_PTR)(x -> sexpr_cdr), mark_stack_ptr, mark_stack_limit, (GC_PTR *)&(x -> sexpr_cdr)); mark_stack_ptr = GC_MARK_AND_PUSH( (GC_PTR)(x -> sexpr_car), mark_stack_ptr, mark_stack_limit, (GC_PTR *)&(x -> sexpr_car)); return(mark_stack_ptr);}#endif /* GC_GCJ_SUPPORT */#ifdef THREAD_LOCAL_ALLOC#undef GC_REDIRECT_TO_LOCAL#include "gc_local_alloc.h"sexpr local_cons (x, y)sexpr x;sexpr y;{ register sexpr r; register int *p; register int my_extra = extra_count; static int my_random = 0; collectable_count++; r = (sexpr) GC_LOCAL_MALLOC(sizeof(struct SEXPR) + my_extra);# ifdef GC_GCJ_SUPPORT if (collectable_count % 2 == 0) { r = (sexpr) GC_LOCAL_GCJ_MALLOC(sizeof(struct SEXPR) + sizeof(GC_word) + my_extra, &gcj_class_struct1); r = (sexpr) ((GC_word *)r + 1); }# endif if (r == 0) { (void)GC_printf0("Out of memory\n"); exit(1); } for (p = (int *)r; ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) { if (*p) { (void)GC_printf1("Found nonzero at 0x%lx (local) - allocator is broken\n", (unsigned long)p); FAIL; } *p = 13; } r -> sexpr_car = x; r -> sexpr_cdr = y; my_extra++; if ( my_extra >= 5000 || my_extra == 200 && ++my_random % 37 != 0) { extra_count = 0; } else { extra_count = my_extra; } return(r);}#endif /* THREAD_LOCAL_ALLOC */sexpr small_cons (x, y)sexpr x;sexpr y;{ register sexpr r; collectable_count++; r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); if (r == 0) { (void)GC_printf0("Out of memory\n"); exit(1); } r -> sexpr_car = x; r -> sexpr_cdr = y; return(r);}sexpr small_cons_uncollectable (x, y)sexpr x;sexpr y;{ register sexpr r; uncollectable_count++; r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); if (r == 0) { (void)GC_printf0("Out of memory\n"); exit(1); } r -> sexpr_car = x; r -> sexpr_cdr = (sexpr)(~(unsigned long)y); return(r);}#ifdef GC_GCJ_SUPPORTsexpr gcj_cons(x, y)sexpr x;sexpr y;{ GC_word * r; sexpr result; static int count = 0; if (++count & 1) {# ifdef USE_MARK_BYTES r = (GC_word *) GC_GCJ_FAST_MALLOC(4, &gcj_class_struct1);# else r = (GC_word *) GC_GCJ_FAST_MALLOC(3, &gcj_class_struct1);# endif } else { r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR) + sizeof(struct fake_vtable*), &gcj_class_struct2); } if (r == 0) { (void)GC_printf0("Out of memory\n"); exit(1); } result = (sexpr)(r + 1); result -> sexpr_car = x; result -> sexpr_cdr = y; return(result);}#endif/* Return reverse(x) concatenated with y */sexpr reverse1(x, y)sexpr x, y;{ if (is_nil(x)) { return(y); } else { return( reverse1(cdr(x), cons(car(x), y)) ); }}sexpr reverse(x)sexpr x;{# ifdef TEST_WITH_SYSTEM_MALLOC malloc(100000);# endif return( reverse1(x, nil) );}sexpr ints(low, up)int low, up;{ if (low > up) { return(nil); } else { return(small_cons(small_cons(INT_TO_SEXPR(low), nil), ints(low+1, up))); }}#ifdef GC_GCJ_SUPPORT/* Return reverse(x) concatenated with y */sexpr gcj_reverse1(x, y)sexpr x, y;{ if (is_nil(x)) { return(y); } else { return( gcj_reverse1(cdr(x), gcj_cons(car(x), y)) ); }}sexpr gcj_reverse(x)sexpr x;{ return( gcj_reverse1(x, nil) );}sexpr gcj_ints(low, up)int low, up;{ if (low > up) { return(nil); } else { return(gcj_cons(gcj_cons(INT_TO_SEXPR(low), nil), gcj_ints(low+1, up))); }}#endif /* GC_GCJ_SUPPORT */#ifdef THREAD_LOCAL_ALLOC/* Return reverse(x) concatenated with y */sexpr local_reverse1(x, y)sexpr x, y;{ if (is_nil(x)) { return(y); } else { return( local_reverse1(cdr(x), local_cons(car(x), y)) ); }}sexpr local_reverse(x)sexpr x;{ return( local_reverse1(x, nil) );}sexpr local_ints(low, up)int low, up;{ if (low > up) { return(nil); } else { return(local_cons(local_cons(INT_TO_SEXPR(low), nil), local_ints(low+1, up))); }}#endif /* THREAD_LOCAL_ALLOC *//* To check uncollectable allocation we build lists with disguised cdr *//* pointers, and make sure they don't go away. */sexpr uncollectable_ints(low, up)int low, up;{ if (low > up) { return(nil); } else { return(small_cons_uncollectable(small_cons(INT_TO_SEXPR(low), nil), uncollectable_ints(low+1, up))); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -