OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [boehm-gc/] [tests/] [test.c] - Blame information for rev 13

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/*
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.
5
 *
6
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
8
 *
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.
14
 */
15
/* An incomplete test for the garbage collector.                */
16
/* Some more obscure entry points are not tested at all.        */
17
/* This must be compiled with the same flags used to build the  */
18
/* GC.  It uses GC internals to allow more precise results      */
19
/* checking for some of the tests.                              */
20
 
21
# undef GC_BUILD
22
 
23
#if defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)
24
#  define GC_DEBUG
25
#endif
26
 
27
# if defined(mips) && defined(SYSTYPE_BSD43)
28
    /* MIPS RISCOS 4 */
29
# else
30
#   include <stdlib.h>
31
# endif
32
# include <stdio.h>
33
# ifdef _WIN32_WCE
34
#   include <winbase.h>
35
#   define assert ASSERT
36
# else
37
#   include <assert.h>        /* Not normally used, but handy for debugging. */
38
# endif
39
# include <assert.h>    /* Not normally used, but handy for debugging. */
40
# include "gc.h"
41
# include "gc_typed.h"
42
# ifdef THREAD_LOCAL_ALLOC
43
#   include "gc_local_alloc.h"
44
# endif
45
# include "private/gc_priv.h"   /* For output, locking, MIN_WORDS,      */
46
                                /* and some statistics.                 */
47
# include "private/gcconfig.h"
48
 
49
# if defined(MSWIN32) || defined(MSWINCE)
50
#   include <windows.h>
51
# endif
52
 
53
# ifdef PCR
54
#   include "th/PCR_ThCrSec.h"
55
#   include "th/PCR_Th.h"
56
#   undef GC_printf0
57
#   define GC_printf0 printf
58
#   undef GC_printf1
59
#   define GC_printf1 printf
60
# endif
61
 
62
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
63
#   include <thread.h>
64
#   include <synch.h>
65
# endif
66
 
67
# if defined(GC_PTHREADS)
68
#   include <pthread.h>
69
# endif
70
 
71
# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
72
    static CRITICAL_SECTION incr_cs;
73
# endif
74
 
75
#ifdef __STDC__
76
# include <stdarg.h>
77
#endif
78
 
79
 
80
/* Allocation Statistics */
81
int stubborn_count = 0;
82
int uncollectable_count = 0;
83
int collectable_count = 0;
84
int atomic_count = 0;
85
int realloc_count = 0;
86
 
87
#if defined(GC_AMIGA_FASTALLOC) && defined(AMIGA)
88
 
89
  extern void GC_amiga_free_all_mem(void);
90
  void Amiga_Fail(void){GC_amiga_free_all_mem();abort();}
91
# define FAIL (void)Amiga_Fail()
92
  void *GC_amiga_gctest_malloc_explicitly_typed(size_t lb, GC_descr d){
93
    void *ret=GC_malloc_explicitly_typed(lb,d);
94
    if(ret==NULL){
95
                if(!GC_dont_gc){
96
              GC_gcollect();
97
              ret=GC_malloc_explicitly_typed(lb,d);
98
                }
99
      if(ret==NULL){
100
        GC_printf0("Out of memory, (typed allocations are not directly "
101
                   "supported with the GC_AMIGA_FASTALLOC option.)\n");
102
        FAIL;
103
      }
104
    }
105
    return ret;
106
  }
107
  void *GC_amiga_gctest_calloc_explicitly_typed(size_t a,size_t lb, GC_descr d){
108
    void *ret=GC_calloc_explicitly_typed(a,lb,d);
109
    if(ret==NULL){
110
                if(!GC_dont_gc){
111
              GC_gcollect();
112
              ret=GC_calloc_explicitly_typed(a,lb,d);
113
                }
114
      if(ret==NULL){
115
        GC_printf0("Out of memory, (typed allocations are not directly "
116
                   "supported with the GC_AMIGA_FASTALLOC option.)\n");
117
        FAIL;
118
      }
119
    }
120
    return ret;
121
  }
122
# define GC_malloc_explicitly_typed(a,b) GC_amiga_gctest_malloc_explicitly_typed(a,b) 
123
# define GC_calloc_explicitly_typed(a,b,c) GC_amiga_gctest_calloc_explicitly_typed(a,b,c) 
124
 
125
#else /* !AMIGA_FASTALLOC */
126
 
127
# ifdef PCR
128
#   define FAIL (void)abort()
129
# else
130
#   ifdef MSWINCE
131
#     define FAIL DebugBreak()
132
#   else
133
#     define FAIL GC_abort("Test failed");
134
#   endif
135
# endif
136
 
137
#endif /* !AMIGA_FASTALLOC */
138
 
139
/* AT_END may be defined to exercise the interior pointer test  */
140
/* if the collector is configured with ALL_INTERIOR_POINTERS.   */
141
/* As it stands, this test should succeed with either           */
142
/* configuration.  In the FIND_LEAK configuration, it should    */
143
/* find lots of leaks, since we free almost nothing.            */
144
 
145
struct SEXPR {
146
    struct SEXPR * sexpr_car;
147
    struct SEXPR * sexpr_cdr;
148
};
149
 
150
 
151
typedef struct SEXPR * sexpr;
152
 
153
# define INT_TO_SEXPR(x) ((sexpr)(unsigned long)(x))
154
 
155
# undef nil
156
# define nil (INT_TO_SEXPR(0))
157
# define car(x) ((x) -> sexpr_car)
158
# define cdr(x) ((x) -> sexpr_cdr)
159
# define is_nil(x) ((x) == nil)
160
 
161
 
162
int extra_count = 0;        /* Amount of space wasted in cons node */
163
 
164
/* Silly implementation of Lisp cons. Intentionally wastes lots of space */
165
/* to test collector.                                                    */
166
# ifdef VERY_SMALL_CONFIG
167
#   define cons small_cons
168
# else
169
sexpr cons (x, y)
170
sexpr x;
171
sexpr y;
172
{
173
    register sexpr r;
174
    register int *p;
175
    register int my_extra = extra_count;
176
 
177
    stubborn_count++;
178
    r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra);
179
    if (r == 0) {
180
        (void)GC_printf0("Out of memory\n");
181
        exit(1);
182
    }
183
    for (p = (int *)r;
184
         ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
185
        if (*p) {
186
            (void)GC_printf1("Found nonzero at 0x%lx - allocator is broken\n",
187
                             (unsigned long)p);
188
            FAIL;
189
        }
190
        *p = 13;
191
    }
192
#   ifdef AT_END
193
        r = (sexpr)((char *)r + (my_extra & ~7));
194
#   endif
195
    r -> sexpr_car = x;
196
    r -> sexpr_cdr = y;
197
    my_extra++;
198
    if ( my_extra >= 5000 ) {
199
        extra_count = 0;
200
    } else {
201
        extra_count = my_extra;
202
    }
203
    GC_END_STUBBORN_CHANGE((char *)r);
204
    return(r);
205
}
206
# endif
207
 
208
#ifdef GC_GCJ_SUPPORT
209
 
210
#include "gc_mark.h"
211
#include "gc_gcj.h"
212
 
213
/* The following struct emulates the vtable in gcj.     */
214
/* This assumes the default value of MARK_DESCR_OFFSET. */
215
struct fake_vtable {
216
  void * dummy;         /* class pointer in real gcj.   */
217
  size_t descr;
218
};
219
 
220
struct fake_vtable gcj_class_struct1 = { 0, sizeof(struct SEXPR)
221
                                            + sizeof(struct fake_vtable *) };
222
                        /* length based descriptor.     */
223
struct fake_vtable gcj_class_struct2 =
224
                                { 0, (3l << (CPP_WORDSZ - 3)) | GC_DS_BITMAP};
225
                        /* Bitmap based descriptor.     */
226
 
227
struct GC_ms_entry * fake_gcj_mark_proc(word * addr,
228
                                        struct GC_ms_entry *mark_stack_ptr,
229
                                        struct GC_ms_entry *mark_stack_limit,
230
                                        word env   )
