00001
00002
00003 # include <stdlib.h>
00004 # include <stdio.h>
00005 # include "gc.h"
00006 # ifdef PCR
00007 # include "th/PCR_ThCrSec.h"
00008 # include "th/PCR_Th.h"
00009 # endif
00010
00011
00012
00013
00014
00015
00016
00017 struct SEXPR {
00018 struct SEXPR * sexpr_car;
00019 struct SEXPR * sexpr_cdr;
00020 };
00021
00022 # ifdef __STDC__
00023 typedef void * void_star;
00024 # else
00025 typedef char * void_star;
00026 # endif
00027
00028 typedef struct SEXPR * sexpr;
00029
00030 extern sexpr cons();
00031
00032 # define nil ((sexpr) 0)
00033 # define car(x) ((x) -> sexpr_car)
00034 # define cdr(x) ((x) -> sexpr_cdr)
00035 # define is_nil(x) ((x) == nil)
00036
00037
00038 int extra_count = 0;
00039
00040
00041
00042 sexpr cons (x, y)
00043 sexpr x;
00044 sexpr y;
00045 {
00046 register sexpr r;
00047 register int *p;
00048 register my_extra = extra_count;
00049
00050 r = (sexpr) GC_MALLOC(sizeof(struct SEXPR) + my_extra);
00051 if (r == 0) {
00052 (void)printf("Out of memory\n");
00053 exit(1);
00054 }
00055 for (p = (int *)r;
00056 ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
00057 if (*p) {
00058 (void)printf("Found nonzero at %X\n - allocator is broken", p);
00059 exit(1);
00060 }
00061 *p = 13;
00062 }
00063 # ifdef AT_END
00064 r = (sexpr)((char *)r + (my_extra & ~7));
00065 # endif
00066 r -> sexpr_car = x;
00067 r -> sexpr_cdr = y;
00068 extra_count = (my_extra + 1) % 5000;
00069 return(r);
00070 }
00071
00072
00073 sexpr reverse1(x, y)
00074 sexpr x, y;
00075 {
00076 if (is_nil(x)) {
00077 return(y);
00078 } else {
00079 return( reverse1(cdr(x), cons(car(x), y)) );
00080 }
00081 }
00082
00083 sexpr reverse(x)
00084 sexpr x;
00085 {
00086 return( reverse1(x, nil) );
00087 }
00088
00089 sexpr ints(low, up)
00090 int low, up;
00091 {
00092 if (low > up) {
00093 return(nil);
00094 } else {
00095 return(cons((sexpr)low, ints(low+1, up)));
00096 }
00097 }
00098
00099 void check_ints(list, low, up)
00100 sexpr list;
00101 int low, up;
00102 {
00103 if ((int)(car(list)) != low) {
00104 (void)printf(
00105 "List reversal produced incorrect list - collector is broken\n");
00106 exit(1);
00107 }
00108 if (low == up) {
00109 if (cdr(list) != nil) {
00110 (void)printf("List too long - collector is broken\n");
00111 exit(1);
00112 }
00113 } else {
00114 check_ints(cdr(list), low+1, up);
00115 }
00116 }
00117
00118
00119 void print_int_list(x)
00120 sexpr x;
00121 {
00122 if (is_nil(x)) {
00123 (void)printf("NIL\n");
00124 } else {
00125 (void)printf("%d", car(x));
00126 if (!is_nil(cdr(x))) {
00127 (void)printf(", ");
00128 (void)print_int_list(cdr(x));
00129 } else {
00130 (void)printf("\n");
00131 }
00132 }
00133 }
00134
00135
00136 struct {
00137 char dummy;
00138 sexpr aa;
00139 } A;
00140 #define a A.aa
00141
00142
00143
00144
00145
00146 reverse_test()
00147 {
00148 int i;
00149 sexpr b;
00150
00151 a = ints(1, 100);
00152 b = ints(1, 50);
00153 for (i = 0; i < 50; i++) {
00154 b = reverse(reverse(b));
00155 }
00156 for (i = 0; i < 10; i++) {
00157
00158
00159 a = reverse(reverse(a));
00160 # if !defined(AT_END) && !defined(PCR)
00161
00162 if (i & 1) {
00163 a = (sexpr)GC_REALLOC((void_star)a, 500);
00164 } else {
00165 a = (sexpr)GC_REALLOC((void_star)a, 4200);
00166 }
00167 # endif
00168 }
00169 check_ints(a,1,100);
00170 check_ints(b,1,50);
00171 a = b = 0;
00172 }
00173
00174
00175
00176
00177
00178 typedef struct treenode {
00179 int level;
00180 struct treenode * lchild;
00181 struct treenode * rchild;
00182 } tn;
00183
00184 int finalizable_count = 0;
00185 int finalized_count = 0;
00186 int dropped_something = 0;
00187
00188 # ifdef __STDC__
00189 void finalizer(void * obj, void * client_data)
00190 # else
00191 void finalizer(obj, client_data)
00192 char * obj;
00193 char * client_data;
00194 # endif
00195 {
00196 tn * t = (tn *)obj;
00197 if ((int)client_data != t -> level) {
00198 (void)printf("Wrong finalization data - collector is broken\n");
00199 exit(1);
00200 }
00201 finalized_count++;
00202 }
00203
00204 size_t counter = 0;
00205
00206 tn * mktree(n)
00207 int n;
00208 {
00209 tn * result = (tn *)GC_MALLOC(sizeof(tn));
00210
00211 if (n == 0) return(0);
00212 if (result == 0) {
00213 (void)printf("Out of memory\n");
00214 exit(1);
00215 }
00216 result -> level = n;
00217 result -> lchild = mktree(n-1);
00218 result -> rchild = mktree(n-1);
00219 if (counter++ % 119 == 0) {
00220 GC_REGISTER_FINALIZER((void_star)result, finalizer, (void_star)n,
00221 (GC_finalization_proc *)0, (void_star *)0);
00222 # ifdef PCR
00223 PCR_ThCrSec_EnterSys();
00224
00225 # endif
00226 finalizable_count++;
00227 # ifdef PCR
00228 PCR_ThCrSec_ExitSys();
00229 # endif
00230 }
00231 return(result);
00232 }
00233
00234 void chktree(t,n)
00235 tn *t;
00236 int n;
00237 {
00238 if (n == 0 && t != 0) {
00239 (void)printf("Clobbered a leaf - collector is broken\n");
00240 exit(1);
00241 }
00242 if (n == 0) return;
00243 if (t -> level != n) {
00244 (void)printf("Lost a node at level %d - collector is broken\n", n);
00245 exit(1);
00246 }
00247 if (counter++ % 373 == 0) (void) GC_MALLOC(counter%5001);
00248 chktree(t -> lchild, n-1);
00249 if (counter++ % 73 == 0) (void) GC_MALLOC(counter%373);
00250 chktree(t -> rchild, n-1);
00251 }
00252
00253 void alloc_small(n)
00254 int n;
00255 {
00256 register int i;
00257
00258 for (i = 0; i < n; i += 8) {
00259 if (GC_MALLOC_ATOMIC(8) == 0) {
00260 (void)printf("Out of memory\n");
00261 exit(1);
00262 }
00263 }
00264 }
00265
00266 tree_test()
00267 {
00268 tn * root = mktree(16);
00269 register int i;
00270
00271 alloc_small(5000000);
00272 chktree(root, 16);
00273 if (finalized_count && ! dropped_something) {
00274 (void)printf("Premature finalization - collector is broken\n");
00275 exit(1);
00276 }
00277 dropped_something = 1;
00278 root = mktree(16);
00279 chktree(root, 16);
00280 for (i = 16; i >= 0; i--) {
00281 root = mktree(i);
00282 chktree(root, i);
00283 }
00284 alloc_small(5000000);
00285 }
00286
00287 # include "gc_private.h"
00288
00289 int n_tests = 0;
00290
00291 void run_one_test()
00292 {
00293 DCL_LOCK_STATE;
00294
00295 reverse_test();
00296 tree_test();
00297 LOCK();
00298 n_tests++;
00299 UNLOCK();
00300
00301 }
00302
00303 void check_heap_stats()
00304 {
00305 (void)printf("Completed %d tests\n", n_tests);
00306 (void)printf("Finalized %d/%d objects - ",
00307 finalized_count, finalizable_count);
00308 if (finalized_count > finalizable_count
00309 || finalized_count < finalizable_count/2) {
00310 (void)printf ("finalization is probably broken\n");
00311 exit(1);
00312 } else {
00313 (void)printf ("finalization is probably ok\n");
00314 }
00315 (void)printf("Total number of bytes allocated is %d\n",
00316 WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc));
00317 (void)printf("Final heap size is %d bytes\n", GC_heapsize);
00318 if (WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc)
00319 < 33500000*n_tests) {
00320 (void)printf("Incorrect execution - missed some allocations\n");
00321 exit(1);
00322 }
00323 if (GC_heapsize > 10000000*n_tests) {
00324 (void)printf("Unexpected heap growth - collector may be broken\n");
00325 exit(1);
00326 }
00327 (void)printf("Collector appears to work\n");
00328 }
00329
00330 #ifndef PCR
00331 main()
00332 {
00333 n_tests = 0;
00334 run_one_test();
00335 check_heap_stats();
00336 (void)fflush(stdout);
00337 return(0);
00338 }
00339 # else
00340 test()
00341 {
00342 PCR_Th_T * th1;
00343 PCR_Th_T * th2;
00344 int code;
00345
00346 n_tests = 0;
00347 th1 = PCR_Th_Fork(run_one_test, 0);
00348 th2 = PCR_Th_Fork(run_one_test, 0);
00349 run_one_test();
00350 if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
00351 != PCR_ERes_okay || code != 0) {
00352 (void)printf("Thread 1 failed\n");
00353 }
00354 if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
00355 != PCR_ERes_okay || code != 0) {
00356 (void)printf("Thread 2 failed\n");
00357 }
00358 check_heap_stats();
00359 (void)fflush(stdout);
00360 return(0);
00361 }
00362 #endif
00363