Fix the handling of inline, unresolved type references.
[official-gcc.git] / boehm-gc / test.c
blob2fc51e12ed77842e708cc71a3df2f72d559825bf
1 /*
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9 * Permission is hereby granted to use or copy this program
10 * for any purpose, provided the above notices are retained on all copies.
11 * Permission to modify the code and to distribute modified code is granted,
12 * provided the above notices are retained, and a notice that the code was
13 * modified is included with the above copyright notice.
15 /* An incomplete test for the garbage collector. */
16 /* Some more obscure entry points are not tested at all. */
18 # if defined(mips) && defined(SYSTYPE_BSD43)
19 /* MIPS RISCOS 4 */
20 # else
21 # include <stdlib.h>
22 # endif
23 # include <stdio.h>
24 # include <assert.h> /* Not normally used, but handy for debugging. */
25 # include "gc.h"
26 # include "gc_typed.h"
27 # include "gc_priv.h" /* For output, locking, and some statistics */
28 # include "config.h"
30 # ifdef MSWIN32
31 # include <windows.h>
32 # endif
34 # ifdef PCR
35 # include "th/PCR_ThCrSec.h"
36 # include "th/PCR_Th.h"
37 # undef GC_printf0
38 # define GC_printf0 printf
39 # undef GC_printf1
40 # define GC_printf1 printf
41 # endif
43 # ifdef SOLARIS_THREADS
44 # include <thread.h>
45 # include <synch.h>
46 # endif
48 # if defined(IRIX_THREADS) || defined(LINUX_THREADS)
49 # include <pthread.h>
50 # endif
52 # ifdef WIN32_THREADS
53 # include <process.h>
54 static CRITICAL_SECTION incr_cs;
55 # endif
56 # if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS)
57 # define THREADS
58 # endif
60 # ifdef AMIGA
61 long __stack = 200000;
62 # endif
64 # define FAIL (void)abort()
66 /* AT_END may be defined to excercise the interior pointer test */
67 /* if the collector is configured with ALL_INTERIOR_POINTERS. */
68 /* As it stands, this test should succeed with either */
69 /* configuration. In the FIND_LEAK configuration, it should */
70 /* find lots of leaks, since we free almost nothing. */
72 struct SEXPR {
73 struct SEXPR * sexpr_car;
74 struct SEXPR * sexpr_cdr;
78 typedef struct SEXPR * sexpr;
80 # define INT_TO_SEXPR(x) ((sexpr)(unsigned long)(x))
82 # undef nil
83 # define nil (INT_TO_SEXPR(0))
84 # define car(x) ((x) -> sexpr_car)
85 # define cdr(x) ((x) -> sexpr_cdr)
86 # define is_nil(x) ((x) == nil)
89 int extra_count = 0; /* Amount of space wasted in cons node */
91 /* Silly implementation of Lisp cons. Intentionally wastes lots of space */
92 /* to test collector. */
93 sexpr cons (x, y)
94 sexpr x;
95 sexpr y;
97 register sexpr r;
98 register int *p;
99 register int my_extra = extra_count;
101 r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra);
102 if (r == 0) {
103 (void)GC_printf0("Out of memory\n");
104 exit(1);
106 for (p = (int *)r;
107 ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
108 if (*p) {
109 (void)GC_printf1("Found nonzero at 0x%lx - allocator is broken\n",
110 (unsigned long)p);
111 FAIL;
113 *p = 13;
115 # ifdef AT_END
116 r = (sexpr)((char *)r + (my_extra & ~7));
117 # endif
118 r -> sexpr_car = x;
119 r -> sexpr_cdr = y;
120 my_extra++;
121 if ( my_extra >= 5000 ) {
122 extra_count = 0;
123 } else {
124 extra_count = my_extra;
126 GC_END_STUBBORN_CHANGE((char *)r);
127 return(r);
130 sexpr small_cons (x, y)
131 sexpr x;
132 sexpr y;
134 register sexpr r;
136 r = (sexpr) GC_MALLOC(sizeof(struct SEXPR));
137 if (r == 0) {
138 (void)GC_printf0("Out of memory\n");
139 exit(1);
141 r -> sexpr_car = x;
142 r -> sexpr_cdr = y;
143 return(r);
146 sexpr small_cons_uncollectable (x, y)
147 sexpr x;
148 sexpr y;
150 register sexpr r;
152 r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR));
153 assert(GC_is_marked(r));
154 if (r == 0) {
155 (void)GC_printf0("Out of memory\n");
156 exit(1);
158 r -> sexpr_car = x;
159 r -> sexpr_cdr = (sexpr)(~(unsigned long)y);
160 return(r);
163 /* Return reverse(x) concatenated with y */
164 sexpr reverse1(x, y)
165 sexpr x, y;
167 if (is_nil(x)) {
168 return(y);
169 } else {
170 return( reverse1(cdr(x), cons(car(x), y)) );
174 sexpr reverse(x)
175 sexpr x;
177 return( reverse1(x, nil) );
180 sexpr ints(low, up)
181 int low, up;
183 if (low > up) {
184 return(nil);
185 } else {
186 return(small_cons(small_cons(INT_TO_SEXPR(low), nil), ints(low+1, up)));
190 /* To check uncollectable allocation we build lists with disguised cdr */
191 /* pointers, and make sure they don't go away. */
192 sexpr uncollectable_ints(low, up)
193 int low, up;
195 if (low > up) {
196 return(nil);
197 } else {
198 return(small_cons_uncollectable(small_cons(INT_TO_SEXPR(low), nil),
199 uncollectable_ints(low+1, up)));
203 void check_ints(list, low, up)
204 sexpr list;
205 int low, up;
207 if ((int)(GC_word)(car(car(list))) != low) {
208 (void)GC_printf0(
209 "List reversal produced incorrect list - collector is broken\n");
210 FAIL;
212 if (low == up) {
213 if (cdr(list) != nil) {
214 (void)GC_printf0("List too long - collector is broken\n");
215 FAIL;
217 } else {
218 check_ints(cdr(list), low+1, up);
222 # define UNCOLLECTABLE_CDR(x) (sexpr)(~(unsigned long)(cdr(x)))
224 void check_uncollectable_ints(list, low, up)
225 sexpr list;
226 int low, up;
228 assert(GC_is_marked(list));
229 if ((int)(GC_word)(car(car(list))) != low) {
230 (void)GC_printf0(
231 "Uncollectable list corrupted - collector is broken\n");
232 FAIL;
234 if (low == up) {
235 if (UNCOLLECTABLE_CDR(list) != nil) {
236 (void)GC_printf0("Uncollectable list too long - collector is broken\n");
237 FAIL;
239 } else {
240 check_uncollectable_ints(UNCOLLECTABLE_CDR(list), low+1, up);
244 /* Not used, but useful for debugging: */
245 void print_int_list(x)
246 sexpr x;
248 if (is_nil(x)) {
249 (void)GC_printf0("NIL\n");
250 } else {
251 (void)GC_printf1("(%ld)", (long)(car(car(x))));
252 if (!is_nil(cdr(x))) {
253 (void)GC_printf0(", ");
254 (void)print_int_list(cdr(x));
255 } else {
256 (void)GC_printf0("\n");
261 /* Try to force a to be strangely aligned */
262 struct {
263 char dummy;
264 sexpr aa;
265 } A;
266 #define a A.aa
269 * Repeatedly reverse lists built out of very different sized cons cells.
270 * Check that we didn't lose anything.
272 void reverse_test()
274 int i;
275 sexpr b;
276 sexpr c;
277 sexpr d;
278 sexpr e;
279 sexpr *f, *g, *h;
280 # if defined(MSWIN32) || defined(MACOS)
281 /* Win32S only allows 128K stacks */
282 # define BIG 1000
283 # else
284 # if defined PCR
285 /* PCR default stack is 100K. Stack frames are up to 120 bytes. */
286 # define BIG 700
287 # else
288 # define BIG 4500
289 # endif
290 # endif
292 A.dummy = 17;
293 a = ints(1, 49);
294 b = ints(1, 50);
295 c = ints(1, BIG);
296 d = uncollectable_ints(1, 100);
297 e = uncollectable_ints(1, 1);
298 /* Check that realloc updates object descriptors correctly */
299 f = (sexpr *)GC_malloc(4 * sizeof(sexpr));
300 f = (sexpr *)GC_realloc((GC_PTR)f, 6 * sizeof(sexpr));
301 f[5] = ints(1,17);
302 g = (sexpr *)GC_malloc(513 * sizeof(sexpr));
303 g = (sexpr *)GC_realloc((GC_PTR)g, 800 * sizeof(sexpr));
304 g[799] = ints(1,18);
305 h = (sexpr *)GC_malloc(1025 * sizeof(sexpr));
306 h = (sexpr *)GC_realloc((GC_PTR)h, 2000 * sizeof(sexpr));
307 h[1999] = ints(1,19);
308 /* Try to force some collections and reuse of small list elements */
309 for (i = 0; i < 10; i++) {
310 (void)ints(1, BIG);
312 /* Superficially test interior pointer recognition on stack */
313 c = (sexpr)((char *)c + sizeof(char *));
314 d = (sexpr)((char *)d + sizeof(char *));
316 # ifdef __STDC__
317 GC_FREE((void *)e);
318 # else
319 GC_FREE((char *)e);
320 # endif
321 check_ints(b,1,50);
322 check_ints(a,1,49);
323 for (i = 0; i < 50; i++) {
324 check_ints(b,1,50);
325 b = reverse(reverse(b));
327 check_ints(b,1,50);
328 check_ints(a,1,49);
329 for (i = 0; i < 60; i++) {
330 /* This maintains the invariant that a always points to a list of */
331 /* 49 integers. Thus this is thread safe without locks, */
332 /* assuming atomic pointer assignments. */
333 a = reverse(reverse(a));
334 # if !defined(AT_END) && !defined(THREADS)
335 /* This is not thread safe, since realloc explicitly deallocates */
336 if (i & 1) {
337 a = (sexpr)GC_REALLOC((GC_PTR)a, 500);
338 } else {
339 a = (sexpr)GC_REALLOC((GC_PTR)a, 8200);
341 # endif
343 check_ints(a,1,49);
344 check_ints(b,1,50);
345 c = (sexpr)((char *)c - sizeof(char *));
346 d = (sexpr)((char *)d - sizeof(char *));
347 check_ints(c,1,BIG);
348 check_uncollectable_ints(d, 1, 100);
349 check_ints(f[5], 1,17);
350 check_ints(g[799], 1,18);
351 check_ints(h[1999], 1,19);
352 # ifndef THREADS
353 a = 0;
354 # endif
355 b = c = 0;
359 * The rest of this builds balanced binary trees, checks that they don't
360 * disappear, and tests finalization.
362 typedef struct treenode {
363 int level;
364 struct treenode * lchild;
365 struct treenode * rchild;
366 } tn;
368 int finalizable_count = 0;
369 int finalized_count = 0;
370 VOLATILE int dropped_something = 0;
372 # ifdef __STDC__
373 void finalizer(void * obj, void * client_data)
374 # else
375 void finalizer(obj, client_data)
376 char * obj;
377 char * client_data;
378 # endif
380 tn * t = (tn *)obj;
382 # ifdef PCR
383 PCR_ThCrSec_EnterSys();
384 # endif
385 # ifdef SOLARIS_THREADS
386 static mutex_t incr_lock;
387 mutex_lock(&incr_lock);
388 # endif
389 # if defined(IRIX_THREADS) || defined(LINUX_THREADS)
390 static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
391 pthread_mutex_lock(&incr_lock);
392 # endif
393 # ifdef WIN32_THREADS
394 EnterCriticalSection(&incr_cs);
395 # endif
396 if ((int)(GC_word)client_data != t -> level) {
397 (void)GC_printf0("Wrong finalization data - collector is broken\n");
398 FAIL;
400 finalized_count++;
401 # ifdef PCR
402 PCR_ThCrSec_ExitSys();
403 # endif
404 # ifdef SOLARIS_THREADS
405 mutex_unlock(&incr_lock);
406 # endif
407 # if defined(IRIX_THREADS) || defined(LINUX_THREADS)
408 pthread_mutex_unlock(&incr_lock);
409 # endif
410 # ifdef WIN32_THREADS
411 LeaveCriticalSection(&incr_cs);
412 # endif
415 size_t counter = 0;
417 # define MAX_FINALIZED 8000
419 # if !defined(MACOS)
420 GC_FAR GC_word live_indicators[MAX_FINALIZED] = {0};
421 #else
422 /* Too big for THINK_C. have to allocate it dynamically. */
423 GC_word *live_indicators = 0;
424 #endif
426 int live_indicators_count = 0;
428 tn * mktree(n)
429 int n;
431 tn * result = (tn *)GC_MALLOC(sizeof(tn));
433 #if defined(MACOS)
434 /* get around static data limitations. */
435 if (!live_indicators)
436 live_indicators =
437 (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word));
438 if (!live_indicators) {
439 (void)GC_printf0("Out of memory\n");
440 exit(1);
442 #endif
443 if (n == 0) return(0);
444 if (result == 0) {
445 (void)GC_printf0("Out of memory\n");
446 exit(1);
448 result -> level = n;
449 result -> lchild = mktree(n-1);
450 result -> rchild = mktree(n-1);
451 if (counter++ % 17 == 0 && n >= 2) {
452 tn * tmp = result -> lchild -> rchild;
454 result -> lchild -> rchild = result -> rchild -> lchild;
455 result -> rchild -> lchild = tmp;
457 if (counter++ % 119 == 0) {
458 int my_index;
461 # ifdef PCR
462 PCR_ThCrSec_EnterSys();
463 # endif
464 # ifdef SOLARIS_THREADS
465 static mutex_t incr_lock;
466 mutex_lock(&incr_lock);
467 # endif
468 # if defined(IRIX_THREADS) || defined(LINUX_THREADS)
469 static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
470 pthread_mutex_lock(&incr_lock);
471 # endif
472 # ifdef WIN32_THREADS
473 EnterCriticalSection(&incr_cs);
474 # endif
475 /* Losing a count here causes erroneous report of failure. */
476 finalizable_count++;
477 my_index = live_indicators_count++;
478 # ifdef PCR
479 PCR_ThCrSec_ExitSys();
480 # endif
481 # ifdef SOLARIS_THREADS
482 mutex_unlock(&incr_lock);
483 # endif
484 # if defined(IRIX_THREADS) || defined(LINUX_THREADS)
485 pthread_mutex_unlock(&incr_lock);
486 # endif
487 # ifdef WIN32_THREADS
488 LeaveCriticalSection(&incr_cs);
489 # endif
492 GC_REGISTER_FINALIZER((GC_PTR)result, finalizer, (GC_PTR)(GC_word)n,
493 (GC_finalization_proc *)0, (GC_PTR *)0);
494 if (my_index >= MAX_FINALIZED) {
495 GC_printf0("live_indicators overflowed\n");
496 FAIL;
498 live_indicators[my_index] = 13;
499 if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
500 (GC_PTR *)(&(live_indicators[my_index])),
501 (GC_PTR)result) != 0) {
502 GC_printf0("GC_general_register_disappearing_link failed\n");
503 FAIL;
505 if (GC_unregister_disappearing_link(
506 (GC_PTR *)
507 (&(live_indicators[my_index]))) == 0) {
508 GC_printf0("GC_unregister_disappearing_link failed\n");
509 FAIL;
511 if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
512 (GC_PTR *)(&(live_indicators[my_index])),
513 (GC_PTR)result) != 0) {
514 GC_printf0("GC_general_register_disappearing_link failed 2\n");
515 FAIL;
518 return(result);
521 void chktree(t,n)
522 tn *t;
523 int n;
525 if (n == 0 && t != 0) {
526 (void)GC_printf0("Clobbered a leaf - collector is broken\n");
527 FAIL;
529 if (n == 0) return;
530 if (t -> level != n) {
531 (void)GC_printf1("Lost a node at level %lu - collector is broken\n",
532 (unsigned long)n);
533 FAIL;
535 if (counter++ % 373 == 0) (void) GC_MALLOC(counter%5001);
536 chktree(t -> lchild, n-1);
537 if (counter++ % 73 == 0) (void) GC_MALLOC(counter%373);
538 chktree(t -> rchild, n-1);
541 # ifdef SOLARIS_THREADS
542 thread_key_t fl_key;
544 void * alloc8bytes()
546 # ifdef SMALL_CONFIG
547 return(GC_malloc(8));
548 # else
549 void ** my_free_list_ptr;
550 void * my_free_list;
552 if (thr_getspecific(fl_key, (void **)(&my_free_list_ptr)) != 0) {
553 (void)GC_printf0("thr_getspecific failed\n");
554 FAIL;
556 if (my_free_list_ptr == 0) {
557 my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *);
558 if (thr_setspecific(fl_key, my_free_list_ptr) != 0) {
559 (void)GC_printf0("thr_setspecific failed\n");
560 FAIL;
563 my_free_list = *my_free_list_ptr;
564 if (my_free_list == 0) {
565 my_free_list = GC_malloc_many(8);
566 if (my_free_list == 0) {
567 (void)GC_printf0("alloc8bytes out of memory\n");
568 FAIL;
571 *my_free_list_ptr = GC_NEXT(my_free_list);
572 GC_NEXT(my_free_list) = 0;
573 return(my_free_list);
574 # endif
577 #else
578 # define alloc8bytes() GC_MALLOC_ATOMIC(8)
579 #endif
581 void alloc_small(n)
582 int n;
584 register int i;
586 for (i = 0; i < n; i += 8) {
587 if (alloc8bytes() == 0) {
588 (void)GC_printf0("Out of memory\n");
589 FAIL;
594 # if defined(THREADS) && defined(GC_DEBUG)
595 # define TREE_HEIGHT 15
596 # else
597 # define TREE_HEIGHT 16
598 # endif
599 void tree_test()
601 tn * root;
602 register int i;
604 root = mktree(TREE_HEIGHT);
605 alloc_small(5000000);
606 chktree(root, TREE_HEIGHT);
607 if (finalized_count && ! dropped_something) {
608 (void)GC_printf0("Premature finalization - collector is broken\n");
609 FAIL;
611 dropped_something = 1;
612 GC_noop(root); /* Root needs to remain live until */
613 /* dropped_something is set. */
614 root = mktree(TREE_HEIGHT);
615 chktree(root, TREE_HEIGHT);
616 for (i = TREE_HEIGHT; i >= 0; i--) {
617 root = mktree(i);
618 chktree(root, i);
620 alloc_small(5000000);
623 unsigned n_tests = 0;
625 GC_word bm_huge[10] = {
626 0xffffffff,
627 0xffffffff,
628 0xffffffff,
629 0xffffffff,
630 0xffffffff,
631 0xffffffff,
632 0xffffffff,
633 0xffffffff,
634 0xffffffff,
635 0x00ffffff,
639 /* A very simple test of explicitly typed allocation */
640 void typed_test()
642 GC_word * old, * new;
643 GC_word bm3 = 0x3;
644 GC_word bm2 = 0x2;
645 GC_word bm_large = 0xf7ff7fff;
646 GC_descr d1 = GC_make_descriptor(&bm3, 2);
647 GC_descr d2 = GC_make_descriptor(&bm2, 2);
648 # ifndef LINT
649 GC_descr dummy = GC_make_descriptor(&bm_large, 32);
650 # endif
651 GC_descr d3 = GC_make_descriptor(&bm_large, 32);
652 GC_descr d4 = GC_make_descriptor(bm_huge, 320);
653 GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4);
654 register int i;
656 old = 0;
657 for (i = 0; i < 4000; i++) {
658 new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1);
659 new[0] = 17;
660 new[1] = (GC_word)old;
661 old = new;
662 new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2);
663 new[0] = 17;
664 new[1] = (GC_word)old;
665 old = new;
666 new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3);
667 new[0] = 17;
668 new[1] = (GC_word)old;
669 old = new;
670 new = (GC_word *) GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word),
671 d1);
672 new[0] = 17;
673 new[1] = (GC_word)old;
674 old = new;
675 if (i & 0xff) {
676 new = (GC_word *) GC_calloc_explicitly_typed(7, 3 * sizeof(GC_word),
677 d2);
678 } else {
679 new = (GC_word *) GC_calloc_explicitly_typed(1001,
680 3 * sizeof(GC_word),
681 d2);
683 new[0] = 17;
684 new[1] = (GC_word)old;
685 old = new;
687 for (i = 0; i < 20000; i++) {
688 if (new[0] != 17) {
689 (void)GC_printf1("typed alloc failed at %lu\n",
690 (unsigned long)i);
691 FAIL;
693 new[0] = 0;
694 old = new;
695 new = (GC_word *)(old[1]);
697 GC_gcollect();
698 GC_noop(x);
701 int fail_count = 0;
703 #ifndef __STDC__
704 /*ARGSUSED*/
705 void fail_proc1(x)
706 GC_PTR x;
708 fail_count++;
711 #else
713 /*ARGSUSED*/
714 void fail_proc1(GC_PTR x)
716 fail_count++;
719 #endif /* __STDC__ */
721 #ifdef THREADS
722 # define TEST_FAIL_COUNT(n) 1
723 #else
724 # define TEST_FAIL_COUNT(n) (fail_count >= (n))
725 #endif
727 void run_one_test()
729 char *x;
730 # ifdef LINT
731 char *y = 0;
732 # else
733 char *y = (char *)(size_t)fail_proc1;
734 # endif
735 DCL_LOCK_STATE;
737 # ifdef FIND_LEAK
738 (void)GC_printf0(
739 "This test program is not designed for leak detection mode\n");
740 (void)GC_printf0("Expect lots of problems.\n");
741 # endif
742 if (GC_size(GC_malloc(7)) != 8
743 || GC_size(GC_malloc(15)) != 16) {
744 (void)GC_printf0("GC_size produced unexpected results\n");
745 FAIL;
747 if (GC_size(GC_malloc(0)) != 4 && GC_size(GC_malloc(0)) != 8) {
748 (void)GC_printf0("GC_malloc(0) failed\n");
749 FAIL;
751 if (GC_size(GC_malloc_uncollectable(0)) != 4
752 && GC_size(GC_malloc_uncollectable(0)) != 8) {
753 (void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
754 FAIL;
756 GC_is_valid_displacement_print_proc = fail_proc1;
757 GC_is_visible_print_proc = fail_proc1;
758 x = GC_malloc(16);
759 if (GC_base(x + 13) != x) {
760 (void)GC_printf0("GC_base(heap ptr) produced incorrect result\n");
761 FAIL;
763 # ifndef PCR
764 if (GC_base(y) != 0) {
765 (void)GC_printf0("GC_base(fn_ptr) produced incorrect result\n");
766 FAIL;
768 # endif
769 if (GC_same_obj(x+5, x) != x + 5) {
770 (void)GC_printf0("GC_same_obj produced incorrect result\n");
771 FAIL;
773 if (GC_is_visible(y) != y || GC_is_visible(x) != x) {
774 (void)GC_printf0("GC_is_visible produced incorrect result\n");
775 FAIL;
777 if (!TEST_FAIL_COUNT(1)) {
778 # if!(defined(RS6000) || defined(POWERPC))
779 /* ON RS6000s function pointers point to a descriptor in the */
780 /* data segment, so there should have been no failures. */
781 (void)GC_printf0("GC_is_visible produced wrong failure indication\n");
782 FAIL;
783 # endif
785 if (GC_is_valid_displacement(y) != y
786 || GC_is_valid_displacement(x) != x
787 || GC_is_valid_displacement(x + 3) != x + 3) {
788 (void)GC_printf0(
789 "GC_is_valid_displacement produced incorrect result\n");
790 FAIL;
792 # ifndef ALL_INTERIOR_POINTERS
793 # if defined(RS6000) || defined(POWERPC)
794 if (!TEST_FAIL_COUNT(1)) {
795 # else
796 if (!TEST_FAIL_COUNT(2)) {
797 # endif
798 (void)GC_printf0("GC_is_valid_displacement produced wrong failure indication\n");
799 FAIL;
801 # endif
802 /* Test floating point alignment */
803 *(double *)GC_MALLOC(sizeof(double)) = 1.0;
804 *(double *)GC_MALLOC(sizeof(double)) = 1.0;
805 /* Repeated list reversal test. */
806 reverse_test();
807 # ifdef PRINTSTATS
808 GC_printf0("-------------Finished reverse_test\n");
809 # endif
810 typed_test();
811 # ifdef PRINTSTATS
812 GC_printf0("-------------Finished typed_test\n");
813 # endif
814 tree_test();
815 LOCK();
816 n_tests++;
817 UNLOCK();
818 /* GC_printf1("Finished %x\n", pthread_self()); */
821 void check_heap_stats()
823 unsigned long max_heap_sz;
824 register int i;
825 int still_live;
826 int late_finalize_count = 0;
828 if (sizeof(char *) > 4) {
829 max_heap_sz = 13000000;
830 } else {
831 max_heap_sz = 11000000;
833 # ifdef GC_DEBUG
834 max_heap_sz *= 2;
835 # ifdef SPARC
836 max_heap_sz *= 2;
837 # endif
838 # endif
839 /* Garbage collect repeatedly so that all inaccessible objects */
840 /* can be finalized. */
841 while (GC_collect_a_little()) { }
842 for (i = 0; i < 16; i++) {
843 GC_gcollect();
844 late_finalize_count += GC_invoke_finalizers();
846 (void)GC_printf1("Completed %lu tests\n", (unsigned long)n_tests);
847 (void)GC_printf2("Finalized %lu/%lu objects - ",
848 (unsigned long)finalized_count,
849 (unsigned long)finalizable_count);
850 # ifdef FINALIZE_ON_DEMAND
851 if (finalized_count != late_finalize_count) {
852 (void)GC_printf0("Demand finalization error\n");
853 FAIL;
855 # endif
856 if (finalized_count > finalizable_count
857 || finalized_count < finalizable_count/2) {
858 (void)GC_printf0("finalization is probably broken\n");
859 FAIL;
860 } else {
861 (void)GC_printf0("finalization is probably ok\n");
863 still_live = 0;
864 for (i = 0; i < MAX_FINALIZED; i++) {
865 if (live_indicators[i] != 0) {
866 still_live++;
869 i = finalizable_count - finalized_count - still_live;
870 if (0 != i) {
871 (void)GC_printf2
872 ("%lu disappearing links remain and %lu more objects were not finalized\n",
873 (unsigned long) still_live, (unsigned long)i);
874 if (i > 10) {
875 GC_printf0("\tVery suspicious!\n");
876 } else {
877 GC_printf0("\tSlightly suspicious, but probably OK.\n");
880 (void)GC_printf1("Total number of bytes allocated is %lu\n",
881 (unsigned long)
882 WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc));
883 (void)GC_printf1("Final heap size is %lu bytes\n",
884 (unsigned long)GC_get_heap_size());
885 if (WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc)
886 < 33500000*n_tests) {
887 (void)GC_printf0("Incorrect execution - missed some allocations\n");
888 FAIL;
890 if (GC_get_heap_size() > max_heap_sz*n_tests) {
891 (void)GC_printf0("Unexpected heap growth - collector may be broken\n");
892 FAIL;
894 (void)GC_printf0("Collector appears to work\n");
897 #if defined(MACOS)
898 void SetMinimumStack(long minSize)
900 long newApplLimit;
902 if (minSize > LMGetDefltStack())
904 newApplLimit = (long) GetApplLimit()
905 - (minSize - LMGetDefltStack());
906 SetApplLimit((Ptr) newApplLimit);
907 MaxApplZone();
911 #define cMinStackSpace (512L * 1024L)
913 #endif
915 #ifdef __STDC__
916 void warn_proc(char *msg, GC_word p)
917 #else
918 void warn_proc(msg, p)
919 char *msg;
920 GC_word p;
921 #endif
923 GC_printf1(msg, (unsigned long)p);
924 FAIL;
928 #if !defined(PCR) && !defined(SOLARIS_THREADS) && !defined(WIN32_THREADS) \
929 && !defined(IRIX_THREADS) && !defined(LINUX_THREADS) || defined(LINT)
930 #ifdef MSWIN32
931 int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
932 #else
933 int main()
934 #endif
936 # if defined(DJGPP)
937 int dummy;
938 # endif
939 n_tests = 0;
941 # if defined(DJGPP)
942 /* No good way to determine stack base from library; do it */
943 /* manually on this platform. */
944 GC_stackbottom = (GC_PTR)(&dummy);
945 # endif
946 # if defined(MACOS)
947 /* Make sure we have lots and lots of stack space. */
948 SetMinimumStack(cMinStackSpace);
949 /* Cheat and let stdio initialize toolbox for us. */
950 printf("Testing GC Macintosh port.\n");
951 # endif
952 GC_INIT(); /* Only needed if gc is dynamic library. */
953 (void) GC_set_warn_proc(warn_proc);
954 # if defined(MPROTECT_VDB) || defined(PROC_VDB)
955 GC_enable_incremental();
956 (void) GC_printf0("Switched to incremental mode\n");
957 # if defined(MPROTECT_VDB)
958 (void)GC_printf0("Emulating dirty bits with mprotect/signals\n");
959 # else
960 (void)GC_printf0("Reading dirty bits from /proc\n");
961 # endif
962 # endif
963 run_one_test();
964 check_heap_stats();
965 (void)fflush(stdout);
966 # ifdef LINT
967 /* Entry points we should be testing, but aren't. */
968 /* Some can be tested by defining GC_DEBUG at the top of this file */
969 /* This is a bit SunOS4 specific. */
970 GC_noop(GC_expand_hp, GC_add_roots, GC_clear_roots,
971 GC_register_disappearing_link,
972 GC_register_finalizer_ignore_self,
973 GC_debug_register_displacement,
974 GC_print_obj, GC_debug_change_stubborn,
975 GC_debug_end_stubborn_change, GC_debug_malloc_uncollectable,
976 GC_debug_free, GC_debug_realloc, GC_generic_malloc_words_small,
977 GC_init, GC_make_closure, GC_debug_invoke_finalizer,
978 GC_page_was_ever_dirty, GC_is_fresh,
979 GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page,
980 GC_set_max_heap_size, GC_get_bytes_since_gc,
981 GC_pre_incr, GC_post_incr);
982 # endif
983 return(0);
985 # endif
987 #ifdef WIN32_THREADS
989 unsigned __stdcall thr_run_one_test(void *arg)
991 run_one_test();
992 return 0;
995 #define NTEST 2
997 int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
999 # if NTEST > 0
1000 HANDLE h[NTEST];
1001 # endif
1002 int i;
1003 unsigned thread_id;
1004 # if 0
1005 GC_enable_incremental();
1006 # endif
1007 InitializeCriticalSection(&incr_cs);
1008 (void) GC_set_warn_proc(warn_proc);
1009 for (i = 0; i < NTEST; i++) {
1010 h[i] = (HANDLE)_beginthreadex(NULL, 0, thr_run_one_test, 0, 0, &thread_id);
1011 if (h[i] == (HANDLE)-1) {
1012 (void)GC_printf1("Thread creation failed %lu\n", (unsigned long)GetLastError());
1013 FAIL;
1016 run_one_test();
1017 for (i = 0; i < NTEST; i++)
1018 if (WaitForSingleObject(h[i], INFINITE) != WAIT_OBJECT_0) {
1019 (void)GC_printf1("Thread wait failed %lu\n", (unsigned long)GetLastError());
1020 FAIL;
1022 check_heap_stats();
1023 (void)fflush(stdout);
1024 return(0);
1027 #endif /* WIN32_THREADS */
1030 #ifdef PCR
1031 test()
1033 PCR_Th_T * th1;
1034 PCR_Th_T * th2;
1035 int code;
1037 n_tests = 0;
1038 /* GC_enable_incremental(); */
1039 (void) GC_set_warn_proc(warn_proc);
1040 th1 = PCR_Th_Fork(run_one_test, 0);
1041 th2 = PCR_Th_Fork(run_one_test, 0);
1042 run_one_test();
1043 if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1044 != PCR_ERes_okay || code != 0) {
1045 (void)GC_printf0("Thread 1 failed\n");
1047 if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1048 != PCR_ERes_okay || code != 0) {
1049 (void)GC_printf0("Thread 2 failed\n");
1051 check_heap_stats();
1052 (void)fflush(stdout);
1053 return(0);
1055 #endif
1057 #if defined(SOLARIS_THREADS) || defined(IRIX_THREADS) || defined(LINUX_THREADS)
1058 void * thr_run_one_test(void * arg)
1060 run_one_test();
1061 return(0);
1064 #ifdef GC_DEBUG
1065 # define GC_free GC_debug_free
1066 #endif
1068 #ifdef SOLARIS_THREADS
1069 main()
1071 thread_t th1;
1072 thread_t th2;
1073 int code;
1075 n_tests = 0;
1076 GC_INIT(); /* Only needed if gc is dynamic library. */
1077 GC_enable_incremental();
1078 (void) GC_set_warn_proc(warn_proc);
1079 if (thr_keycreate(&fl_key, GC_free) != 0) {
1080 (void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
1081 FAIL;
1083 if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, 0, &th1)) != 0) {
1084 (void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1085 FAIL;
1087 if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, THR_NEW_LWP, &th2)) != 0) {
1088 (void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1089 FAIL;
1091 run_one_test();
1092 if ((code = thr_join(th1, 0, 0)) != 0) {
1093 (void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1094 FAIL;
1096 if (thr_join(th2, 0, 0) != 0) {
1097 (void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1098 FAIL;
1100 check_heap_stats();
1101 (void)fflush(stdout);
1102 return(0);
1104 #else /* pthreads */
1105 main()
1107 pthread_t th1;
1108 pthread_t th2;
1109 pthread_attr_t attr;
1110 int code;
1112 # ifdef IRIX_THREADS
1113 /* Force a larger stack to be preallocated */
1114 /* Since the initial cant always grow later. */
1115 *((volatile char *)&code - 1024*1024) = 0; /* Require 1 Mb */
1116 # endif /* IRIX_THREADS */
1117 pthread_attr_init(&attr);
1118 # ifdef IRIX_THREADS
1119 pthread_attr_setstacksize(&attr, 1000000);
1120 # endif
1121 n_tests = 0;
1122 # ifdef MPROTECT_VDB
1123 GC_enable_incremental();
1124 (void) GC_printf0("Switched to incremental mode\n");
1125 (void) GC_printf0("Emulating dirty bits with mprotect/signals\n");
1126 # endif
1127 (void) GC_set_warn_proc(warn_proc);
1128 if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) {
1129 (void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1130 FAIL;
1132 if ((code = pthread_create(&th2, &attr, thr_run_one_test, 0)) != 0) {
1133 (void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1134 FAIL;
1136 run_one_test();
1137 if ((code = pthread_join(th1, 0)) != 0) {
1138 (void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1139 FAIL;
1141 if (pthread_join(th2, 0) != 0) {
1142 (void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1143 FAIL;
1145 check_heap_stats();
1146 (void)fflush(stdout);
1147 pthread_attr_destroy(&attr);
1148 GC_printf1("Completed %d collections\n", GC_gc_no);
1149 return(0);
1151 #endif /* pthreads */
1152 #endif /* SOLARIS_THREADS || IRIX_THREADS || LINUX_THREADS */