231
{
232
    sexpr x;
233
    if (1 == env) {
234
        /* Object allocated with debug allocator.       */
235
        addr = (word *)GC_USR_PTR_FROM_BASE(addr);
236
    }
237
    x = (sexpr)(addr + 1); /* Skip the vtable pointer. */
238
    mark_stack_ptr = GC_MARK_AND_PUSH(
239
                              (GC_PTR)(x -> sexpr_cdr), mark_stack_ptr,
240
                              mark_stack_limit, (GC_PTR *)&(x -> sexpr_cdr));
241
    mark_stack_ptr = GC_MARK_AND_PUSH(
242
                              (GC_PTR)(x -> sexpr_car), mark_stack_ptr,
243
                              mark_stack_limit, (GC_PTR *)&(x -> sexpr_car));
244
    return(mark_stack_ptr);
245
}
246
 
247
#endif /* GC_GCJ_SUPPORT */
248
 
249
#ifdef THREAD_LOCAL_ALLOC
250
 
251
#undef GC_REDIRECT_TO_LOCAL
252
#include "gc_local_alloc.h"
253
 
254
sexpr local_cons (x, y)
255
sexpr x;
256
sexpr y;
257
{
258
    register sexpr r;
259
    register int *p;
260
    register int my_extra = extra_count;
261
    static int my_random = 0;
262
 
263
    collectable_count++;
264
    r = (sexpr) GC_LOCAL_MALLOC(sizeof(struct SEXPR) + my_extra);
265
#   ifdef GC_GCJ_SUPPORT
266
      if (collectable_count % 2 == 0) {
267
        r = (sexpr) GC_LOCAL_GCJ_MALLOC(sizeof(struct SEXPR) + sizeof(GC_word) + my_extra,
268
                                        &gcj_class_struct1);
269
        r = (sexpr) ((GC_word *)r + 1);
270
      }
271
#   endif
272
    if (r == 0) {
273
        (void)GC_printf0("Out of memory\n");
274
        exit(1);
275
    }
276
    for (p = (int *)r;
277
         ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
278
        if (*p) {
279
            (void)GC_printf1("Found nonzero at 0x%lx (local) - allocator is broken\n",
280
                             (unsigned long)p);
281
            FAIL;
282
        }
283
        *p = 13;
284
    }
285
    r -> sexpr_car = x;
286
    r -> sexpr_cdr = y;
287
    my_extra++;
288
    if ( my_extra >= 5000 || my_extra == 200 && ++my_random % 37 != 0) {
289
        extra_count = 0;
290
    } else {
291
        extra_count = my_extra;
292
    }
293
    return(r);
294
}
295
#endif /* THREAD_LOCAL_ALLOC */
296
 
297
sexpr small_cons (x, y)
298
sexpr x;
299
sexpr y;
300
{
301
    register sexpr r;
302
 
303
    collectable_count++;
304
    r = (sexpr) GC_MALLOC(sizeof(struct SEXPR));
305
    if (r == 0) {
306
        (void)GC_printf0("Out of memory\n");
307
        exit(1);
308
    }
309
    r -> sexpr_car = x;
310
    r -> sexpr_cdr = y;
311
    return(r);
312
}
313
 
314
sexpr small_cons_uncollectable (x, y)
315
sexpr x;
316
sexpr y;
317
{
318
    register sexpr r;
319
 
320
    uncollectable_count++;
321
    r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR));
322
    if (r == 0) {
323
        (void)GC_printf0("Out of memory\n");
324
        exit(1);
325
    }
326
    r -> sexpr_car = x;
327
    r -> sexpr_cdr = (sexpr)(~(unsigned long)y);
328
    return(r);
329
}
330
 
331
#ifdef GC_GCJ_SUPPORT
332
 
333
 
334
sexpr gcj_cons(x, y)
335
sexpr x;
336
sexpr y;
337
{
338
    GC_word * r;
339
    sexpr result;
340
    static int count = 0;
341
 
342
    if (++count & 1) {
343
#     ifdef USE_MARK_BYTES
344
        r = (GC_word *) GC_GCJ_FAST_MALLOC(4, &gcj_class_struct1);
345
#     else
346
        r = (GC_word *) GC_GCJ_FAST_MALLOC(3, &gcj_class_struct1);
347
#     endif
348
    } else {
349
        r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR)
350
                                      + sizeof(struct fake_vtable*),
351
                                      &gcj_class_struct2);
352
    }
353
    if (r == 0) {
354
        (void)GC_printf0("Out of memory\n");
355
        exit(1);
356
    }
357
    result = (sexpr)(r + 1);
358
    result -> sexpr_car = x;
359
    result -> sexpr_cdr = y;
360
    return(result);
361
}
362
#endif
363
 
364
/* Return reverse(x) concatenated with y */
365
sexpr reverse1(x, y)
366
sexpr x, y;
367
{
368
    if (is_nil(x)) {
369
        return(y);
370
    } else {
371
        return( reverse1(cdr(x), cons(car(x), y)) );
372
    }
373
}
374
 
375
sexpr reverse(x)
376
sexpr x;
377
{
378
#   ifdef TEST_WITH_SYSTEM_MALLOC
379
      malloc(100000);
380
#   endif
381
    return( reverse1(x, nil) );
382
}
383
 
384
sexpr ints(low, up)
385
int low, up;
386
{
387
    if (low > up) {
388
        return(nil);
389
    } else {
390
        return(small_cons(small_cons(INT_TO_SEXPR(low), nil), ints(low+1, up)));
391
    }
392
}
393
 
394
#ifdef GC_GCJ_SUPPORT
395
/* Return reverse(x) concatenated with y */
396
sexpr gcj_reverse1(x, y)
397
sexpr x, y;
398
{
399
    if (is_nil(x)) {
400
        return(y);
401
    } else {
402
        return( gcj_reverse1(cdr(x), gcj_cons(car(x), y)) );
403
    }
404
}
405
 
406
sexpr gcj_reverse(x)
407
sexpr x;
408
{
409
    return( gcj_reverse1(x, nil) );
410
}
411
 
412
sexpr gcj_ints(low, up)
413
int low, up;
414
{
415
    if (low > up) {
416
        return(nil);
417
    } else {
418
        return(gcj_cons(gcj_cons(INT_TO_SEXPR(low), nil), gcj_ints(low+1, up)));
419
    }
420
}
421
#endif /* GC_GCJ_SUPPORT */
422
 
423
#ifdef THREAD_LOCAL_ALLOC
424
/* Return reverse(x) concatenated with y */
425
sexpr local_reverse1(x, y)
426
sexpr x, y;
427
{
428
    if (is_nil(x)) {
429
        return(y);
430
    } else {
431
        return( local_reverse1(cdr(x), local_cons(car(x), y)) );
432
    }
433
}
434
 
435
sexpr local_reverse(x)
436
sexpr x;
437
{
438
    return( local_reverse1(x, nil) );
439
}
440
 
441
sexpr local_ints(low, up)
442
int low, up;
443
{
444
    if (low > up) {
445
        return(nil);
446
    } else {
447
        return(local_cons(local_cons(INT_TO_SEXPR(low), nil), local_ints(low+1, up)));
448
    }
449
}
450
#endif /* THREAD_LOCAL_ALLOC */
451
 
452
/* To check uncollectable allocation we build lists with disguised cdr  */
453
/* pointers, and make sure they don't go away.                          */
454
sexpr uncollectable_ints(low, up)
455
int low, up;
456
{
457
    if (low > up) {
458
        return(nil);
459
    } else {
460
        return(small_cons_uncollectable(small_cons(INT_TO_SEXPR(low), nil),
461
               uncollectable_ints(low+1, up)));
462
    }
463
}
464
 
465
void check_ints(list, low, up)
466
sexpr list;
467
int low, up;
468
{
469
    if ((int)(GC_word)(car(car(list))) != low) {
470
        (void)GC_printf0(
471
           "List reversal produced incorrect list - collector is broken\n");
472
        FAIL;
473
    }
474
    if (low == up) {
475
        if (cdr(list) != nil) {
476
           (void)GC_printf0("List too long - collector is broken\n");
477
           FAIL;
478
        }
479
    } else {
480
        check_ints(cdr(list), low+1, up);
481
    }
482
}
483
 
484
# define UNCOLLECTABLE_CDR(x) (sexpr)(~(unsigned long)(cdr(x)))
485
 
