diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
commit | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/pkg/runtime/mfinal.c | |
parent | 28592ee1ea1f5cdffcf85472f9de0285d928cf12 (diff) | |
download | golang-80f18fc933cf3f3e829c5455a1023d69f7b86e52.tar.gz |
Imported Upstream version 60
Diffstat (limited to 'src/pkg/runtime/mfinal.c')
-rw-r--r-- | src/pkg/runtime/mfinal.c | 181 |
1 files changed, 0 insertions, 181 deletions
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c deleted file mode 100644 index f3138145b..000000000 --- a/src/pkg/runtime/mfinal.c +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "malloc.h" - -// Lock to protect finalizer data structures. -// Cannot reuse mheap.Lock because the finalizer -// maintenance requires allocation. -static Lock finlock; - -// Finalizer hash table. Direct hash, linear scan, at most 3/4 full. -// Table size is power of 3 so that hash can be key % max. -// Key[i] == (void*)-1 denotes free but formerly occupied entry -// (doesn't stop the linear scan). -// Key and val are separate tables because the garbage collector -// must be instructed to ignore the pointers in key but follow the -// pointers in val. -typedef struct Fintab Fintab; -struct Fintab -{ - void **key; - Finalizer **val; - int32 nkey; // number of non-nil entries in key - int32 ndead; // number of dead (-1) entries in key - int32 max; // size of key, val allocations -}; - -static void -addfintab(Fintab *t, void *k, Finalizer *v) -{ - int32 i, j; - - i = (uintptr)k % (uintptr)t->max; - for(j=0; j<t->max; j++) { - if(t->key[i] == nil) { - t->nkey++; - goto ret; - } - if(t->key[i] == (void*)-1) { - t->ndead--; - goto ret; - } - if(++i == t->max) - i = 0; - } - - // cannot happen - table is known to be non-full - runtime·throw("finalizer table inconsistent"); - -ret: - t->key[i] = k; - t->val[i] = v; -} - -static Finalizer* -lookfintab(Fintab *t, void *k, bool del) -{ - int32 i, j; - Finalizer *v; - - if(t->max == 0) - return nil; - i = (uintptr)k % (uintptr)t->max; - for(j=0; j<t->max; j++) { - if(t->key[i] == nil) - return nil; - if(t->key[i] == k) { - v = t->val[i]; - if(del) { - t->key[i] = (void*)-1; - t->val[i] = nil; - t->ndead++; - } - return v; - } - if(++i == t->max) - i = 0; - } - - // cannot happen - table is known to be non-full - runtime·throw("finalizer table inconsistent"); - return nil; -} - -static Fintab fintab; - -// add finalizer; caller is responsible for making sure not already in table -void -runtime·addfinalizer(void *p, void (*f)(void*), int32 nret) -{ - Fintab newtab; - int32 i; - byte *base; - Finalizer *e; - - e = nil; - if(f != nil) { - e = runtime·mal(sizeof *e); - e->fn = f; - e->nret = nret; - } - - runtime·lock(&finlock); - if(!runtime·mlookup(p, &base, nil, nil) || p != base) { - runtime·unlock(&finlock); - runtime·throw("addfinalizer on invalid pointer"); - } - if(f == nil) { - lookfintab(&fintab, p, 1); - runtime·unlock(&finlock); - return; - } - - if(lookfintab(&fintab, p, 0)) { - runtime·unlock(&finlock); - runtime·throw("double finalizer"); - } - runtime·setblockspecial(p); - - if(fintab.nkey >= fintab.max/2+fintab.max/4) { - // keep table at most 3/4 full: - // allocate new table and rehash. - - runtime·memclr((byte*)&newtab, sizeof newtab); - newtab.max = fintab.max; - if(newtab.max == 0) - newtab.max = 3*3*3; - else if(fintab.ndead < fintab.nkey/2) { - // grow table if not many dead values. - // otherwise just rehash into table of same size. - newtab.max *= 3; - } - - newtab.key = runtime·mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1); - newtab.val = runtime·mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1); - - for(i=0; i<fintab.max; i++) { - void *k; - - k = fintab.key[i]; - if(k != nil && k != (void*)-1) - addfintab(&newtab, k, fintab.val[i]); - } - runtime·free(fintab.key); - runtime·free(fintab.val); - fintab = newtab; - } - - addfintab(&fintab, p, e); - runtime·unlock(&finlock); -} - -// get finalizer; if del, delete finalizer. -// caller is responsible for updating RefHasFinalizer bit. -Finalizer* -runtime·getfinalizer(void *p, bool del) -{ - Finalizer *f; - - runtime·lock(&finlock); - f = lookfintab(&fintab, p, del); - runtime·unlock(&finlock); - return f; -} - -void -runtime·walkfintab(void (*fn)(void*)) -{ - void **key; - void **ekey; - - runtime·lock(&finlock); - key = fintab.key; - ekey = key + fintab.max; - for(; key < ekey; key++) - if(*key != nil && *key != ((void*)-1)) - fn(*key); - runtime·unlock(&finlock); -} |