From: Ivan Maidanski Date: Tue, 13 Sep 2011 06:58:36 +0000 (+0400) Subject: ENABLE_DISCLAIM: Make stylistic fixes in many places and add many FIXME. X-Git-Tag: gc7_3alpha2~320^2~14 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b30ed5b081184a3f5624096dbcb02e97003eeee;p=gc ENABLE_DISCLAIM: Make stylistic fixes in many places and add many FIXME. --- diff --git a/Makefile.direct b/Makefile.direct index 85a1e239..0cf9426c 100644 --- a/Makefile.direct +++ b/Makefile.direct @@ -36,7 +36,7 @@ VPATH= $(srcdir) AO_SRC_DIR=$(srcdir)/libatomic_ops AO_INSTALL_DIR=$(srcdir)/libatomic_ops-install -CFLAGS= -O -I$(srcdir)/include -I$(AO_INSTALL_DIR)/include -DATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM +CFLAGS= -O -I$(srcdir)/include -I$(AO_INSTALL_DIR)/include -DATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS # To build the parallel collector on Linux, add to the above: # -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC @@ -74,16 +74,14 @@ OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o \ headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o \ malloc.o stubborn.o checksums.o pthread_support.o pthread_stop_world.o \ darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o gcj_mlc.o specific.o \ - gc_dlopen.o backgraph.o win32_threads.o pthread_start.o thread_local_alloc.o \ - disclaim.o + gc_dlopen.o backgraph.o win32_threads.o pthread_start.o thread_local_alloc.o CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c \ headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c \ new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c \ checksums.c pthread_support.c pthread_stop_world.c darwin_stop_world.c \ typd_mlc.c ptr_chck.c mallocx.c gcj_mlc.c specific.c gc_dlopen.c \ - backgraph.c win32_threads.c pthread_start.c thread_local_alloc.c \ - disclaim.c + backgraph.c win32_threads.c pthread_start.c thread_local_alloc.c CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/tests/de.c \ cord/tests/cordtest.c include/cord.h include/ec.h \ @@ -103,7 +101,7 @@ SRCS= $(CSRCS) \ include/javaxfc.h \ include/gc_backptr.h include/gc_gcj.h include/private/dbg_mlc.h \ include/private/specific.h include/leak_detector.h \ - include/gc_pthread_redirects.h include/gc_disclaim.h \ + include/gc_pthread_redirects.h \ include/gc_config_macros.h include/private/pthread_support.h \ include/private/pthread_stop_world.h include/private/darwin_semaphore.h \ include/private/darwin_stop_world.h include/private/thread_local_alloc.h \ diff --git a/disclaim.c b/disclaim.c index c18133a2..1a639133 100644 --- a/disclaim.c +++ b/disclaim.c @@ -12,13 +12,23 @@ * */ +// FIXME: Move this code to another existing file (which is appropriate), +// and remove this file (adding a new file is a bit complex due to numerous +// scripts present). + #include "private/gc_priv.h" + +// FIXME: add #ifdef ENABLE_DISCLAIM + #include "private/thread_local_alloc.h" -#include "gc_disclaim.h" + // FIXME: we can include it only if THREAD_LOCAL_ALLOC. +#include "gc_disclaim.h" /* Low level interface for reclaim callbacks. */ +// FIXME: Use declared type for proc. +// FIXME: Use GC_API and GC_CALL. void GC_register_disclaim_proc(int kind, int (*proc)(void *obj, void *cd), void *cd, int mark_unconditionally) @@ -28,20 +38,25 @@ void GC_register_disclaim_proc(int kind, GC_obj_kinds[kind].ok_mark_unconditionally = mark_unconditionally; } - /* High level interface for finalization. */ -int GC_finalized_kind; +STATIC int GC_finalized_kind; -int GC_finalized_debug_kind; +STATIC ptr_t * GC_finalized_objfreelist = 0; +STATIC ptr_t * GC_finalized_debugobjfreelist = 0; -ptr_t * GC_finalized_objfreelist; -ptr_t * GC_finalized_debugobjfreelist; -static int GC_finalized_disclaim(void *obj, void *cd) +STATIC int GC_finalized_disclaim(void *obj, void *cd) // FIXME: Add CALLBACK { struct GC_finalizer_closure *fc = *(void **)obj; - if ((word)fc & 1) { /* See [1] */ + if (((word)fc & 1) != 0) { + /* The disclaim function may be passed fragments from the free-list, on + * which it should not run finalization. To recognize this case, we use + * the fact that the first word on such fragments are always even (a link + * to the next fragment, or NULL). If it is desirable to have a finalizer + * which does not use the first word for storing finalization info, + * GC_reclaim_with_finalization must be extended to clear fragments so + * that the assumption holds for the selected word. */ fc = (void *)((word)fc & ~(word)1); (*fc->proc)((void **)obj + 1, fc->cd); } @@ -49,15 +64,19 @@ static int GC_finalized_disclaim(void *obj, void *cd) } static int done_init = 0; -void GC_init_finalized_malloc() + +// FIXME: GC_API +void GC_init_finalized_malloc(void) { DCL_LOCK_STATE; - if (done_init) + + if (done_init) // FIXME: Is race possible here? return; - GC_init(); + GC_init(); // FIXME: Portable client should always do GC_INIT() itself + LOCK(); if (done_init) - goto done; + goto done; // FIXME: avoid "goto" if possible done_init = 1; GC_finalized_objfreelist = (ptr_t *)GC_new_free_list_inner(); @@ -71,11 +90,13 @@ done: UNLOCK(); } -void * GC_clear_stack(); +void * GC_clear_stack(); // FIXME: remove as declared in gc_priv.h #ifdef THREAD_LOCAL_ALLOC - void * GC_core_finalized_malloc(size_t lb, struct GC_finalizer_closure *fclos) + STATIC void * GC_core_finalized_malloc(size_t lb, + struct GC_finalizer_closure *fclos) #else +// FIXME: add GC_API, GC_CALL void * GC_finalized_malloc(size_t lb, struct GC_finalizer_closure *fclos) #endif { @@ -84,7 +105,7 @@ void * GC_clear_stack(); DCL_LOCK_STATE; lb += sizeof(void *); - if (!done_init) + if (!done_init) // FIXME: Probably GC_ASSERT is adequate here? ABORT("You must call GC_init_finalize_malloc before using " "GC_malloc_with_finalizer."); if (EXPECT(SMALL_OBJ(lb), 1)) { @@ -101,21 +122,25 @@ void * GC_clear_stack(); GC_bytes_allocd += GRANULES_TO_BYTES(lg); UNLOCK(); } - } else + } else { op = GC_generic_malloc((word)lb, GC_finalized_kind); + } *(void **)op = (ptr_t)fclos + 1; /* See [1] */ return GC_clear_stack(op + sizeof(void *)); } #ifdef THREAD_LOCAL_ALLOC -void * GC_finalized_malloc(size_t client_lb, struct GC_finalizer_closure *fclos) -{ + // FIXME: GC_API, GC_CALL + void * GC_finalized_malloc(size_t client_lb, + struct GC_finalizer_closure *fclos) + { size_t lb = client_lb + sizeof(void *); size_t lg = ROUNDED_UP_GRANULES(lb); GC_tlfs tsd; void *result; void **tiny_fl, **my_fl, *my_entry; void *next; + if (GC_EXPECT(lg >= GC_TINY_FREELISTS, 0)) return GC_core_finalized_malloc(client_lb, fclos); @@ -142,13 +167,5 @@ void * GC_finalized_malloc(size_t client_lb, struct GC_finalizer_closure *fclos) *(void **)result = (ptr_t)fclos + 1; PREFETCH_FOR_WRITE(next); return (void **)result + 1; -} -#endif - -/* [1] The disclaim function may be passed fragments from the free-list, on - * which it should not run finalization. To recognize this case, we use - * the fact that the first word on such fragments are always even (a link - * to the next fragment, or NULL). If it is desirable to have a finalizer - * which does not use the first word for storing finalization info, - * GC_reclaim_with_finalization must be extended to clear fragments so - * that the assumption holds for the selected word. */ + } +#endif /* THREAD_LOCAL_ALLOC */ diff --git a/include/gc_disclaim.h b/include/gc_disclaim.h index 46b2272f..d179c008 100644 --- a/include/gc_disclaim.h +++ b/include/gc_disclaim.h @@ -12,8 +12,11 @@ * */ -#ifndef _GC_DISCLAIM_H -#define _GC_DISCLAIM_H +// FIXME: Add this file to that many scripts we have (see, e.g., gc_mark.h +// as a reference). + +#ifndef GC_DISCLAIM_H +#define GC_DISCLAIM_H #include "gc.h" @@ -23,13 +26,15 @@ /* will be protected from collection if "mark_from_all" is non-zero, */ /* but at the expense that long chains of objects will take many cycles */ /* to reclaim. */ +// FIXME: declare type for callback, use GC_CALBACK +// FIXME: comment out all parameter names void GC_register_disclaim_proc(int kind, int (*proc)(void *obj, void *cd), void *cd, int mark_from_all); /* The finalizer closure used by GC_finalized_malloc. */ struct GC_finalizer_closure { - void (*proc)(void *obj, void *cd); + void (*proc)(void *obj, void *cd); // FIXME: use typedef void *cd; }; @@ -42,4 +47,7 @@ GC_API void *GC_finalized_malloc(size_t size, struct GC_finalizer_closure *fc); /* Prepare the object kind used for GC_finalized_malloc. */ GC_API void GC_init_finalized_malloc(void); +// FIXME: Use GC_CALL and GC_API +// FIXME: GC_init_finalized_malloc: replace with + #endif diff --git a/include/include.am b/include/include.am index a3c64d58..fa40630e 100644 --- a/include/include.am +++ b/include/include.am @@ -30,6 +30,7 @@ pkginclude_HEADERS += \ include/gc_version.h if ENABLE_DISCLAIM +# FIXME: all include headers must be in pkginclude_HEADERS inconditionally pkginclude_HEADERS += include/gc_disclaim.h endif EXTRA_DIST += include/gc_disclaim.h diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index eaefbd82..0f3fb3fa 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -816,10 +816,10 @@ struct hblkhdr { # define FREE_BLK 4 /* Block is free, i.e. not in use. */ # ifdef ENABLE_DISCLAIM # define HAS_DISCLAIM 8 - /* This kind has a callback on reclaim. */ + /* This kind has a callback on reclaim. */ # define MARK_UNCONDITIONALLY 16 /* Mark from all objects, marked or */ - /* not. Used to mark objects needed by */ + /* not. Used to mark objects needed by */ /* reclaim notifier. */ # endif unsigned short hb_last_reclaimed; @@ -1237,7 +1237,7 @@ GC_EXTERN struct obj_kind { /* Mark from all, including unmarked, objects */ /* in block. Used to protect objects reachable */ /* from reclaim notifiers. */ - int (*ok_disclaim_proc)(void *obj, void *cd); + int (*ok_disclaim_proc)(void *obj, void *cd); // FIXME: GC_CALLBACK void *ok_disclaim_cd; /* The disclaim procedure is called before obj */ /* is reclaimed, but must also tolerate being */ @@ -1245,8 +1245,8 @@ GC_EXTERN struct obj_kind { /* exit prevents object from being reclaimed. */ # define OK_DISCLAIM_INITZ FALSE, NULL, NULL # else -# define OK_DISCLAIM_INITZ -# endif +# define OK_DISCLAIM_INITZ /* empty */ +# endif /* !ENABLE_DISCLAIM */ } GC_obj_kinds[MAXOBJKINDS]; #define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds)) diff --git a/reclaim.c b/reclaim.c index ef87f078..f009c2a3 100644 --- a/reclaim.c +++ b/reclaim.c @@ -15,7 +15,8 @@ */ #include "private/gc_priv.h" -#include "gc_disclaim.h" + +#include "gc_disclaim.h" // FIXME: add ifdef #include @@ -212,12 +213,12 @@ STATIC ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz, } #ifdef ENABLE_DISCLAIM -/* Call reclaim notifier for block's kind on each unmarked object in */ -/* block, all within a pair of corresponding enter/leave callbacks. */ -STATIC ptr_t GC_disclaim_and_reclaim(struct hblk *hbp, hdr *hhdr, size_t sz, - ptr_t list, signed_word *count) -{ - register int bit_no = 0; + /* Call reclaim notifier for block's kind on each unmarked object in */ + /* block, all within a pair of corresponding enter/leave callbacks. */ + STATIC ptr_t GC_disclaim_and_reclaim(struct hblk *hbp, hdr *hhdr, size_t sz, + ptr_t list, signed_word *count) + { + register int bit_no = 0; // FIXME: remove register register word *p, *q, *plim; signed_word n_bytes_found = 0; struct obj_kind *ok = &GC_obj_kinds[hhdr->hb_obj_kind]; @@ -263,7 +264,7 @@ STATIC ptr_t GC_disclaim_and_reclaim(struct hblk *hbp, hdr *hhdr, size_t sz, } *count += n_bytes_found; return list; -} + } #endif /* ENABLE_DISCLAIM */ /* Don't really reclaim objects, just check for unmarked ones: */ @@ -299,11 +300,11 @@ GC_INNER ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz, GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */); # endif # ifdef ENABLE_DISCLAIM - if (hhdr -> hb_flags & HAS_DISCLAIM) - result = GC_disclaim_and_reclaim(hbp, hhdr, sz, list, count); - else + if (hhdr -> hb_flags & HAS_DISCLAIM) { + result = GC_disclaim_and_reclaim(hbp, hhdr, sz, list, count); + } else # endif - if (init || GC_debugging_started) { + /* else */ if (init || GC_debugging_started) { result = GC_reclaim_clear(hbp, hhdr, sz, list, count); } else { GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */); @@ -338,8 +339,8 @@ STATIC void GC_reclaim_small_nonempty_block(struct hblk *hbp, } #ifdef ENABLE_DISCLAIM -STATIC void GC_disclaim_and_reclaim_or_free_small_block(struct hblk *hbp) -{ + STATIC void GC_disclaim_and_reclaim_or_free_small_block(struct hblk *hbp) + { hdr *hhdr = HDR(hbp); size_t sz = hhdr -> hb_sz; struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; @@ -355,8 +356,8 @@ STATIC void GC_disclaim_and_reclaim_or_free_small_block(struct hblk *hbp) GC_bytes_found += HBLKSIZE; GC_freehblk(hbp); } -} -#endif + } +#endif /* ENABLE_DISCLAIM */ /* * Restore an unmarked large object or an entirely empty blocks of small objects @@ -385,7 +386,7 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) if ((*ok->ok_disclaim_proc)(hbp, ok->ok_disclaim_cd)) { /* Not disclaimed => resurrect the object. */ set_mark_bit_from_hdr(hhdr, 0); - /* excuse me, */ goto in_use; + goto in_use; } } # endif @@ -397,7 +398,7 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) } } else { # ifdef ENABLE_DISCLAIM - in_use: + in_use: # endif if (hhdr -> hb_descr != 0) { GC_composite_in_use += sz; @@ -422,11 +423,11 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) GC_reclaim_small_nonempty_block(hbp, TRUE /* report_if_found */); } else if (empty) { # ifdef ENABLE_DISCLAIM - if ((hhdr -> hb_flags & HAS_DISCLAIM)) + if ((hhdr -> hb_flags & HAS_DISCLAIM) != 0) { GC_disclaim_and_reclaim_or_free_small_block(hbp); - else + } else # endif - { + /* else */ { GC_bytes_found += HBLKSIZE; GC_freehblk(hbp); } diff --git a/tests/disclaim_bench.c b/tests/disclaim_bench.c index df67bf4f..ea7ca094 100644 --- a/tests/disclaim_bench.c +++ b/tests/disclaim_bench.c @@ -1,10 +1,27 @@ -#include "gc_disclaim.h" -#include "atomic_ops.h" +/* + * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved. + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + #include #include #include #include -#include + +#include // FIXME: It would be good not to use timing API by + // default (is it is not quite portable). + +#include "atomic_ops.h" +#include "gc_disclaim.h" static AO_t free_count = 0; @@ -16,11 +33,10 @@ struct testobj_s { void testobj_finalize(void *obj, void *carg) { -#define obj ((testobj_t)obj) AO_fetch_and_add1((AO_t *)carg); - assert(obj->i++ == 109); -#undef obj + assert(((testobj_t)obj)->i++ == 109); } + static struct GC_finalizer_closure fclos = { testobj_finalize, &free_count @@ -30,28 +46,33 @@ testobj_t testobj_new(int model) { testobj_t obj; switch (model) { - case 0: - obj = GC_malloc(sizeof(struct testobj_s)); - GC_register_finalizer_no_order(obj, testobj_finalize, &free_count, - NULL, NULL); - break; - case 1: - obj = GC_finalized_malloc(sizeof(struct testobj_s), &fclos); - break; - case 2: - obj = GC_malloc(sizeof(struct testobj_s)); - break; - default: - abort(); + case 0: + obj = GC_MALLOC(sizeof(struct testobj_s)); + GC_register_finalizer_no_order(obj, testobj_finalize, &free_count, + NULL, NULL); + break; + case 1: + obj = GC_finalized_malloc(sizeof(struct testobj_s), &fclos); + break; + case 2: + obj = GC_MALLOC(sizeof(struct testobj_s)); + break; + default: + exit(-1); } assert(obj->i == 0 && obj->keep_link == NULL); obj->i = 109; return obj; } - #define ALLOC_CNT (4*1024*1024) -#define KEEP_CNT ( 32*1024) +#define KEEP_CNT (32*1024) + +static char const *model_str[3] = { + "regular finalization", + "finalize on reclaim", + "no finalization" +}; int main(int argc, char **argv) { @@ -59,57 +80,55 @@ int main(int argc, char **argv) int model; testobj_t *keep_arr; double t; - static char const *model_str[3] = { - "regular finalization", - "finalize on reclaim", - "no finalization" - }; - GC_init(); + GC_INIT(); GC_init_finalized_malloc(); - /* Seed with time for distict usage patters over repeated runs. */ - srand48(time(NULL)); + /* Seed with time for distict usage patterns over repeated runs. */ + srand48(time(NULL)); // FIXME: not available on some targets - keep_arr = GC_malloc(sizeof(void *)*KEEP_CNT); + keep_arr = GC_MALLOC(sizeof(void *)*KEEP_CNT); if (argc == 1) { - char *buf = GC_malloc(strlen(argv[0]) + 3); - printf("\t\t\tfin. ratio time/s time/fin.\n"); - for (i = 0; i < 3; ++i) { - int st; - sprintf(buf, "%s %d", argv[0], i); - st = system(buf); - if (st != 0) - return st; - } - return 0; + char *buf = GC_MALLOC(strlen(argv[0]) + 3); + printf("\t\t\tfin. ratio time/s time/fin.\n"); + for (i = 0; i < 3; ++i) { + int st; + sprintf(buf, "%s %d", argv[0], i); // FIXME: Use snprintf + //FIXME: snprintf not available on WinCE + st = system(buf); // FIXME: is this available on all targets? + if (st != 0) + return st; + } + return 0; } if (argc == 2 && strcmp(argv[1], "--help") == 0) { - fprintf(stderr, - "Usage: %s FINALIZATION_MODEL\n" - "\t0 -- original finalization\n" - "\t1 -- finalization on reclaim\n" - "\t2 -- no finalization\n", argv[0]); - return 1; + fprintf(stderr, + "Usage: %s FINALIZATION_MODEL\n" + "\t0 -- original finalization\n" + "\t1 -- finalization on reclaim\n" + "\t2 -- no finalization\n", argv[0]); + return 1; } model = atoi(argv[1]); if (model < 0 || model > 2) - exit(2); - t = -clock(); + exit(2); + t = -clock(); // FIXME: not available on some targets? + // FIXME: don't use '-' on probably unsigned type for (i = 0; i < ALLOC_CNT; ++i) { - int k = lrand48() % KEEP_CNT; - keep_arr[k] = testobj_new(model); + int k = lrand48() % KEEP_CNT; // FIXME: not available on some targets + keep_arr[k] = testobj_new(model); } + GC_gcollect(); - t += clock(); - t /= CLOCKS_PER_SEC; + + t += clock(); // FIXME: not available on some targets? + t /= CLOCKS_PER_SEC; // FIXME: not available on some targets if (model < 2) - printf("%20s: %12.4lf %12lg %12lg\n", model_str[model], - free_count/(double)ALLOC_CNT, t, t/free_count); + printf("%20s: %12.4lf %12lg %12lg\n", model_str[model], + free_count/(double)ALLOC_CNT, t, t/free_count); else - printf("%20s: 0 %12lg N/A\n", - model_str[model], t); - + printf("%20s: 0 %12lg N/A\n", // FIXME: Use \t + model_str[model], t); return 0; } diff --git a/tests/disclaim_test.c b/tests/disclaim_test.c index 6e005ad7..00fad7c6 100644 --- a/tests/disclaim_test.c +++ b/tests/disclaim_test.c @@ -1,12 +1,27 @@ -/* Test that objects reachable from an object allocated with - * GC_malloc_with_finalizer is not reclaimable before the finalizer - * is called. */ +/* + * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved. + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* Test that objects reachable from an object allocated with */ +/* GC_malloc_with_finalizer is not reclaimable before the finalizer */ +/* is called. */ #include #include #include #include -#include + +#include "gc_disclaim.h" typedef struct pair_s *pair_t; @@ -24,7 +39,9 @@ pair_dct(void *obj, void *cd) int checksum; /* Check that obj and its car and cdr are not trashed. */ - //printf("Destruct %p = (%p, %p)\n", p, p->car, p->cdr); +# ifdef DEBUG_DISCLAIM_DESTRUCT + printf("Destruct %p = (%p, %p)\n", p, p->car, p->cdr); +# endif assert(GC_base(obj)); assert(p->is_valid); assert(!p->car || p->car->is_valid); @@ -46,12 +63,15 @@ pair_new(pair_t car, pair_t cdr) { pair_t p; static struct GC_finalizer_closure fc = { pair_dct, NULL }; + p = GC_finalized_malloc(sizeof(struct pair_s), &fc); p->is_valid = 1; p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0); p->car = car; p->cdr = cdr; - //printf("Construct %p = (%p, %p)\n", p, p->car, p->cdr); +# ifdef DEBUG_DISCLAIM_DESTRUCT + printf("Construct %p = (%p, %p)\n", p, p->car, p->cdr); +# endif return p; } @@ -59,14 +79,14 @@ void pair_check_rec(pair_t p) { while (p) { - int checksum = 782; - if (p->car) checksum += p->car->checksum; - if (p->cdr) checksum += p->cdr->checksum; - assert(p->checksum == checksum); - if (rand() % 2) - p = p->car; - else - p = p->cdr; + int checksum = 782; + if (p->car) checksum += p->car->checksum; + if (p->cdr) checksum += p->cdr->checksum; + assert(p->checksum == checksum); + if (rand() % 2) + p = p->car; + else + p = p->cdr; } } @@ -90,52 +110,57 @@ void *test(void *data) pair_t pop[POP_SIZE]; memset(pop, 0, sizeof(pop)); for (i = 0; i < MUTATE_CNT; ++i) { - int t = rand() % POP_SIZE; - switch (rand() % (i > GROW_LIMIT? 5 : 3)) { - case 0: case 3: - if (pop[t]) - pop[t] = pop[t]->car; - break; - case 1: case 4: - if (pop[t]) - pop[t] = pop[t]->cdr; - break; - case 2: - pop[t] = pair_new(pop[rand() % POP_SIZE], - pop[rand() % POP_SIZE]); - break; - } - if (rand() % 8 == 1) - pair_check_rec(pop[rand() % POP_SIZE]); + int t = rand() % POP_SIZE; + switch (rand() % (i > GROW_LIMIT? 5 : 3)) { + case 0: case 3: + if (pop[t]) + pop[t] = pop[t]->car; + break; + case 1: case 4: + if (pop[t]) + pop[t] = pop[t]->cdr; + break; + case 2: + pop[t] = pair_new(pop[rand() % POP_SIZE], + pop[rand() % POP_SIZE]); + break; + } + if (rand() % 8 == 1) + pair_check_rec(pop[rand() % POP_SIZE]); } return 0; } -int main() +int main(void) { #if THREAD_CNT > 1 pthread_t th[THREAD_CNT]; int i; #endif - GC_init(); + GC_INIT(); GC_init_finalized_malloc(); + #if THREAD_CNT > 1 printf("Threaded disclaim test.\n"); for (i = 0; i < THREAD_CNT; ++i) { - int err = pthread_create(&th[i], NULL, test, NULL); - if (err) { - fprintf(stderr, "Failed to create thread # %d: %s\n", i, - strerror(err)); - exit(1); - } + // FIXME: this is not available on Win32 without pthreads + // FIXME: Should GC_ suffix be used? + int err = pthread_create(&th[i], NULL, test, NULL); + if (err) { + fprintf(stderr, "Failed to create thread # %d: %s\n", i, + strerror(err)); + exit(1); + } + } + for (i = 0; i < THREAD_CNT; ++i) { + // FIXME: Should GC_ suffix be used? + // FIXME: Check error code. + pthread_join(th[i], NULL); } - for (i = 0; i < THREAD_CNT; ++i) - pthread_join(th[i], NULL); #else printf("Unthreaded disclaim test.\n"); test(NULL); #endif return 0; } - diff --git a/tests/tests.am b/tests/tests.am index f7985c9a..9685ae67 100644 --- a/tests/tests.am +++ b/tests/tests.am @@ -97,7 +97,6 @@ TESTS += disclaim_test check_PROGRAMS += disclaim_test disclaim_test_SOURCES = tests/disclaim_test.c disclaim_test_LDADD = $(test_ldadd) - TESTS += disclaim_bench check_PROGRAMS += disclaim_bench disclaim_bench_SOURCES = tests/disclaim_bench.c diff --git a/thread_local_alloc.c b/thread_local_alloc.c index ac351734..57b34443 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -99,7 +99,7 @@ GC_INNER void GC_init_thread_local(GC_tlfs p) p -> gcj_freelists[i] = (void *)(word)1; # endif # ifdef ENABLE_DISCLAIM - p -> finalized_freelists[i] = (void *)1; + p -> finalized_freelists[i] = (void *)(word)1; # endif } /* Set up the size 0 free lists. */ @@ -112,7 +112,7 @@ GC_INNER void GC_init_thread_local(GC_tlfs p) p -> gcj_freelists[0] = ERROR_FL; # endif # ifdef ENABLE_DISCLAIM - p -> finalized_freelists[0] = (void *)1; + p -> finalized_freelists[0] = (void *)(word)1; # endif } @@ -288,7 +288,8 @@ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p) # endif /* GC_GCJ_SUPPORT */ # ifdef ENABLE_DISCLAIM q = p -> finalized_freelists[j]; - if ((word)q > HBLKSIZE) GC_set_fl_marks(q); + if ((word)q > HBLKSIZE) + GC_set_fl_marks(q); # endif } } @@ -311,7 +312,8 @@ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p) # endif /* GC_GCJ_SUPPORT */ # ifdef ENABLE_DISCLAIM q = p -> finalized_freelists[j]; - if ((word)q > HBLKSIZE) GC_check_fl_marks(q); + if ((word)q > HBLKSIZE) + GC_check_fl_marks(q); # endif } }