486
void check_uncollectable_ints(list, low, up)
487
sexpr list;
488
int low, up;
489
{
490
    if ((int)(GC_word)(car(car(list))) != low) {
491
        (void)GC_printf0(
492
           "Uncollectable list corrupted - collector is broken\n");
493
        FAIL;
494
    }
495
    if (low == up) {
496
        if (UNCOLLECTABLE_CDR(list) != nil) {
497
           (void)GC_printf0("Uncollectable list too long - collector is broken\n");
498
           FAIL;
499
        }
500
    } else {
501
        check_uncollectable_ints(UNCOLLECTABLE_CDR(list), low+1, up);
502
    }
503
}
504
 
505
/* Not used, but useful for debugging: */
506
void print_int_list(x)
507
sexpr x;
508
{
509
    if (is_nil(x)) {
510
        (void)GC_printf0("NIL\n");
511
    } else {
512
        (void)GC_printf1("(%ld)", (long)(car(car(x))));
513
        if (!is_nil(cdr(x))) {
514
            (void)GC_printf0(", ");
515
            (void)print_int_list(cdr(x));
516
        } else {
517
            (void)GC_printf0("\n");
518
        }
519
    }
520
}
521
 
522
/*
523
 * A tiny list reversal test to check thread creation.
524
 */
525
#ifdef THREADS
526
 
527
# if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)
528
    DWORD  __stdcall tiny_reverse_test(void * arg)
529
# else
530
    void * tiny_reverse_test(void * arg)
531
# endif
532
{
533
    int i;
534
    for (i = 0; i < 5; ++i) {
535
      check_ints(reverse(reverse(ints(1,10))), 1, 10);
536
#     ifdef THREAD_LOCAL_ALLOC
537
        check_ints(local_reverse(local_reverse(local_ints(1,10))), 1, 10);
538
#     endif
539
    }
540
    return 0;
541
}
542
 
543
# if defined(GC_PTHREADS)
544
    void fork_a_thread()
545
    {
546
      pthread_t t;
547
      int code;
548
      if ((code = pthread_create(&t, 0, tiny_reverse_test, 0)) != 0) {
549
        (void)GC_printf1("Small thread creation failed %lu\n",
550
                         (unsigned long)code);
551
        FAIL;
552
      }
553
      if ((code = pthread_join(t, 0)) != 0) {
554
        (void)GC_printf1("Small thread join failed %lu\n",
555
        (unsigned long)code);
556
        FAIL;
557
      }
558
    }
559
 
560
# elif defined(GC_WIN32_THREADS)
561
    void fork_a_thread()
562
    {
563
        DWORD thread_id;
564
        HANDLE h;
565
        h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id);
566
        if (h == (HANDLE)NULL) {
567
            (void)GC_printf1("Small thread creation failed %lu\n",
568
                             (unsigned long)GetLastError());
569
            FAIL;
570
        }
571
        if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
572
            (void)GC_printf1("Small thread wait failed %lu\n",
573
                             (unsigned long)GetLastError());
574
            FAIL;
575
        }
576
    }
577
 
578
/* # elif defined(GC_SOLARIS_THREADS) */
579
 
580
# else
581
 
582
#   define fork_a_thread()
583
 
584
# endif
585
 
586
#else
587
 
588
# define fork_a_thread()
589
 
590
#endif 
591
 
592
/* Try to force a to be strangely aligned */
593
struct {
594
  char dummy;
595
  sexpr aa;
596
} A;
597
#define a A.aa
598
 
599
/*
600
 * Repeatedly reverse lists built out of very different sized cons cells.
601
 * Check that we didn't lose anything.
602
 */
603
void reverse_test()
604
{
605
    int i;
606
    sexpr b;
607
    sexpr c;
608
    sexpr d;
609
    sexpr e;
610
    sexpr *f, *g, *h;
611
#   if defined(MSWIN32) || defined(MACOS)
612
      /* Win32S only allows 128K stacks */
613
#     define BIG 1000
614
#   else
615
#     if defined PCR
616
        /* PCR default stack is 100K.  Stack frames are up to 120 bytes. */
617
#       define BIG 700
618
#     else
619
#       if defined MSWINCE
620
          /* WinCE only allows 64K stacks */
621
#         define BIG 500
622
#       else
623
#         if defined(OSF1)
624
            /* OSF has limited stack space by default, and large frames. */
625
#           define BIG 200
626
#         else
627
#           define BIG 4500
628
#         endif
629
#       endif
630
#     endif
631
#   endif
632
 
633
    A.dummy = 17;
634
    a = ints(1, 49);
635
    b = ints(1, 50);
636
    c = ints(1, BIG);
637
    d = uncollectable_ints(1, 100);
638
    e = uncollectable_ints(1, 1);
639
    /* Check that realloc updates object descriptors correctly */
640
    collectable_count++;
641
    f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr));
642
    realloc_count++;
643
    f = (sexpr *)GC_REALLOC((GC_PTR)f, 6 * sizeof(sexpr));
644
    f[5] = ints(1,17);
645
    collectable_count++;
646
    g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr));
647
    realloc_count++;
648
    g = (sexpr *)GC_REALLOC((GC_PTR)g, 800 * sizeof(sexpr));
649
    g[799] = ints(1,18);
650
    collectable_count++;
651
    h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr));
652
    realloc_count++;
653
    h = (sexpr *)GC_REALLOC((GC_PTR)h, 2000 * sizeof(sexpr));
654
#   ifdef GC_GCJ_SUPPORT
655
      h[1999] = gcj_ints(1,200);
656
      for (i = 0; i < 51; ++i)
657
        h[1999] = gcj_reverse(h[1999]);
658
      /* Leave it as the reveresed list for now. */
659
#   else
660
      h[1999] = ints(1,200);
661
#   endif
662
    /* Try to force some collections and reuse of small list elements */
663
      for (i = 0; i < 10; i++) {
664
        (void)ints(1, BIG);
665
      }
666
    /* Superficially test interior pointer recognition on stack */
667
      c = (sexpr)((char *)c + sizeof(char *));
668
      d = (sexpr)((char *)d + sizeof(char *));
669
 
670
#   ifdef __STDC__
671
        GC_FREE((void *)e);
672
#   else
673
        GC_FREE((char *)e);
674
#   endif
675
    check_ints(b,1,50);
676
    check_ints(a,1,49);
677
    for (i = 0; i < 50; i++) {
678
        check_ints(b,1,50);
679
        b = reverse(reverse(b));
680
    }
681
    check_ints(b,1,50);
682
    check_ints(a,1,49);
683
    for (i = 0; i < 60; i++) {
684
        if (i % 10 == 0) fork_a_thread();
685
        /* This maintains the invariant that a always points to a list of */
686
        /* 49 integers.  Thus this is thread safe without locks,          */
687
        /* assuming atomic pointer assignments.                           */
688
        a = reverse(reverse(a));
689
#       ifdef THREAD_LOCAL_ALLOC
690
          a = local_reverse(local_reverse(a));
691
#       endif
692
#       if !defined(AT_END) && !defined(THREADS)
693
          /* This is not thread safe, since realloc explicitly deallocates */
694
          if (i & 1) {
695
            a = (sexpr)GC_REALLOC((GC_PTR)a, 500);
696
          } else {
697
            a = (sexpr)GC_REALLOC((GC_PTR)a, 8200);
698
          }
699
#       endif
700
    }
701
    check_ints(a,1,49);
702
    check_ints(b,1,50);
703
    c = (sexpr)((char *)c - sizeof(char *));
704
    d = (sexpr)((char *)d - sizeof(char *));
705
    check_ints(c,1,BIG);
706
    check_uncollectable_ints(d, 1, 100);
707
    check_ints(f[5], 1,17);
708
    check_ints(g[799], 1,18);
709
#   ifdef GC_GCJ_SUPPORT
710
      h[1999] = gcj_reverse(h[1999]);
711
#   endif
712
    check_ints(h[1999], 1,200);
713
#   ifndef THREADS
714
        a = 0;
715
#   endif  
716
    b = c = 0;
717
}
718
 
719
#undef a
720
 
721
/*
722
 * The rest of this builds balanced binary trees, checks that they don't
723
 * disappear, and tests finalization.
724
 */
725
typedef struct treenode {
726
    int level;
727
    struct treenode * lchild;
728
    struct treenode * rchild;
729
} tn;
730
 
731
int finalizable_count = 0;
732
int finalized_count = 0;
733
VOLATILE int dropped_something = 0;
734
 
735
# ifdef __STDC__
736
  void finalizer(void * obj, void * client_data)
