summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/mfinal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/mfinal.c')
-rw-r--r--src/pkg/runtime/mfinal.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c
index 817d98737..ae737e8da 100644
--- a/src/pkg/runtime/mfinal.c
+++ b/src/pkg/runtime/mfinal.c
@@ -18,17 +18,14 @@ typedef struct Fintab Fintab;
struct Fintab
{
void **key;
- struct {
- void *fn;
- int32 nret;
- } *val;
+ 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, void *fn, int32 nret)
+addfintab(Fintab *t, void *k, Finalizer *v)
{
int32 i, j;
@@ -51,15 +48,14 @@ addfintab(Fintab *t, void *k, void *fn, int32 nret)
ret:
t->key[i] = k;
- t->val[i].fn = fn;
- t->val[i].nret = nret;
+ t->val[i] = v;
}
-static void*
-lookfintab(Fintab *t, void *k, bool del, int32 *nret)
+static Finalizer*
+lookfintab(Fintab *t, void *k, bool del)
{
int32 i, j;
- void *v;
+ Finalizer *v;
if(t->max == 0)
return nil;
@@ -68,13 +64,10 @@ lookfintab(Fintab *t, void *k, bool del, int32 *nret)
if(t->key[i] == nil)
return nil;
if(t->key[i] == k) {
- v = t->val[i].fn;
- if(nret)
- *nret = t->val[i].nret;
+ v = t->val[i];
if(del) {
t->key[i] = (void*)-1;
- t->val[i].fn = nil;
- t->val[i].nret = 0;
+ t->val[i] = nil;
t->ndead++;
}
return v;
@@ -98,6 +91,14 @@ addfinalizer(void *p, void (*f)(void*), int32 nret)
int32 i;
uint32 *ref;
byte *base;
+ Finalizer *e;
+
+ e = nil;
+ if(f != nil) {
+ e = mal(sizeof *e);
+ e->fn = f;
+ e->nret = nret;
+ }
lock(&finlock);
if(!mlookup(p, &base, nil, nil, &ref) || p != base) {
@@ -106,7 +107,7 @@ addfinalizer(void *p, void (*f)(void*), int32 nret)
}
if(f == nil) {
if(*ref & RefHasFinalizer) {
- lookfintab(&fintab, p, 1, nil);
+ lookfintab(&fintab, p, 1);
*ref &= ~RefHasFinalizer;
}
unlock(&finlock);
@@ -141,26 +142,41 @@ addfinalizer(void *p, void (*f)(void*), int32 nret)
k = fintab.key[i];
if(k != nil && k != (void*)-1)
- addfintab(&newtab, k, fintab.val[i].fn, fintab.val[i].nret);
+ addfintab(&newtab, k, fintab.val[i]);
}
free(fintab.key);
free(fintab.val);
fintab = newtab;
}
- addfintab(&fintab, p, f, nret);
+ addfintab(&fintab, p, e);
unlock(&finlock);
}
// get finalizer; if del, delete finalizer.
// caller is responsible for updating RefHasFinalizer bit.
-void*
-getfinalizer(void *p, bool del, int32 *nret)
+Finalizer*
+getfinalizer(void *p, bool del)
{
- void *f;
+ Finalizer *f;
lock(&finlock);
- f = lookfintab(&fintab, p, del, nret);
+ f = lookfintab(&fintab, p, del);
unlock(&finlock);
return f;
}
+
+void
+walkfintab(void (*fn)(void*))
+{
+ void **key;
+ void **ekey;
+
+ lock(&finlock);
+ key = fintab.key;
+ ekey = key + fintab.max;
+ for(; key < ekey; key++)
+ if(*key != nil && *key != ((void*)-1))
+ fn(*key);
+ unlock(&finlock);
+}