37
37
# include <assert.h> /* Not normally used, but handy for debugging. */
39
# include <assert.h> /* Not normally used, but handy for debugging. */
41
40
# include "gc_typed.h"
42
# ifdef THREAD_LOCAL_ALLOC
43
# include "gc_local_alloc.h"
45
41
# include "private/gc_priv.h" /* For output, locking, MIN_WORDS, */
46
/* and some statistics. */
47
# include "private/gcconfig.h"
42
/* and some statistics, and gcconfig.h. */
49
44
# if defined(MSWIN32) || defined(MSWINCE)
50
45
# include <windows.h>
47
# define GC_print_stats 0 /* Not exported from DLL */
48
/* Redefine to 1 to generate output. */
54
53
# include "th/PCR_ThCrSec.h"
55
54
# include "th/PCR_Th.h"
57
# define GC_printf0 printf
59
# define GC_printf1 printf
62
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
55
# define GC_printf printf
67
58
# if defined(GC_PTHREADS)
112
110
ret=GC_calloc_explicitly_typed(a,lb,d);
115
GC_printf0("Out of memory, (typed allocations are not directly "
116
"supported with the GC_AMIGA_FASTALLOC option.)\n");
113
GC_printf("Out of memory, (typed allocations are not directly "
114
"supported with the GC_AMIGA_FASTALLOC option.)\n");
166
165
# ifdef VERY_SMALL_CONFIG
167
166
# define cons small_cons
168
sexpr cons (sexpr x, sexpr y)
175
register int my_extra = extra_count;
172
int my_extra = extra_count;
177
174
stubborn_count++;
178
175
r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra);
180
(void)GC_printf0("Out of memory\n");
177
(void)GC_printf("Out of memory\n");
183
180
for (p = (int *)r;
184
181
((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
186
(void)GC_printf1("Found nonzero at 0x%lx - allocator is broken\n",
183
(void)GC_printf("Found nonzero at %p - allocator is broken\n", p);
186
*p = (int)((13 << 12) + ((p - (int *)r) & 0xfff));
193
189
r = (sexpr)((char *)r + (my_extra & ~7));
237
233
x = (sexpr)(addr + 1); /* Skip the vtable pointer. */
238
234
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));
235
(void *)(x -> sexpr_cdr), mark_stack_ptr,
236
mark_stack_limit, (void * *)&(x -> sexpr_cdr));
241
237
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));
238
(void *)(x -> sexpr_car), mark_stack_ptr,
239
mark_stack_limit, (void * *)&(x -> sexpr_car));
244
240
return(mark_stack_ptr);
247
243
#endif /* GC_GCJ_SUPPORT */
249
#ifdef THREAD_LOCAL_ALLOC
251
#undef GC_REDIRECT_TO_LOCAL
252
#include "gc_local_alloc.h"
254
sexpr local_cons (x, y)
260
register int my_extra = extra_count;
261
static int my_random = 0;
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,
269
r = (sexpr) ((GC_word *)r + 1);
273
(void)GC_printf0("Out of memory\n");
277
((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
279
(void)GC_printf1("Found nonzero at 0x%lx (local) - allocator is broken\n",
288
if ( my_extra >= 5000 || my_extra == 200 && ++my_random % 37 != 0) {
291
extra_count = my_extra;
295
#endif /* THREAD_LOCAL_ALLOC */
297
sexpr small_cons (x, y)
246
sexpr small_cons (sexpr x, sexpr y)
303
250
collectable_count++;
304
251
r = (sexpr) GC_MALLOC(sizeof(struct SEXPR));
306
(void)GC_printf0("Out of memory\n");
253
(void)GC_printf("Out of memory\n");
309
256
r -> sexpr_car = x;
314
sexpr small_cons_uncollectable (x, y)
261
sexpr small_cons_uncollectable (sexpr x, sexpr y)
320
265
uncollectable_count++;
321
266
r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR));
323
(void)GC_printf0("Out of memory\n");
268
(void)GC_printf("Out of memory\n");
326
271
r -> sexpr_car = x;
327
r -> sexpr_cdr = (sexpr)(~(unsigned long)y);
272
r -> sexpr_cdr = (sexpr)(~(GC_word)y);
331
276
#ifdef GC_GCJ_SUPPORT
279
sexpr gcj_cons(sexpr x, sexpr y)
340
283
static int count = 0;
343
# ifdef USE_MARK_BYTES
344
r = (GC_word *) GC_GCJ_FAST_MALLOC(4, &gcj_class_struct1);
346
r = (GC_word *) GC_GCJ_FAST_MALLOC(3, &gcj_class_struct1);
349
r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR)
350
+ sizeof(struct fake_vtable*),
285
r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR)
286
+ sizeof(struct fake_vtable*),
354
(void)GC_printf0("Out of memory\n");
289
(void)GC_printf("Out of memory\n");
357
292
result = (sexpr)(r + 1);
421
350
#endif /* GC_GCJ_SUPPORT */
423
#ifdef THREAD_LOCAL_ALLOC
424
/* Return reverse(x) concatenated with y */
425
sexpr local_reverse1(x, y)
431
return( local_reverse1(cdr(x), local_cons(car(x), y)) );
435
sexpr local_reverse(x)
438
return( local_reverse1(x, nil) );
441
sexpr local_ints(low, up)
447
return(local_cons(local_cons(INT_TO_SEXPR(low), nil), local_ints(low+1, up)));
450
#endif /* THREAD_LOCAL_ALLOC */
452
352
/* To check uncollectable allocation we build lists with disguised cdr */
453
353
/* pointers, and make sure they don't go away. */
454
sexpr uncollectable_ints(low, up)
354
sexpr uncollectable_ints(int low, int up)
465
void check_ints(list, low, up)
364
void check_ints(sexpr list, int low, int up)
469
if ((int)(GC_word)(car(car(list))) != low) {
366
if (SEXPR_TO_INT(car(car(list))) != low) {
471
368
"List reversal produced incorrect list - collector is broken\n");
475
372
if (cdr(list) != nil) {
476
(void)GC_printf0("List too long - collector is broken\n");
373
(void)GC_printf("List too long - collector is broken\n");
484
# define UNCOLLECTABLE_CDR(x) (sexpr)(~(unsigned long)(cdr(x)))
381
# define UNCOLLECTABLE_CDR(x) (sexpr)(~(GC_word)(cdr(x)))
486
void check_uncollectable_ints(list, low, up)
383
void check_uncollectable_ints(sexpr list, int low, int up)
490
if ((int)(GC_word)(car(car(list))) != low) {
385
if (SEXPR_TO_INT(car(car(list))) != low) {
492
387
"Uncollectable list corrupted - collector is broken\n");
496
391
if (UNCOLLECTABLE_CDR(list) != nil) {
497
(void)GC_printf0("Uncollectable list too long - collector is broken\n");
392
(void)GC_printf("Uncollectable list too long - collector is broken\n");
505
400
/* Not used, but useful for debugging: */
506
void print_int_list(x)
401
void print_int_list(sexpr x)
510
(void)GC_printf0("NIL\n");
404
(void)GC_printf("NIL\n");
512
(void)GC_printf1("(%ld)", (long)(car(car(x))));
406
(void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x))));
513
407
if (!is_nil(cdr(x))) {
514
(void)GC_printf0(", ");
408
(void)GC_printf(", ");
515
409
(void)print_int_list(cdr(x));
517
(void)GC_printf0("\n");
411
(void)GC_printf("\n");
417
void check_marks_int_list(sexpr x)
419
if (!GC_is_marked((ptr_t)x))
420
GC_printf("[unm:%p]", x);
422
GC_printf("[mkd:%p]", x);
424
(void)GC_printf("NIL\n");
426
if (!GC_is_marked((ptr_t)car(x))) GC_printf("[unm car:%p]", car(x));
427
(void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x))));
428
if (!is_nil(cdr(x))) {
429
(void)GC_printf(", ");
430
(void)check_marks_int_list(cdr(x));
432
(void)GC_printf("\n");
548
460
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);
461
(void)GC_printf("Small thread creation failed %d\n", code);
553
464
if ((code = pthread_join(t, 0)) != 0) {
554
(void)GC_printf1("Small thread join failed %lu\n",
555
(unsigned long)code);
465
(void)GC_printf("Small thread join failed %d\n", code);
565
475
h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id);
566
476
if (h == (HANDLE)NULL) {
567
(void)GC_printf1("Small thread creation failed %lu\n",
568
(unsigned long)GetLastError());
477
(void)GC_printf("Small thread creation failed %d\n",
571
481
if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
572
(void)GC_printf1("Small thread wait failed %lu\n",
573
(unsigned long)GetLastError());
482
(void)GC_printf("Small thread wait failed %d\n",
578
/* # elif defined(GC_SOLARIS_THREADS) */
582
490
# define fork_a_thread()
640
548
collectable_count++;
641
549
f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr));
643
f = (sexpr *)GC_REALLOC((GC_PTR)f, 6 * sizeof(sexpr));
551
f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr));
644
552
f[5] = ints(1,17);
645
553
collectable_count++;
646
554
g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr));
648
g = (sexpr *)GC_REALLOC((GC_PTR)g, 800 * sizeof(sexpr));
556
g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr));
649
557
g[799] = ints(1,18);
650
558
collectable_count++;
651
559
h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr));
653
h = (sexpr *)GC_REALLOC((GC_PTR)h, 2000 * sizeof(sexpr));
561
h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr));
654
562
# ifdef GC_GCJ_SUPPORT
655
563
h[1999] = gcj_ints(1,200);
656
564
for (i = 0; i < 51; ++i)
686
594
/* 49 integers. Thus this is thread safe without locks, */
687
595
/* assuming atomic pointer assignments. */
688
596
a = reverse(reverse(a));
689
# ifdef THREAD_LOCAL_ALLOC
690
a = local_reverse(local_reverse(a));
692
597
# if !defined(AT_END) && !defined(THREADS)
693
598
/* This is not thread safe, since realloc explicitly deallocates */
695
a = (sexpr)GC_REALLOC((GC_PTR)a, 500);
600
a = (sexpr)GC_REALLOC((void *)a, 500);
697
a = (sexpr)GC_REALLOC((GC_PTR)a, 8200);
602
a = (sexpr)GC_REALLOC((void *)a, 8200);
746
651
PCR_ThCrSec_EnterSys();
748
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
749
static mutex_t incr_lock;
750
mutex_lock(&incr_lock);
752
# if defined(GC_PTHREADS)
653
# if defined(GC_PTHREADS)
753
654
static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
754
655
pthread_mutex_lock(&incr_lock);
756
# ifdef GC_WIN32_THREADS
757
EnterCriticalSection(&incr_cs);
656
# elif defined(GC_WIN32_THREADS)
657
EnterCriticalSection(&incr_cs);
760
659
if ((int)(GC_word)client_data != t -> level) {
761
(void)GC_printf0("Wrong finalization data - collector is broken\n");
660
(void)GC_printf("Wrong finalization data - collector is broken\n");
764
663
finalized_count++;
767
666
PCR_ThCrSec_ExitSys();
769
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
770
mutex_unlock(&incr_lock);
772
668
# if defined(GC_PTHREADS)
773
669
pthread_mutex_unlock(&incr_lock);
775
# ifdef GC_WIN32_THREADS
776
LeaveCriticalSection(&incr_cs);
670
# elif defined(GC_WIN32_THREADS)
671
LeaveCriticalSection(&incr_cs);
792
686
int live_indicators_count = 0;
797
# ifdef THREAD_LOCAL_ALLOC
798
tn * result = (tn *)GC_LOCAL_MALLOC(sizeof(tn));
800
tn * result = (tn *)GC_MALLOC(sizeof(tn));
690
tn * result = (tn *)GC_MALLOC(sizeof(tn));
803
692
collectable_count++;
804
# ifdef THREAD_LOCAL_ALLOC
805
/* Minimally exercise thread local allocation */
807
char * result = (char *)GC_LOCAL_MALLOC_ATOMIC(17);
808
memset(result, 'a', 17);
810
# endif /* THREAD_LOCAL_ALLOC */
811
693
# if defined(MACOS)
812
694
/* get around static data limitations. */
813
695
if (!live_indicators)
814
696
live_indicators =
815
697
(GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word));
816
698
if (!live_indicators) {
817
(void)GC_printf0("Out of memory\n");
699
(void)GC_printf("Out of memory\n");
821
703
if (n == 0) return(0);
822
704
if (result == 0) {
823
(void)GC_printf0("Out of memory\n");
705
(void)GC_printf("Out of memory\n");
826
708
result -> level = n;
840
722
PCR_ThCrSec_EnterSys();
842
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
843
static mutex_t incr_lock;
844
mutex_lock(&incr_lock);
846
724
# if defined(GC_PTHREADS)
847
725
static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
848
726
pthread_mutex_lock(&incr_lock);
850
# ifdef GC_WIN32_THREADS
851
EnterCriticalSection(&incr_cs);
727
# elif defined(GC_WIN32_THREADS)
728
EnterCriticalSection(&incr_cs);
854
730
/* Losing a count here causes erroneous report of failure. */
855
731
finalizable_count++;
858
734
PCR_ThCrSec_ExitSys();
860
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
861
mutex_unlock(&incr_lock);
863
736
# if defined(GC_PTHREADS)
864
737
pthread_mutex_unlock(&incr_lock);
866
# ifdef GC_WIN32_THREADS
867
LeaveCriticalSection(&incr_cs);
738
# elif defined(GC_WIN32_THREADS)
739
LeaveCriticalSection(&incr_cs);
872
GC_REGISTER_FINALIZER((GC_PTR)result, finalizer, (GC_PTR)(GC_word)n,
873
(GC_finalization_proc *)0, (GC_PTR *)0);
743
GC_REGISTER_FINALIZER((void *)result, finalizer, (void *)(GC_word)n,
744
(GC_finalization_proc *)0, (void * *)0);
874
745
if (my_index >= MAX_FINALIZED) {
875
GC_printf0("live_indicators overflowed\n");
746
GC_printf("live_indicators overflowed\n");
878
749
live_indicators[my_index] = 13;
879
750
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");
751
(void * *)(&(live_indicators[my_index])),
752
(void *)result) != 0) {
753
GC_printf("GC_general_register_disappearing_link failed\n");
885
756
if (GC_unregister_disappearing_link(
887
758
(&(live_indicators[my_index]))) == 0) {
888
GC_printf0("GC_unregister_disappearing_link failed\n");
759
GC_printf("GC_unregister_disappearing_link failed\n");
891
762
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");
763
(void * *)(&(live_indicators[my_index])),
764
(void *)result) != 0) {
765
GC_printf("GC_general_register_disappearing_link failed 2\n");
768
GC_reachable_here(result);
773
void chktree(tn *t, int n)
905
775
if (n == 0 && t != 0) {
906
(void)GC_printf0("Clobbered a leaf - collector is broken\n");
776
(void)GC_printf("Clobbered a leaf - collector is broken\n");
909
779
if (n == 0) return;
910
780
if (t -> level != n) {
911
(void)GC_printf1("Lost a node at level %lu - collector is broken\n",
781
(void)GC_printf("Lost a node at level %d - collector is broken\n", n);
915
784
if (counter++ % 373 == 0) {
924
793
chktree(t -> rchild, n-1);
927
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
932
# if defined(SMALL_CONFIG) || defined(GC_DEBUG)
934
return(GC_MALLOC(8));
936
void ** my_free_list_ptr;
939
if (thr_getspecific(fl_key, (void **)(&my_free_list_ptr)) != 0) {
940
(void)GC_printf0("thr_getspecific failed\n");
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");
951
my_free_list = *my_free_list_ptr;
952
if (my_free_list == 0) {
954
my_free_list = GC_malloc_many(8);
955
if (my_free_list == 0) {
956
(void)GC_printf0("alloc8bytes out of memory\n");
960
*my_free_list_ptr = GC_NEXT(my_free_list);
961
GC_NEXT(my_free_list) = 0;
962
return(my_free_list);
968
# if defined(GC_PTHREADS)
797
#if defined(GC_PTHREADS)
969
798
pthread_key_t fl_key;
971
800
void * alloc8bytes()
1085
912
GC_word bm_large = 0xf7ff7fff;
1086
913
GC_descr d1 = GC_make_descriptor(&bm3, 2);
1087
914
GC_descr d2 = GC_make_descriptor(&bm2, 2);
1089
GC_descr dummy = GC_make_descriptor(&bm_large, 32);
1091
915
GC_descr d3 = GC_make_descriptor(&bm_large, 32);
1092
916
GC_descr d4 = GC_make_descriptor(bm_huge, 320);
1093
917
GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4);
921
(void)GC_make_descriptor(&bm_large, 32);
1096
923
collectable_count++;
1098
925
for (i = 0; i < 4000; i++) {
1099
926
collectable_count++;
1100
927
new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1);
1101
928
if (0 != new[0] || 0 != new[1]) {
1102
GC_printf0("Bad initialization by GC_malloc_explicitly_typed\n");
929
GC_printf("Bad initialization by GC_malloc_explicitly_typed\n");
1200
1027
void run_one_test()
1206
1034
char *y = (char *)(size_t)fail_proc1;
1036
CLOCK_TYPE start_time;
1037
CLOCK_TYPE reverse_time;
1038
CLOCK_TYPE typed_time;
1039
CLOCK_TYPE tree_time;
1040
unsigned long time_diff;
1208
1041
DCL_LOCK_STATE;
1210
1043
# ifdef FIND_LEAK
1212
1045
"This test program is not designed for leak detection mode\n");
1213
(void)GC_printf0("Expect lots of problems.\n");
1046
GC_printf("Expect lots of problems.\n");
1216
1049
# ifndef DBG_HDRS_ALL
1217
1050
collectable_count += 3;
1218
if (GC_size(GC_malloc(7)) != 8 &&
1219
GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)
1051
if ((GC_size(GC_malloc(7)) != 8 &&
1052
GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word))
1220
1053
|| GC_size(GC_malloc(15)) != 16) {
1221
(void)GC_printf0("GC_size produced unexpected results\n");
1054
GC_printf("GC_size produced unexpected results\n");
1224
1057
collectable_count += 1;
1225
1058
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)));
1059
GC_printf("GC_malloc(0) failed: GC_size returns %ld\n",
1060
(unsigned long)GC_size(GC_malloc(0)));
1230
1063
collectable_count += 1;
1231
1064
if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) {
1232
(void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
1065
GC_printf("GC_malloc_uncollectable(0) failed\n");
1235
1068
GC_is_valid_displacement_print_proc = fail_proc1;
1236
1069
GC_is_visible_print_proc = fail_proc1;
1237
1070
collectable_count += 1;
1238
1071
x = GC_malloc(16);
1239
1072
if (GC_base(x + 13) != x) {
1240
(void)GC_printf0("GC_base(heap ptr) produced incorrect result\n");
1073
GC_printf("GC_base(heap ptr) produced incorrect result\n");
1244
1077
if (GC_base(y) != 0) {
1245
(void)GC_printf0("GC_base(fn_ptr) produced incorrect result\n");
1078
GC_printf("GC_base(fn_ptr) produced incorrect result\n");
1249
1082
if (GC_same_obj(x+5, x) != x + 5) {
1250
(void)GC_printf0("GC_same_obj produced incorrect result\n");
1083
GC_printf("GC_same_obj produced incorrect result\n");
1253
1086
if (GC_is_visible(y) != y || GC_is_visible(x) != x) {
1254
(void)GC_printf0("GC_is_visible produced incorrect result\n");
1087
GC_printf("GC_is_visible produced incorrect result\n");
1093
GC_printf("GC_PTR_STORE failed: %p != %p\n", *z, x);
1257
1096
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 */
1097
# if!(defined(POWERPC) || defined(IA64)) || defined(M68K)
1098
/* On POWERPCs function pointers point to a descriptor in the */
1260
1099
/* data segment, so there should have been no failures. */
1261
1100
/* The same applies to IA64. Something similar seems to */
1262
1101
/* be going on with NetBSD/M68K. */
1263
(void)GC_printf0("GC_is_visible produced wrong failure indication\n");
1102
GC_printf("GC_is_visible produced wrong failure indication\n");
1267
1106
if (GC_is_valid_displacement(y) != y
1268
1107
|| GC_is_valid_displacement(x) != x
1269
1108
|| GC_is_valid_displacement(x + 3) != x + 3) {
1271
1110
"GC_is_valid_displacement produced incorrect result\n");
1291
1130
if (GC_all_interior_pointers && !TEST_FAIL_COUNT(1)
1292
1131
|| !GC_all_interior_pointers && !TEST_FAIL_COUNT(2)) {
1294
(void)GC_printf0("GC_is_valid_displacement produced wrong failure indication\n");
1133
GC_printf("GC_is_valid_displacement produced wrong failure indication\n");
1298
1137
# endif /* DBG_HDRS_ALL */
1299
1138
/* Test floating point alignment */
1300
collectable_count += 2;
1301
*(double *)GC_MALLOC(sizeof(double)) = 1.0;
1302
*(double *)GC_MALLOC(sizeof(double)) = 1.0;
1139
collectable_count += 2;
1140
*(double *)GC_MALLOC(sizeof(double)) = 1.0;
1141
*(double *)GC_MALLOC(sizeof(double)) = 1.0;
1142
/* Test size 0 allocation a bit more */
1145
for (i = 0; i < 10000; ++i) {
1147
GC_FREE(GC_MALLOC(0));
1148
GC_MALLOC_ATOMIC(0);
1149
GC_FREE(GC_MALLOC_ATOMIC(0));
1303
1152
# ifdef GC_GCJ_SUPPORT
1304
1153
GC_REGISTER_DISPLACEMENT(sizeof(struct fake_vtable *));
1305
1154
GC_init_gcj_malloc(0, (void *)fake_gcj_mark_proc);
1319
1168
(GC_gcollect(),GC_malloc(12)),
1171
/* GC_malloc(0) must return NULL or something we can deallocate. */
1172
GC_free(GC_malloc(0));
1173
GC_free(GC_malloc_atomic(0));
1174
GC_free(GC_malloc(0));
1175
GC_free(GC_malloc_atomic(0));
1322
1176
/* Repeated list reversal test. */
1177
GET_TIME(start_time);
1323
1178
reverse_test();
1325
GC_printf0("-------------Finished reverse_test\n");
1179
if (GC_print_stats) {
1180
GET_TIME(reverse_time);
1181
time_diff = MS_TIME_DIFF(reverse_time, start_time);
1182
GC_log_printf("-------------Finished reverse_test at time %u (%p)\n",
1183
(unsigned) time_diff, &start_time);
1327
1185
# ifndef DBG_HDRS_ALL
1330
GC_printf0("-------------Finished typed_test\n");
1187
if (GC_print_stats) {
1188
GET_TIME(typed_time);
1189
time_diff = MS_TIME_DIFF(typed_time, start_time);
1190
GC_log_printf("-------------Finished typed_test at time %u (%p)\n",
1191
(unsigned) time_diff, &start_time);
1332
1193
# endif /* DBG_HDRS_ALL */
1195
if (GC_print_stats) {
1196
GET_TIME(tree_time);
1197
time_diff = MS_TIME_DIFF(tree_time, start_time);
1198
GC_log_printf("-------------Finished tree_test at time %u (%p)\n",
1199
(unsigned) time_diff, &start_time);
1388
1253
late_finalize_count += GC_invoke_finalizers();
1390
(void)GC_printf1("Completed %lu tests\n", (unsigned long)n_tests);
1391
(void)GC_printf1("Allocated %lu collectable objects\n", (unsigned long)collectable_count);
1392
(void)GC_printf1("Allocated %lu uncollectable objects\n", (unsigned long)uncollectable_count);
1393
(void)GC_printf1("Allocated %lu atomic objects\n", (unsigned long)atomic_count);
1394
(void)GC_printf1("Allocated %lu stubborn objects\n", (unsigned long)stubborn_count);
1395
(void)GC_printf2("Finalized %lu/%lu objects - ",
1396
(unsigned long)finalized_count,
1397
(unsigned long)finalizable_count);
1255
(void)GC_printf("Completed %u tests\n", n_tests);
1256
(void)GC_printf("Allocated %d collectable objects\n", collectable_count);
1257
(void)GC_printf("Allocated %d uncollectable objects\n",
1258
uncollectable_count);
1259
(void)GC_printf("Allocated %d atomic objects\n", atomic_count);
1260
(void)GC_printf("Allocated %d stubborn objects\n", stubborn_count);
1261
(void)GC_printf("Finalized %d/%d objects - ",
1262
finalized_count, finalizable_count);
1398
1263
# ifdef FINALIZE_ON_DEMAND
1399
1264
if (finalized_count != late_finalize_count) {
1400
(void)GC_printf0("Demand finalization error\n");
1265
(void)GC_printf("Demand finalization error\n");
1404
1269
if (finalized_count > finalizable_count
1405
1270
|| finalized_count < finalizable_count/2) {
1406
(void)GC_printf0("finalization is probably broken\n");
1271
(void)GC_printf("finalization is probably broken\n");
1409
(void)GC_printf0("finalization is probably ok\n");
1274
(void)GC_printf("finalization is probably ok\n");
1411
1276
still_live = 0;
1412
1277
for (i = 0; i < MAX_FINALIZED; i++) {
1417
1282
i = finalizable_count - finalized_count - still_live;
1420
("%lu disappearing links remain and %ld more objects were not finalized\n",
1421
(unsigned long) still_live, (long)i);
1284
GC_printf("%d disappearing links remain and %d more objects "
1285
"were not finalized\n", still_live, i);
1423
GC_printf0("\tVery suspicious!\n");
1287
GC_printf("\tVery suspicious!\n");
1425
GC_printf0("\tSlightly suspicious, but probably OK.\n");
1289
GC_printf("\tSlightly suspicious, but probably OK.\n");
1428
(void)GC_printf1("Total number of bytes allocated is %lu\n",
1292
(void)GC_printf("Total number of bytes allocated is %lu\n",
1429
1293
(unsigned long)
1430
WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc));
1431
(void)GC_printf1("Final heap size is %lu bytes\n",
1432
(unsigned long)GC_get_heap_size());
1433
if (WORDS_TO_BYTES(GC_words_allocd + GC_words_allocd_before_gc)
1294
(GC_bytes_allocd + GC_bytes_allocd_before_gc));
1295
(void)GC_printf("Final heap size is %lu bytes\n",
1296
(unsigned long)GC_get_heap_size());
1297
if (GC_bytes_allocd + GC_bytes_allocd_before_gc
1434
1298
# ifdef VERY_SMALL_CONFIG
1435
1299
< 2700000*n_tests) {
1437
1301
< 33500000*n_tests) {
1439
(void)GC_printf0("Incorrect execution - missed some allocations\n");
1303
(void)GC_printf("Incorrect execution - missed some allocations\n");
1442
1306
if (GC_get_heap_size() > max_heap_sz*n_tests) {
1443
(void)GC_printf0("Unexpected heap growth - collector may be broken\n");
1307
(void)GC_printf("Unexpected heap growth - collector may be broken\n");
1446
(void)GC_printf0("Collector appears to work\n");
1310
(void)GC_printf("Collector appears to work\n");
1449
1313
#if defined(MACOS)
1502
1366
/* Cheat and let stdio initialize toolbox for us. */
1503
1367
printf("Testing GC Macintosh port.\n");
1505
GC_INIT(); /* Only needed on a few platforms. */
1506
(void) GC_set_warn_proc(warn_proc);
1507
# if (defined(MPROTECT_VDB) || defined(PROC_VDB)) \
1508
&& !defined(MAKE_BACK_GRAPH)
1370
GC_set_warn_proc(warn_proc);
1371
# if (defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(GWW_VDB)) \
1372
&& !defined(MAKE_BACK_GRAPH) && !defined(NO_INCREMENTAL)
1509
1373
GC_enable_incremental();
1510
(void) GC_printf0("Switched to incremental mode\n");
1374
GC_printf("Switched to incremental mode\n");
1511
1375
# if defined(MPROTECT_VDB)
1512
(void)GC_printf0("Emulating dirty bits with mprotect/signals\n");
1376
GC_printf("Emulating dirty bits with mprotect/signals\n");
1514
1378
# ifdef PROC_VDB
1515
(void)GC_printf0("Reading dirty bits from /proc\n");
1379
GC_printf("Reading dirty bits from /proc\n");
1517
(void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n");
1381
GC_printf("Using DEFAULT_VDB dirty bit implementation\n");
1521
1385
run_one_test();
1522
1386
check_heap_stats();
1523
1387
# ifndef MSWINCE
1524
(void)fflush(stdout);
1527
1391
/* Entry points we should be testing, but aren't. */
1644
1508
HANDLE win_thr_h;
1646
1510
DWORD thread_id;
1513
GC_use_DllMain(); /* Test with implicit thread registration if possible. */
1514
GC_printf("Using DllMain to track threads\n");
1517
# ifndef NO_INCREMENTAL
1648
1518
GC_enable_incremental();
1651
1520
InitializeCriticalSection(&incr_cs);
1652
1521
(void) GC_set_warn_proc(warn_proc);
1653
1522
# ifdef MSWINCE
1654
1523
win_created_h = CreateEvent(NULL, FALSE, FALSE, NULL);
1655
1524
if (win_created_h == (HANDLE)NULL) {
1656
(void)GC_printf1("Event creation failed %lu\n", (unsigned long)GetLastError());
1525
(void)GC_printf("Event creation failed %\n", GetLastError());
1659
1528
win_thr_h = GC_CreateThread(NULL, 0, thr_window, 0, 0, &thread_id);
1660
1529
if (win_thr_h == (HANDLE)NULL) {
1661
(void)GC_printf1("Thread creation failed %lu\n", (unsigned long)GetLastError());
1530
(void)GC_printf("Thread creation failed %d\n", GetLastError());
1664
1533
if (WaitForSingleObject(win_created_h, INFINITE) != WAIT_OBJECT_0)
1669
1538
for (i = 0; i < NTEST; i++) {
1670
1539
h[i] = GC_CreateThread(NULL, 0, thr_run_one_test, 0, 0, &thread_id);
1671
1540
if (h[i] == (HANDLE)NULL) {
1672
(void)GC_printf1("Thread creation failed %lu\n", (unsigned long)GetLastError());
1541
(void)GC_printf("Thread creation failed %d\n", GetLastError());
1710
1579
run_one_test();
1711
1580
if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1712
1581
!= PCR_ERes_okay || code != 0) {
1713
(void)GC_printf0("Thread 1 failed\n");
1582
(void)GC_printf("Thread 1 failed\n");
1715
1584
if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
1716
1585
!= PCR_ERes_okay || code != 0) {
1717
(void)GC_printf0("Thread 2 failed\n");
1586
(void)GC_printf("Thread 2 failed\n");
1719
1588
check_heap_stats();
1724
#if defined(GC_SOLARIS_THREADS) || defined(GC_PTHREADS)
1593
#if defined(GC_PTHREADS)
1725
1594
void * thr_run_one_test(void * arg)
1727
1596
run_one_test();
1732
1601
# define GC_free GC_debug_free
1735
#if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
1743
GC_INIT(); /* Only needed if gc is dynamic library. */
1744
# ifndef MAKE_BACK_GRAPH
1745
GC_enable_incremental();
1747
(void) GC_set_warn_proc(warn_proc);
1748
if (thr_keycreate(&fl_key, GC_free) != 0) {
1749
(void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
1752
if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, 0, &th1)) != 0) {
1753
(void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1756
if ((code = thr_create(0, 1024*1024, thr_run_one_test, 0, THR_NEW_LWP, &th2)) != 0) {
1757
(void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1761
if ((code = thr_join(th1, 0, 0)) != 0) {
1762
(void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1765
if (thr_join(th2, 0, 0) != 0) {
1766
(void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1770
(void)fflush(stdout);
1773
#else /* pthreads */
1783
1608
pthread_attr_t attr;
1786
1610
# ifdef GC_IRIX_THREADS
1787
1611
/* Force a larger stack to be preallocated */
1788
1612
/* Since the initial cant always grow later. */
1792
1616
/* Default stack size is too small, especially with the 64 bit ABI */
1793
1617
/* Increase it. */
1794
1618
if (pthread_default_stacksize_np(1024*1024, 0) != 0) {
1795
(void)GC_printf0("pthread_default_stacksize_np failed.\n");
1619
(void)GC_printf("pthread_default_stacksize_np failed.\n");
1797
1621
# endif /* GC_HPUX_THREADS */
1622
# ifdef PTW32_STATIC_LIB
1623
pthread_win32_process_attach_np ();
1624
pthread_win32_thread_attach_np ();
1800
1628
pthread_attr_init(&attr);
1801
1629
# if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
1806
1634
# if (defined(MPROTECT_VDB)) \
1807
1635
&& !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) \
1808
&& !defined(MAKE_BACK_GRAPH)
1636
&& !defined(MAKE_BACK_GRAPH) && !defined(USE_PROC_FOR_LIBRARIES) \
1637
&& !defined(NO_INCREMENTAL)
1809
1638
GC_enable_incremental();
1810
(void) GC_printf0("Switched to incremental mode\n");
1639
(void) GC_printf("Switched to incremental mode\n");
1811
1640
# if defined(MPROTECT_VDB)
1812
(void)GC_printf0("Emulating dirty bits with mprotect/signals\n");
1641
(void)GC_printf("Emulating dirty bits with mprotect/signals\n");
1814
1643
# ifdef PROC_VDB
1815
(void)GC_printf0("Reading dirty bits from /proc\n");
1644
(void)GC_printf("Reading dirty bits from /proc\n");
1817
(void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n");
1646
(void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n");
1821
1650
(void) GC_set_warn_proc(warn_proc);
1822
1651
if ((code = pthread_key_create(&fl_key, 0)) != 0) {
1823
(void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
1652
(void)GC_printf("Key creation failed %d\n", code);
1826
1655
if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) {
1827
(void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
1656
(void)GC_printf("Thread 1 creation failed %d\n", code);
1830
1659
if ((code = pthread_create(&th2, &attr, thr_run_one_test, 0)) != 0) {
1831
(void)GC_printf1("Thread 2 creation failed %lu\n", (unsigned long)code);
1660
(void)GC_printf("Thread 2 creation failed %d\n", code);
1834
1663
run_one_test();
1835
1664
if ((code = pthread_join(th1, 0)) != 0) {
1836
(void)GC_printf1("Thread 1 failed %lu\n", (unsigned long)code);
1665
(void)GC_printf("Thread 1 failed %d\n", code);
1839
1668
if (pthread_join(th2, 0) != 0) {
1840
(void)GC_printf1("Thread 2 failed %lu\n", (unsigned long)code);
1669
(void)GC_printf("Thread 2 failed %d\n", code);
1843
1672
check_heap_stats();
1844
1673
(void)fflush(stdout);
1845
1674
pthread_attr_destroy(&attr);
1846
GC_printf1("Completed %d collections\n", GC_gc_no);
1675
GC_printf("Completed %d collections\n", GC_gc_no);
1676
# ifdef PTW32_STATIC_LIB
1677
pthread_win32_thread_detach_np ();
1678
pthread_win32_process_detach_np ();
1849
1682
#endif /* GC_PTHREADS */
1850
#endif /* GC_SOLARIS_THREADS || GC_PTHREADS */