737
# else
738
  void finalizer(obj, client_data)
739
  char * obj;
740
  char * client_data;
741
# endif
742
{
743
  tn * t = (tn *)obj;
744
 
745
# ifdef PCR
746
     PCR_ThCrSec_EnterSys();
747
# endif
748
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
749
    static mutex_t incr_lock;
750
    mutex_lock(&incr_lock);
751
# endif
752
# if  defined(GC_PTHREADS)
753
    static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
754
    pthread_mutex_lock(&incr_lock);
755
# else
756
#   ifdef GC_WIN32_THREADS
757
      EnterCriticalSection(&incr_cs);
758
#   endif
759
# endif
760
  if ((int)(GC_word)client_data != t -> level) {
761
     (void)GC_printf0("Wrong finalization data - collector is broken\n");
762
     FAIL;
763
  }
764
  finalized_count++;
765
  t -> level = -1;      /* detect duplicate finalization immediately */
766
# ifdef PCR
767
    PCR_ThCrSec_ExitSys();
768
# endif
769
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
770
    mutex_unlock(&incr_lock);
771
# endif
772
# if defined(GC_PTHREADS)
773
    pthread_mutex_unlock(&incr_lock);
774
# else
775
#   ifdef GC_WIN32_THREADS
776
      LeaveCriticalSection(&incr_cs);
777
#   endif
778
# endif
779
}
780
 
781
size_t counter = 0;
782
 
783
# define MAX_FINALIZED 8000
784
 
785
# if !defined(MACOS)
786
  GC_FAR GC_word live_indicators[MAX_FINALIZED] = {0};
787
#else
788
  /* Too big for THINK_C. have to allocate it dynamically. */
789
  GC_word *live_indicators = 0;
790
#endif
791
 
792
int live_indicators_count = 0;
793
 
794
tn * mktree(n)
795
int n;
796
{
797
#   ifdef THREAD_LOCAL_ALLOC
798
      tn * result = (tn *)GC_LOCAL_MALLOC(sizeof(tn));
799
#   else
800
      tn * result = (tn *)GC_MALLOC(sizeof(tn));
801
#   endif
802
 
803
    collectable_count++;
804
#   ifdef THREAD_LOCAL_ALLOC
805
       /* Minimally exercise thread local allocation */
806
       {
807
         char * result = (char *)GC_LOCAL_MALLOC_ATOMIC(17);
808
         memset(result, 'a', 17);
809
       }
810
#   endif /* THREAD_LOCAL_ALLOC */
811
#   if defined(MACOS)
812
        /* get around static data limitations. */
813
        if (!live_indicators)
814
                live_indicators =
815
                    (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word));
816
        if (!live_indicators) {
817
          (void)GC_printf0("Out of memory\n");
818
          exit(1);
819
        }
820
#   endif
821
    if (n == 0) return(0);
822
    if (result == 0) {
823
        (void)GC_printf0("Out of memory\n");
824
        exit(1);
825
    }
826
    result -> level = n;
827
    result -> lchild = mktree(n-1);
828
    result -> rchild = mktree(n-1);
829
    if (counter++ % 17 == 0 && n >= 2) {
830
        tn * tmp = result -> lchild -> rchild;
831
 
832
        result -> lchild -> rchild = result -> rchild -> lchild;
833
        result -> rchild -> lchild = tmp;
834
    }
835
    if (counter++ % 119 == 0) {
836
        int my_index;
837
 
838
        {
839
#         ifdef PCR
840
            PCR_ThCrSec_EnterSys();
841
#         endif
842
#         if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
843
            static mutex_t incr_lock;
844
            mutex_lock(&incr_lock);
845
#         endif
846
#         if defined(GC_PTHREADS)
847
            static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
848
            pthread_mutex_lock(&incr_lock);
849
#         else
850
#           ifdef GC_WIN32_THREADS
851
              EnterCriticalSection(&incr_cs);
852
#           endif
853
#         endif
854
                /* Losing a count here causes erroneous report of failure. */
855
          finalizable_count++;
856
          my_index = live_indicators_count++;
857
#         ifdef PCR
858
            PCR_ThCrSec_ExitSys();
859
#         endif
860
#         if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
861
            mutex_unlock(&incr_lock);
862
#         endif
863
#         if defined(GC_PTHREADS)
864
            pthread_mutex_unlock(&incr_lock);
865
#         else
866
#           ifdef GC_WIN32_THREADS
867
              LeaveCriticalSection(&incr_cs);
868
#           endif
869
#         endif
870
        }
871
 
872
        GC_REGISTER_FINALIZER((GC_PTR)result, finalizer, (GC_PTR)(GC_word)n,
873
                              (GC_finalization_proc *)0, (GC_PTR *)0);
874
        if (my_index >= MAX_FINALIZED) {
875
                GC_printf0("live_indicators overflowed\n");
876
                FAIL;
877
        }
878
        live_indicators[my_index] = 13;
879
        if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
880
                (GC_PTR *)(&(live_indicators[my_index])),
881
                (GC_PTR)result) != 0) {
882
                GC_printf0("GC_general_register_disappearing_link failed\n");
883
                FAIL;
884
        }
885
        if (GC_unregister_disappearing_link(
886
                (GC_PTR *)
887
                   (&(live_indicators[my_index]))) == 0) {
888
                GC_printf0("GC_unregister_disappearing_link failed\n");
889
                FAIL;
890
        }
891
        if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
892
                (GC_PTR *)(&(live_indicators[my_index])),
893
                (GC_PTR)result) != 0) {
894
                GC_printf0("GC_general_register_disappearing_link failed 2\n");
895
                FAIL;
896
        }
897
    }
898
    return(result);
899
}
900
 
901
void chktree(t,n)
902
tn *t;
903
int n;
904
{
905
    if (n == 0 && t != 0) {
906
        (void)GC_printf0("Clobbered a leaf - collector is broken\n");
907
        FAIL;
908
    }
909
    if (n == 0) return;
910
    if (t -> level != n) {
911
        (void)GC_printf1("Lost a node at level %lu - collector is broken\n",
912
                         (unsigned long)n);
913
        FAIL;
914
    }
915
    if (counter++ % 373 == 0) {
916
        collectable_count++;
917
        (void) GC_MALLOC(counter%5001);
918
    }
919
    chktree(t -> lchild, n-1);
920
    if (counter++ % 73 == 0) {
921
        collectable_count++;
922
        (void) GC_MALLOC(counter%373);
923
    }
924
    chktree(t -> rchild, n-1);
925
}
926
 
927
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
928
thread_key_t fl_key;
929
 
930
void * alloc8bytes()
931
{
932
# if defined(SMALL_CONFIG) || defined(GC_DEBUG)
933
    collectable_count++;
934
    return(GC_MALLOC(8));
935
# else
936
    void ** my_free_list_ptr;
937
    void * my_free_list;
938
 
939
    if (thr_getspecific(fl_key, (void **)(&my_free_list_ptr)) != 0) {
940
        (void)GC_printf0("thr_getspecific failed\n");
941
        FAIL;
942
    }
943
    if (my_free_list_ptr == 0) {
944
        uncollectable_count++;
945
        my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *);
946
        if (thr_setspecific(fl_key, my_free_list_ptr) != 0) {
947
            (void)GC_printf0("thr_setspecific failed\n");
948
            FAIL;
949
        }
950
    }
951
    my_free_list = *my_free_list_ptr;
952
    if (my_free_list == 0) {
953
        collectable_count++;
954
        my_free_list = GC_malloc_many(8);
955
        if (my_free_list == 0) {
956
            (void)GC_printf0("alloc8bytes out of memory\n");
957
            FAIL;
958
        }
959
    }
960
    *my_free_list_ptr = GC_NEXT(my_free_list);
961
    GC_NEXT(my_free_list) = 0;
962
    return(my_free_list);
963
# endif
964
}
965
 
966
#else
967
 
968
# if defined(GC_PTHREADS)
969
pthread_key_t fl_key;
970
 
