From 2a17f76cec4071001563b89333359b6b623e247c Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 9 Apr 2008 17:25:30 +0000 Subject: [PATCH] streamline GC's thread and custodian tracking svn: r9224 --- collects/scribblings/guide/truth.scrbl | 4 +- doc/release-notes/mzscheme/MzScheme_4.txt | 8 ++- src/mzscheme/gc2/gc2.h | 4 ++ src/mzscheme/gc2/newgc.c | 85 +++++++++++------------ src/mzscheme/include/scheme.h | 2 +- src/mzscheme/src/thread.c | 3 + 6 files changed, 57 insertions(+), 49 deletions(-) diff --git a/collects/scribblings/guide/truth.scrbl b/collects/scribblings/guide/truth.scrbl index f0de187dc9..99ce1573fc 100644 --- a/collects/scribblings/guide/truth.scrbl +++ b/collects/scribblings/guide/truth.scrbl @@ -53,8 +53,8 @@ mistake, such as accidentally reversing the arguments to @interaction[(cons (list 2 3) 1) (cons 1 (list 2 3))] Non-list pairs are used intentionally, sometimes. For example, the -@scheme[make-immutable-hash-table] function takes a list of pairs, -where the @scheme[car] of each pair is a key and the @scheme[cdr] is an +@scheme[make-immutable-hash] function takes a list of pairs, where the +@scheme[car] of each pair is a key and the @scheme[cdr] is an arbitrary value. The only thing more confusing to new Schemers than non-list pairs is diff --git a/doc/release-notes/mzscheme/MzScheme_4.txt b/doc/release-notes/mzscheme/MzScheme_4.txt index 7929cdb688..cb464817ad 100644 --- a/doc/release-notes/mzscheme/MzScheme_4.txt +++ b/doc/release-notes/mzscheme/MzScheme_4.txt @@ -502,8 +502,8 @@ with some syntactic and name changes. * Hash-table function names have changed: - make-hash-table => make-hash make-weak-hash - make-hasheq make-weak-hasheq + make-hash-table => make-hasheq make-weak-hasheq + make-hash make-weak-hash hash-table? => hash? hash-eq? hash-weak? hash-table-get => hash-ref hash-table-put! => hash-set! @@ -512,6 +512,10 @@ with some syntactic and name changes. hash-table-map => hash-map .... .... + IMPORTANT: The correct translation of `(make-hash-table)' is + `(make-hasheq)', not `(make-hash)'. Instead, `(make-hash)' + is equivalent to `(make-hash-table 'equal)'. + The new functions `hash-set' and `hash-remove' support constant-time functional update of immutable hash tables. diff --git a/src/mzscheme/gc2/gc2.h b/src/mzscheme/gc2/gc2.h index 4c56c5f82f..7d34d403cc 100644 --- a/src/mzscheme/gc2/gc2.h +++ b/src/mzscheme/gc2/gc2.h @@ -74,6 +74,10 @@ GC2_EXTERN void GC_init_type_tags(int count, int pair, int mutable_pair, int wea freedom in the layout of a weak box or ephemeron, so it performs weak box traversals itself, but MzScheme gets to choose the tag.) */ +GC2_EXTERN void GC_register_root_custodian(void *); +/* + Registers the root custodian. */ + GC2_EXTERN void GC_register_new_thread(void *, void *); /* Indicates that a just-allocated point is for a thread record diff --git a/src/mzscheme/gc2/newgc.c b/src/mzscheme/gc2/newgc.c index f9d0600c59..ec05d3e102 100644 --- a/src/mzscheme/gc2/newgc.c +++ b/src/mzscheme/gc2/newgc.c @@ -1290,24 +1290,24 @@ typedef short Type_Tag; #ifdef NEWGC_BTC_ACCOUNT inline static int current_owner(Scheme_Custodian *c); -struct thread { +struct gc_thread_info { void *thread; int owner; - struct thread *next; + struct gc_thread_info *next; }; static Mark_Proc normal_thread_mark = NULL, normal_custodian_mark = NULL, normal_cust_box_mark = NULL; -static struct thread *threads = NULL; +static struct gc_thread_info *threads = NULL; static unsigned short cust_box_tag; inline static void register_new_thread(void *t, void *c) { - struct thread *work; + struct gc_thread_info *work; - work = (struct thread *)malloc(sizeof(struct thread)); + work = (struct gc_thread_info *)malloc(sizeof(struct gc_thread_info)); work->owner = current_owner((Scheme_Custodian *)c); - ((Scheme_Thread *)t)->gc_owner_set = work->owner; + ((Scheme_Thread *)t)->gc_info = work; work->thread = t; work->next = threads; threads = work; @@ -1315,20 +1315,15 @@ inline static void register_new_thread(void *t, void *c) inline static void register_thread(void *t, void *c) { - struct thread *work; + struct gc_thread_info *work; - for(work = threads; work; work = work->next) - if(work->thread == t) { - work->owner = current_owner((Scheme_Custodian *)c); - ((Scheme_Thread *)t)->gc_owner_set = work->owner; - return; - } - register_new_thread(t, c); + work = ((Scheme_Thread *)t)->gc_info; + work->owner = current_owner((Scheme_Custodian *)c); } inline static void mark_threads(int owner) { - struct thread *work; + struct gc_thread_info *work; for(work = threads; work; work = work->next) if(work->owner == owner) { @@ -1368,7 +1363,7 @@ inline static void mark_cust_boxes(Scheme_Custodian *cur) inline static void clean_up_thread_list(void) { - struct thread *work = threads, *prev = NULL; + struct gc_thread_info *work = threads, *prev = NULL; while(work) { if(!find_page(work->thread) || marked(work->thread)) { @@ -1376,7 +1371,7 @@ inline static void clean_up_thread_list(void) prev = work; work = work->next; } else { - struct thread *next = work->next; + struct gc_thread_info *next = work->next; if(prev) prev->next = next; if(!prev) threads = next; @@ -1388,7 +1383,7 @@ inline static void clean_up_thread_list(void) inline static int thread_get_owner(void *p) { - return ((Scheme_Thread *)p)->gc_owner_set; + return ((Scheme_Thread *)p)->gc_info->owner; } #endif @@ -1535,13 +1530,15 @@ inline static int create_blank_owner_set(void) { int i; unsigned int old_top; + struct ot_entry **naya; - for(i = 1; i < owner_table_top; i++) - if(!owner_table[i]) { + for (i = 1; i < owner_table_top; i++) { + if (!owner_table[i]) { owner_table[i] = malloc(sizeof(struct ot_entry)); bzero(owner_table[i], sizeof(struct ot_entry)); return i; } + } old_top = owner_table_top; if (!owner_table_top) @@ -1549,7 +1546,9 @@ inline static int create_blank_owner_set(void) else owner_table_top *= 2; - owner_table = realloc(owner_table, owner_table_top*sizeof(struct ot_entry*)); + naya = (struct ot_entry **)malloc(owner_table_top*sizeof(struct ot_entry*)); + memcpy(naya, owner_table, old_top*sizeof(struct ot_entry*)); + owner_table = naya; bzero((char*)owner_table + (sizeof(struct ot_entry*) * old_top), (owner_table_top - old_top) * sizeof(struct ot_entry*)); @@ -1563,10 +1562,6 @@ inline static int custodian_to_owner_set(Scheme_Custodian *cust) if (cust->gc_owner_set) return cust->gc_owner_set; - for(i = 1; i < owner_table_top; i++) - if(owner_table[i] && (owner_table[i]->originator == cust)) - return i; - i = create_blank_owner_set(); owner_table[i]->originator = cust; cust->gc_owner_set = i; @@ -1576,25 +1571,7 @@ inline static int custodian_to_owner_set(Scheme_Custodian *cust) inline static int current_owner(Scheme_Custodian *c) { - static int has_gotten_root_custodian = 0; - - if(!owner_table) { - owner_table = malloc(10 * sizeof(struct ot_entry*)); - bzero(owner_table, 10 * sizeof(struct ot_entry*)); - if(create_blank_owner_set() != 1) { - GCPRINT(GCOUTF, "Something extremely weird (and bad) has happened.\n"); - abort(); - } - } - - if(!has_gotten_root_custodian && c) { - has_gotten_root_custodian = 1; - owner_table[1]->originator = c; - c->gc_owner_set = 1; - return 1; - } - - if(!scheme_current_thread) + if (!scheme_current_thread) return 1; else if (!c) return thread_get_owner(scheme_current_thread); @@ -1602,6 +1579,26 @@ inline static int current_owner(Scheme_Custodian *c) return custodian_to_owner_set(c); } +void GC_register_root_custodian(void *_c) +{ + Scheme_Custodian *c = (Scheme_Custodian *)_c; + + if (owner_table) { + /* Reset */ + free(owner_table); + owner_table = NULL; + owner_table_top = 0; + } + + if (create_blank_owner_set() != 1) { + GCPRINT(GCOUTF, "Something extremely weird (and bad) has happened.\n"); + abort(); + } + + owner_table[1]->originator = c; + c->gc_owner_set = 1; +} + inline static int custodian_member_owner_set(void *cust, int set) { Scheme_Custodian_Reference *box; diff --git a/src/mzscheme/include/scheme.h b/src/mzscheme/include/scheme.h index f6688096da..fd0ebd8327 100644 --- a/src/mzscheme/include/scheme.h +++ b/src/mzscheme/include/scheme.h @@ -1073,7 +1073,7 @@ typedef struct Scheme_Thread { Scheme_Object *mbox_sema; #ifdef MZ_PRECISE_GC - int gc_owner_set; + struct gc_thread_info *gc_info; /* managed by the GC */ #endif } Scheme_Thread; diff --git a/src/mzscheme/src/thread.c b/src/mzscheme/src/thread.c index 6fb732a686..292e883b3c 100644 --- a/src/mzscheme/src/thread.c +++ b/src/mzscheme/src/thread.c @@ -6332,6 +6332,9 @@ static void make_initial_config(Scheme_Thread *p) REGISTER_SO(last_custodian); REGISTER_SO(limited_custodians); main_custodian = scheme_make_custodian(NULL); +#ifdef MZ_PRECISE_GC + GC_register_root_custodian(main_custodian); +#endif last_custodian = main_custodian; init_param(cells, paramz, MZCONFIG_CUSTODIAN, (Scheme_Object *)main_custodian);