971
void * alloc8bytes()
972
{
973
# if defined(SMALL_CONFIG) || defined(GC_DEBUG)
974
    collectable_count++;
975
    return(GC_MALLOC(8));
976
# else
977
    void ** my_free_list_ptr;
978
    void * my_free_list;
979
 
980
    my_free_list_ptr = (void **)pthread_getspecific(fl_key);
981
    if (my_free_list_ptr == 0) {
982
        uncollectable_count++;
983
        my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *);
984
        if (pthread_setspecific(fl_key, my_free_list_ptr) != 0) {
985
            (void)GC_printf0("pthread_setspecific failed\n");
986
            FAIL;
987
        }
988
    }
989
    my_free_list = *my_free_list_ptr;
990
    if (my_free_list == 0) {
991
        my_free_list = GC_malloc_many(8);
992
        if (my_free_list == 0) {
993
            (void)GC_printf0("alloc8bytes out of memory\n");
994
            FAIL;
995
        }
996
    }
997
    *my_free_list_ptr = GC_NEXT(my_free_list);
998
    GC_NEXT(my_free_list) = 0;
999
    collectable_count++;
1000
    return(my_free_list);
1001
# endif
1002
}
1003
 
1004
# else
1005
#   define alloc8bytes() GC_MALLOC_ATOMIC(8)
1006
# endif
1007
#endif
1008
 
1009
void alloc_small(n)
1010
int n;
1011
{
1012
    register int i;
1013
 
1014
    for (i = 0; i < n; i += 8) {
1015
        atomic_count++;
1016
        if (alloc8bytes() == 0) {
1017
            (void)GC_printf0("Out of memory\n");
1018
            FAIL;
1019
        }
1020
    }
1021
}
1022
 
1023
# if defined(THREADS) && defined(GC_DEBUG)
1024
#   ifdef VERY_SMALL_CONFIG
1025
#     define TREE_HEIGHT 12
1026
#   else
1027
#     define TREE_HEIGHT 15
1028
#   endif
1029
# else
1030
#   ifdef VERY_SMALL_CONFIG
1031
#     define TREE_HEIGHT 13
1032
#   else
1033
#     define TREE_HEIGHT 16
1034
#   endif
1035
# endif
1036
void tree_test()
1037
{
1038
    tn * root;
1039
    register int i;
1040
 
1041
    root = mktree(TREE_HEIGHT);
1042
#   ifndef VERY_SMALL_CONFIG
1043
      alloc_small(5000000);
1044
#   endif
1045
    chktree(root, TREE_HEIGHT);
1046
    if (finalized_count && ! dropped_something) {
1047
        (void)GC_printf0("Premature finalization - collector is broken\n");
1048
        FAIL;
1049
    }
1050
    dropped_something = 1;
1051
    GC_noop(root);      /* Root needs to remain live until      */
1052
                        /* dropped_something is set.            */
1053
    root = mktree(TREE_HEIGHT);
1054
    chktree(root, TREE_HEIGHT);
1055
    for (i = TREE_HEIGHT; i >= 0; i--) {
1056
        root = mktree(i);
1057
        chktree(root, i);
1058
    }
1059
#   ifndef VERY_SMALL_CONFIG
1060
      alloc_small(5000000);
1061
#   endif
1062
}
1063
 
1064
unsigned n_tests = 0;
1065
 
1066
GC_word bm_huge[10] = {
1067
    0xffffffff,
1068
    0xffffffff,
1069
    0xffffffff,
1070
    0xffffffff,
1071
    0xffffffff,
1072
    0xffffffff,
1073
    0xffffffff,
1074
    0xffffffff,
1075
    0xffffffff,
1076
    0x00ffffff,
1077
};
1078
 
1079
/* A very simple test of explicitly typed allocation    */
1080
void typed_test()
1081
{
1082
    GC_word * old, * new;
1083
    GC_word bm3 = 0x3;
1084
    GC_word bm2 = 0x2;
1085
    GC_word bm_large = 0xf7ff7fff;
1086
    GC_descr d1 = GC_make_descriptor(&bm3, 2);
1087
    GC_descr d2 = GC_make_descriptor(&bm2, 2);
1088
#   ifndef LINT
1089
      GC_descr dummy = GC_make_descriptor(&bm_large, 32);
1090
#   endif
1091
    GC_descr d3 = GC_make_descriptor(&bm_large, 32);
1092
    GC_descr d4 = GC_make_descriptor(bm_huge, 320);
1093
    GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4);
1094
    register int i;
1095
 
1096
    collectable_count++;
1097
    old = 0;
1098
    for (i = 0; i < 4000; i++) {
1099
        collectable_count++;
1100
        new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1);
1101
        if (0 != new[0] || 0 != new[1]) {
1102
            GC_printf0("Bad initialization by GC_malloc_explicitly_typed\n");
1103
            FAIL;
1104
        }
1105
        new[0] = 17;
1106
        new[1] = (GC_word)old;
1107
        old = new;
1108
        collectable_count++;
1109
        new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2);
1110
        new[0] = 17;
1111
        new[1] = (GC_word)old;
1112
        old = new;
1113
        collectable_count++;
1114
        new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3);
1115
        new[0] = 17;
1116
        new[1] = (GC_word)old;
1117
        old = new;
1118
        collectable_count++;
1119
        new = (GC_word *) GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word),
1120
                                                     d1);
1121
        new[0] = 17;
1122
        new[1] = (GC_word)old;
1123
        old = new;
1124
        collectable_count++;
1125
        if (i & 0xff) {
1126
          new = (GC_word *) GC_calloc_explicitly_typed(7, 3 * sizeof(GC_word),
1127
                                                     d2);
1128
        } else {
1129
          new = (GC_word *) GC_calloc_explicitly_typed(1001,
1130
                                                       3 * sizeof(GC_word),
1131
                                                       d2);
1132
          if (0 != new[0] || 0 != new[1]) {
1133
            GC_printf0("Bad initialization by GC_malloc_explicitly_typed\n");
1134
            FAIL;
1135
          }
1136
        }
1137
        new[0] = 17;
1138
        new[1] = (GC_word)old;
1139
        old = new;
1140
    }
1141
    for (i = 0; i < 20000; i++) {
1142
        if (new[0] != 17) {
1143
            (void)GC_printf1("typed alloc failed at %lu\n",
1144
                             (unsigned long)i);
1145
            FAIL;
1146
        }
1147
        new[0] = 0;
1148
        old = new;
1149
        new = (GC_word *)(old[1]);
1150
    }
1151
    GC_gcollect();
1152
    GC_noop(x);
1153
}
1154
 
1155
int fail_count = 0;
1156
 
1157
#ifndef __STDC__
1158
/*ARGSUSED*/
1159
void fail_proc1(x)
1160
GC_PTR x;
1161
{
1162
    fail_count++;
1163
}
1164
 
1165
#else
1166
 
1167
/*ARGSUSED*/
1168
void fail_proc1(GC_PTR x)
1169
{
1170
    fail_count++;
1171
}
1172
 
1173
static void uniq(void *p, ...) {
1174
  va_list a;
1175
  void *q[100];
1176
  int n = 0, i, j;
1177
  q[n++] = p;
1178
  va_start(a,p);
1179
  for (;(q[n] = va_arg(a,void *));n++) ;
1180
  va_end(a);
1181
  for (i=0; i<n; i++)
1182
    for (j=0; j<i; j++)
1183
      if (q[i] == q[j]) {
1184
        GC_printf0(
1185
              "Apparently failed to mark form some function arguments.\n"
1186
              "Perhaps GC_push_regs was configured incorrectly?\n"
1187
        );
1188
        FAIL;
1189
      }
1190
}
1191
 
1192
#endif /* __STDC__ */
1193
 
1194
#ifdef THREADS
1195
#   define TEST_FAIL_COUNT(n) 1
1196
#else 
1197
#   define TEST_FAIL_COUNT(n) (fail_count >= (n))
1198
#endif
1199
 
1200
void run_one_test()
1201
{
1202
    char *x;
1203
#   ifdef LINT
1204
        char *y = 0;
1205
#   else
1206
        char *y = (char *)(size_t)fail_proc1;
1207
#   endif
1208
    DCL_LOCK_STATE;
1209
 
1210
#   ifdef FIND_LEAK
1211
        (void)GC_printf0(
1212
                "This test program is not designed for leak detection mode\n");
1213
        (void)GC_printf0("Expect lots of problems.\n");
1214
#   endif
1215
    GC_FREE(0);
1216
#   ifndef DBG_HDRS_ALL
1217
      collectable_count += 3;
1218
      if (GC_size(GC_malloc(7)) != 8 &&
1219
          GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)
1220
        || GC_size(GC_malloc(15)) != 16) {
1221
            (void)GC_printf0("GC_size produced unexpected results\n");
1222
            FAIL;
1223
      }
1224
      collectable_count += 1;
1225
      if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) {
1226
        (void)GC_printf1("GC_malloc(0) failed: GC_size returns %ld\n",
1227
                         GC_size(GC_malloc(0)));
1228
            FAIL;
1229
      }
1230
      collectable_count += 1;
1231
      if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) {
1232
        (void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
1233
            FAIL;
1234
      }
1235
      GC_is_valid_displacement_print_proc = fail_proc1;
1236
      GC_is_visible_print_proc = fail_proc1;
1237
      collectable_count += 1;
1238
      x = GC_malloc(16);
1239
      if (GC_base(x + 13) != x) {
1240
        (void)GC_printf0("GC_base(heap ptr) produced incorrect result\n");
1241
        FAIL;
1242
      }
1243
#     ifndef PCR
1244
        if (GC_base(y) != 0) {
1245
          (void)GC_printf0("GC_base(fn_ptr) produced incorrect result\n");
1246
          FAIL;
1247
        }
1248
#     endif
1249
      if (GC_same_obj(x+5, x) != x + 5) {
1250
        (void)GC_printf0("GC_same_obj produced incorrect result\n");
1251
        FAIL;
1252
      }
1253
      if (GC_is_visible(y) != y || GC_is_visible(x) != x) {
1254
        (void)GC_printf0("GC_is_visible produced incorrect result\n");
1255
        FAIL;
1256
      }
1257
      if (!TEST_FAIL_COUNT(1)) {
1258
#       if!(defined(RS6000) || defined(POWERPC) || defined(IA64)) || defined(M68K)
1259
          /* ON RS6000s function pointers point to a descriptor in the  */
1260
          /* data segment, so there should have been no failures.       */
1261
          /* The same applies to IA64.  Something similar seems to      */
1262
          /* be going on with NetBSD/M68K.                              */
1263
          (void)GC_printf0("GC_is_visible produced wrong failure indication\n");
1264
          FAIL;
1265
#       endif
1266
      }
1267
      if (GC_is_valid_displacement(y) != y
1268
        || GC_is_valid_displacement(x) != x
1269
        || GC_is_valid_displacement(x + 3) != x + 3) {
1270
        (void)GC_printf0(
1271
                "GC_is_valid_displacement produced incorrect result\n");
1272
        FAIL;
1273
      }
1274
#     if defined(__STDC__) && !defined(MSWIN32) && !defined(MSWINCE)
1275
        /* Harder to test under Windows without a gc.h declaration.  */
1276
        {
1277
          size_t i;
1278
          extern void *GC_memalign();
1279
 
1280
          GC_malloc(17);
1281
          for (i = sizeof(GC_word); i < 512; i *= 2) {
1282
            GC_word result = (GC_word) GC_memalign(i, 17);
1283
            if (result % i != 0 || result == 0 || *(int *)result != 0) FAIL;
1284
          }
1285
        }
1286
#     endif
1287
#     ifndef ALL_INTERIOR_POINTERS
1288
#      if defined(RS6000) || defined(POWERPC)
1289
        if (!TEST_FAIL_COUNT(1)) {
1290
#      else
1291
        if (GC_all_interior_pointers && !TEST_FAIL_COUNT(1)
1292
            || !GC_all_interior_pointers && !TEST_FAIL_COUNT(2)) {
1293
#      endif
1294
          (void)GC_printf0("GC_is_valid_displacement produced wrong failure indication\n");
1295
          FAIL;
1296
        }
1297
#     endif
1298
#   endif /* DBG_HDRS_ALL */
1299
    /* Test floating point alignment */
1300
   collectable_count += 2;
1301
        *(double *)GC_MALLOC(sizeof(double)) = 1.0;
1302
        *(double *)GC_MALLOC(sizeof(double)) = 1.0;
1303
#   ifdef GC_GCJ_SUPPORT
1304
      GC_REGISTER_DISPLACEMENT(sizeof(struct fake_vtable *));
1305
      GC_init_gcj_malloc(0, (void *)fake_gcj_mark_proc);
1306
#   endif
1307
    /* Make sure that fn arguments are visible to the collector.        */
1308
#   ifdef __STDC__
1309
      uniq(
1310
        GC_malloc(12), GC_malloc(12), GC_malloc(12),
1311
        (GC_gcollect(),GC_malloc(12)),
1312
        GC_malloc(12), GC_malloc(12), GC_malloc(12),
1313
        (GC_gcollect(),GC_malloc(12)),
1314
        GC_malloc(12), GC_malloc(12), GC_malloc(12),
1315
        (GC_gcollect(),GC_malloc(12)),
1316
        GC_malloc(12), GC_malloc(12), GC_malloc(12),
1317
        (GC_gcollect(),GC_malloc(12)),
1318
        GC_malloc(12), GC_malloc(12), GC_malloc(12),
1319
        (GC_gcollect(),GC_malloc(12)),
1320
        (void *)0);
1321
#   endif
1322
    /* Repeated list reversal test. */
1323
        reverse_test();
1324
#   ifdef PRINTSTATS
1325
        GC_printf0("-------------Finished reverse_test\n");
1326
#   endif
1327
#   ifndef DBG_HDRS_ALL
1328
      typed_test();
1329
#     ifdef PRINTSTATS
1330
        GC_printf0("-------------Finished typed_test\n");
1331
#     endif
1332
#   endif /* DBG_HDRS_ALL */
1333
    tree_test();
1334
    LOCK();
1335
    n_tests++;
1336
    UNLOCK();
1337
#   if defined(THREADS) && defined(HANDLE_FORK)
1338
      if (fork() == 0) {
1339
        GC_gcollect();
1340
        tiny_reverse_test(0);
1341
        GC_gcollect();
1342
        GC_printf0("Finished a child process\n");
1343
        exit(0);
1344
      }
1345
#   endif
1346
    /* GC_printf1("Finished %x\n", pthread_self()); */
1347
}
1348
 
1349
void check_heap_stats()
1350
{
1351
    unsigned long max_heap_sz;
1352
    register int i;
1353
    int still_live;
1354
    int late_finalize_count = 0;
1355
 
1356
#   ifdef VERY_SMALL_CONFIG
1357
    /* these are something of a guess */
1358
    if (sizeof(char *) > 4) {
1359
        max_heap_sz = 4500000;
1360
    } else {
1361
        max_heap_sz = 2800000;
1362
    }
1363
#   else
1364
    if (sizeof(char *) > 4) {
1365
        max_heap_sz = 19000000;
1366
    } else {
1367
        max_heap_sz = 11000000;
1368
    }
1369
#   endif
1370
#   ifdef GC_DEBUG
1371
        max_heap_sz *= 2;
1372
#       ifdef SAVE_CALL_CHAIN
1373
            max_heap_sz *= 3;
1374
#           ifdef SAVE_CALL_COUNT
1375
                max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4;
1376
#           endif
1377
#       endif
1378
#   endif
1379
    /* Garbage collect repeatedly so that all inaccessible objects      */
1380
    /* can be finalized.                                                */
1381
      while (GC_collect_a_little()) { }
1382
      for (i = 0; i < 16; i++) {
1383
        GC_gcollect();
1384
        late_finalize_count += GC_invoke_finalizers();
1385
      }
1386
    (void)GC_printf1("Completed %lu tests\n", (unsigned long)n_tests);
1387
    (void)GC_printf1("Allocated %lu collectable objects\n", (unsigned long)collectable_count);
1388
    (void)GC_printf1("Allocated %lu uncollectable objects\n", (unsigned long)uncollectable_count);
1389
    (void)GC_printf1("Allocated %lu atomic objects\n", (unsigned long)atomic_count);
1390
    (void)GC_printf1("Allocated %lu stubborn objects\n", (unsigned long)stubborn_count);
1391
    (void)GC_printf2("Finalized %lu/%lu objects - ",
1392
                     (unsigned long)finalized_count,
1393
                     (unsigned long)finalizable_count);
1394
#   ifdef FINALIZE_ON_DEMAND
1395
        if (finalized_count != late_finalize_count) {
1396
            (void)GC_printf0("Demand finalization error\n");
1397
            FAIL;
1398
        }
1399
#   endif
1400
    if (finalized_count > finalizable_count
1401
        || finalized_count < finalizable_count/2) {
1402
        (void)GC_printf0("finalization is probably broken\n");
1403
        FAIL;
1404
    } else {
1405
        (void)GC_printf0("finalization is probably ok\n");
1406
    }
1407
    still_live = 0;
1408
    for (i = 0; i < MAX_FINALIZED; i++) {
1409
        if (live_indicators[i] != 0) {
1410
            still_live++;
1411
        }
1412
    }
1413
    i = finalizable_count - finalized_count - still_live;
1414
    if (0 != i) {
1415
        (void)GC_printf2
1416
            ("%lu disappearing links remain and %ld more objects were not finalized\n",
1417
             (unsigned long) still_live, (long)i);
1418
        if (i > 10) {
1419
            GC_printf0("\tVery suspicious!\n");
1420
        } else {
1421
            GC_printf0("\tSlightly suspicious, but probably OK.\n");
1422
        }
1423
    }
1424
    (void)GC_printf1("Total number of bytes allocated is %lu\n",
1425
                (unsigned long)
1426
                   WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc));
1427
    (void)GC_printf1("Final heap size is %lu bytes\n",
1428
                     (unsigned long)GC_get_heap_size());
1429
    if (WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc)
1430
#   ifdef VERY_SMALL_CONFIG
1431
        < 2700000*n_tests) {
1432
#   else
1433
        < 33500000*n_tests) {
1434
#   endif
1435
        (void)GC_printf0("Incorrect execution - missed some allocations\n");
1436
        FAIL;
1437
    }
1438
    if (GC_get_heap_size() > max_heap_sz*n_tests) {
1439
        (void)GC_printf0("Unexpected heap growth - collector may be broken\n");
1440
        FAIL;
1441
    }
1442
    (void)GC_printf0("Collector appears to work\n");
1443
}
1444
 
1445
#if defined(MACOS)
1446
void SetMinimumStack(long minSize)
1447
{
1448
        long newApplLimit;
1449
 
1450
        if (minSize > LMGetDefltStack())
1451
        {
1452
                newApplLimit = (long) GetApplLimit()
1453
                                - (minSize - LMGetDefltStack());
1454
                SetApplLimit((Ptr) newApplLimit);
1455
                MaxApplZone();
1456
        }
1457
}
1458
 
1459
#define cMinStackSpace (512L * 1024L)
1460
 
1461
#endif
1462
 
1463
#ifdef __STDC__
1464
    void warn_proc(char *msg, GC_word p)
1465
#else
1466
    void warn_proc(msg, p)
1467
    char *msg;
1468
    GC_word p;
1469
#endif
1470
{
1471
    GC_printf1(msg, (unsigned long)p);
1472
    /*FAIL;*/
1473
}
1474
 
1475
 
1476
#if !defined(PCR) && !defined(GC_SOLARIS_THREADS) \
1477
    && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \
1478
    || defined(LINT)
1479
#if defined(MSWIN32) && !defined(__MINGW32__)
1480
  int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPTSTR cmd, int n)
1481
#else
1482
  int main()
1483
#endif
1484
{
1485
#   if defined(DJGPP)
1486
        int dummy;
1487
#   endif
1488
    n_tests = 0;
1489
 
1490
#   if defined(DJGPP)
1491
        /* No good way to determine stack base from library; do it */
1492
        /* manually on this platform.                              */
1493
        GC_stackbottom = (GC_PTR)(&dummy);
1494
#   endif
1495
#   if defined(MACOS)
1496
        /* Make sure we have lots and lots of stack space.      */
1497
        SetMinimumStack(cMinStackSpace);
1498
        /* Cheat and let stdio initialize toolbox for us.       */
1499
        printf("Testing GC Macintosh port.\n");
1500
#   endif
1501
    GC_INIT();  /* Only needed on a few platforms.      */
1502
    (void) GC_set_warn_proc(warn_proc);
1503
#   if (defined(MPROTECT_VDB) || defined(PROC_VDB)) \
1504
          && !defined(MAKE_BACK_GRAPH)
1505
      GC_enable_incremental();
1506
      (void) GC_printf0("Switched to incremental mode\n");
1507
#     if defined(MPROTECT_VDB)
1508
        (void)GC_printf0("Emulating dirty bits with mprotect/signals\n");
1509
#     else
1510
#       ifdef PROC_VDB
1511
        (void)GC_printf0("Reading dirty bits from /proc\n");
1512
#       else
1513
    (void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n");
1514
#       endif
1515
#      endif
1516
#   endif
1517
    run_one_test();
1518
    check_heap_stats();
1519
#   ifndef MSWINCE
1520
    (void)fflush(stdout);
1521
#   endif
1522
#   ifdef LINT
1523
        /* Entry points we should be testing, but aren't.                  */
1524
        /* Some can be tested by defining GC_DEBUG at the top of this file */
1525
        /* This is a bit SunOS4 specific.                                  */
1526
        GC_noop(GC_expand_hp, GC_add_roots, GC_clear_roots,
1527
                GC_register_disappearing_link,
1528
                GC_register_finalizer_ignore_self,
1529
                GC_debug_register_displacement,
1530
                GC_print_obj, GC_debug_change_stubborn,
1531
                GC_debug_end_stubborn_change, GC_debug_malloc_uncollectable,
1532
                GC_debug_free, GC_debug_realloc, GC_generic_malloc_words_small,
1533
                GC_init, GC_make_closure, GC_debug_invoke_finalizer,
1534
                GC_page_was_ever_dirty, GC_is_fresh,
1535
                GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page,
1536
                GC_set_max_heap_size, GC_get_bytes_since_gc,
1537
                GC_get_total_bytes, GC_pre_incr, GC_post_incr);
1538
#   endif
1539
#   ifdef MSWIN32
1540
      GC_win32_free_heap();
1541
#   endif
1542
    return(0);
1543
}
1544
# endif
1545
 
1546
#if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)
1547
 
1548
DWORD __stdcall thr_run_one_test(void *arg)
1549
{
1550
  run_one_test();
1551
  return 0;
1552
}
1553
 
1554
#ifdef MSWINCE
1555
HANDLE win_created_h;
1556
HWND win_handle;
1557
 
1558
LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1559
{
1560
  LRESULT ret = 0;
1561
  switch (uMsg) {
1562
    case WM_HIBERNATE:
1563
      GC_printf0("Received WM_HIBERNATE, calling GC_gcollect\n");
1564
      GC_gcollect();
1565
      break;
1566
    case WM_CLOSE:
1567
      GC_printf0("Received WM_CLOSE, closing window\n");
1568
      DestroyWindow(hwnd);
1569
      break;
1570
    case WM_DESTROY:
1571
      PostQuitMessage(0);
1572
      break;
1573
    default:
1574
      ret = DefWindowProc(hwnd, uMsg, wParam, lParam);
1575
      break;
1576
  }
1577
  return ret;
1578
}
1579
 
1580
DWORD __stdcall thr_window(void *arg)
1581
{
1582
  WNDCLASS win_class = {
1583
    CS_NOCLOSE,
1584
    window_proc,
1585
    0,
1586
    0,
1587
    GetModuleHandle(NULL),
1588
    NULL,
1589
    NULL,
1590
    (HBRUSH)(COLOR_APPWORKSPACE+1),
1591
    NULL,
1592
    L"GCtestWindow"
1593
  };
1594
  MSG msg;
1595
 
1596
  if (!RegisterClass(&win_class))
1597
    FAIL;
1598
 
1599
  win_handle = CreateWindowEx(
1600
    0,
1601
    L"GCtestWindow",
1602
    L"GCtest",
1603
    0,
1604
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1605
    NULL,
1606
    NULL,
1607
    GetModuleHandle(NULL),
1608
    NULL);
1609
 
1610
  if (win_handle == NULL)
1611
    FAIL;
1612
 
1613
  SetEvent(win_created_h);
1614
 
1615
  ShowWindow(win_handle, SW_SHOW);
1616
  UpdateWindow(win_handle);
1617
 
1618
  while (GetMessage(&msg, NULL, 0, 0)) {
1619
    TranslateMessage(&msg);
1620
    DispatchMessage(&msg);
1621
  }
1622
 
1623
  return 0;
1624
}
1625
#endif
1626
 
1627
#define NTEST 2
1628
 
1629
# ifdef MSWINCE
1630
int APIENTRY GC_WinMain(HINSTANCE instance, HINSTANCE prev, LPWSTR cmd, int n)
1631
#   else
1632
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
1633
# endif
1634
{
1635
# if NTEST > 0
1636
   HANDLE h[NTEST];
1637
   int i;
1638
# endif
1639
# ifdef MSWINCE
1640
    HANDLE win_thr_h;
1641
# endif
1642
  DWORD thread_id;
1643
# if 0
1644
    GC_enable_incremental();
1645
# endif
1646
  GC_init();
1647
  InitializeCriticalSection(&incr_cs);
1648
  (void) GC_set_warn_proc(warn_proc);
1649
# ifdef MSWINCE
1650
    win_created_h = CreateEvent(NULL, FALSE, FALSE, NULL);
1651
    if (win_created_h == (HANDLE)NULL) {
1652
      (void)GC_printf1("Event creation failed %lu\n", (unsigned long)GetLastError());
1653
      FAIL;
1654
    }
1655
    win_thr_h = GC_CreateThread(NULL, 0, thr_window, 0, 0, &thread_id);
1656
    if (win_thr_h == (HANDLE)NULL) {
1657
      (void)GC_printf1("Thread creation failed %lu\n", (unsigned long)GetLastError());
1658
      FAIL;
1659
    }
1660
    if (WaitForSingleObject(win_created_h, INFINITE) != WAIT_OBJECT_0)
1661
      FAIL;
1662
    CloseHandle(win_created_h);
1663
# endif
1664
# if NTEST > 0
1665
   for (i = 0; i < NTEST; i++) {
1666
    h[i] = GC_CreateThread(NULL, 0, thr_run_one_test, 0, 0, &thread_id);
1667
    if (h[i] == (HANDLE)NULL) {
1668
      (void)GC_printf1("Thread creation failed %lu\n", (unsigned long)GetLastError());
1669
      FAIL;
1670
    }
1671
   }
1672
# endif /* NTEST > 0 */
1673
  run_one_test();
1674
# if NTEST > 0
1675
   for (i = 0; i < NTEST; i++) {
1676
    if (WaitForSingleObject(h[i], INFINITE) != WAIT_OBJECT_0) {
1677
      (void)GC_printf1("Thread wait failed %lu\n", (unsigned long)GetLastError());
1678
      FAIL;
1679
    }
1680
   }
1681
# endif /* NTEST > 0 */
1682
# ifdef MSWINCE
1683
    PostMessage(win_handle, WM_CLOSE, 0, 0);
1684
    if (WaitForSingleObject(win_thr_h, INFINITE) != WAIT_OBJECT_0)
1685
      FAIL;
1686
# endif
1687
  check_heap_stats();
1688
  return(0);
1689
}
1690
 
1691
#endif /* GC_WIN32_THREADS */
1692
 
1693
 
1694
#ifdef PCR
1695
test()
1696
{
1697
    PCR_Th_T * th1;
1698
    PCR_Th_T * th2;
1699
    int code;
1700
 
1701
    n_tests = 0;
1702
    /* GC_enable_incremental(); */
1703
    (void) GC_set_warn_proc(warn_proc);
1704
    th1 = PCR_Th_Fork(run_one_test, 0);
1705
    th2 = PCR_Th_Fork(run_one_test, 0);
1706
    run_one_test();
1707
    if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1708
        != PCR_ERes_okay || code != 0) {
1709
        (void)GC_printf0("Thread 1 failed\n");
1710
    }
1711
    if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1712
        != PCR_ERes_okay || code != 0) {
1713
        (void)GC_printf0("Thread 2 failed\n");
1714
    }
1715
    check_heap_stats();
1716
    return(0);
1717
}
1718
#endif
1719
 
1720
#if defined(GC_SOLARIS_THREADS) || defined(GC_PTHREADS)
1721
void * thr_run_one_test(void * arg)
1722
{
1723
    run_one_test();
1724
    return(0);
1725
}
1726
 
1727
#ifdef GC_DEBUG
1728
#  define GC_free GC_debug_free
1729
#endif
1730
 
1731
#if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
1732
main()
1733
{
1734
    thread_t th1;
1735
    thread_t th2;
1736
    int code;
1737
 
1738
    n_tests = 0;
1739
    GC_INIT();  /* Only needed if gc is dynamic library.        */
1740
#   ifndef MAKE_BACK_GRAPH
1741
      GC_enable_incremental();
1742
#   endif
1743
    (void) GC_set_warn_proc(warn_proc);
1744
    if (thr_keycreate(&fl_key, GC_free) != 0) {
1745
        (void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
1746
        FAIL;
1747
    }
1748
    if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, 0, &th1)) != 0) {
1749
        (void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1750
        FAIL;
1751
    }
1752
    if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, THR_NEW_LWP, &th2)) != 0) {
1753
        (void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1754
        FAIL;
1755
    }
1756
    run_one_test();
1757
    if ((code = thr_join(th1, 0, 0)) != 0) {
1758
        (void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1759
        FAIL;
1760
    }
1761
    if (thr_join(th2, 0, 0) != 0) {
1762
        (void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1763
        FAIL;
1764
    }
1765
    check_heap_stats();
1766
    (void)fflush(stdout);
1767
    return(0);
1768
}
1769
#else /* pthreads */
1770
 
1771
#ifndef GC_PTHREADS
1772
  --> bad news
1773
#endif
1774
 
1775
main()
1776
{
1777
    pthread_t th1;
1778
    pthread_t th2;
1779
    pthread_attr_t attr;
1780
    int code;
1781
 
1782
#   ifdef GC_IRIX_THREADS
1783
        /* Force a larger stack to be preallocated      */
1784
        /* Since the initial cant always grow later.    */
1785
        *((volatile char *)&code - 1024*1024) = 0;      /* Require 1 Mb */
1786
#   endif /* GC_IRIX_THREADS */
1787
#   if defined(GC_HPUX_THREADS)
1788
        /* Default stack size is too small, especially with the 64 bit ABI */
1789
        /* Increase it.                                                    */
1790
        if (pthread_default_stacksize_np(1024*1024, 0) != 0) {
1791
          (void)GC_printf0("pthread_default_stacksize_np failed.\n");
1792
        }
1793
#   endif       /* GC_HPUX_THREADS */
1794
    GC_INIT();
1795
 
1796
    pthread_attr_init(&attr);
1797
#   if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
1798
        || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
1799
        pthread_attr_setstacksize(&attr, 1000000);
1800
#   endif
1801
    n_tests = 0;
1802
#   if (defined(MPROTECT_VDB)) \
1803
            && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) \
1804
            && !defined(MAKE_BACK_GRAPH)
1805
        GC_enable_incremental();
1806
        (void) GC_printf0("Switched to incremental mode\n");
1807
#     if defined(MPROTECT_VDB)
1808
        (void)GC_printf0("Emulating dirty bits with mprotect/signals\n");
1809
#     else
1810
#       ifdef PROC_VDB
1811
            (void)GC_printf0("Reading dirty bits from /proc\n");
1812
#       else
1813
            (void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n");
1814
#       endif
1815
#     endif
1816
#   endif
1817
    (void) GC_set_warn_proc(warn_proc);
1818
    if ((code = pthread_key_create(&fl_key, 0)) != 0) {
1819
        (void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
1820
        FAIL;
1821
    }
1822
    if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) {
1823
        (void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1824
        FAIL;
1825
    }
1826
    if ((code = pthread_create(&th2, &attr, thr_run_one_test, 0)) != 0) {
1827
        (void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1828
        FAIL;
1829
    }
1830
    run_one_test();
1831
    if ((code = pthread_join(th1, 0)) != 0) {
1832
        (void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1833
        FAIL;
1834
    }
1835
    if (pthread_join(th2, 0) != 0) {
1836
        (void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1837
        FAIL;
1838
    }
1839
    check_heap_stats();
1840
    (void)fflush(stdout);
1841
    pthread_attr_destroy(&attr);
1842
    GC_printf1("Completed %d collections\n", GC_gc_no);
1843
    return(0);
1844
}
1845
#endif /* GC_PTHREADS */
1846
#endif /* GC_SOLARIS_THREADS || GC_PTHREADS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.