summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/mgc0.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-02-08 21:41:54 -0800
committerRuss Cox <rsc@golang.org>2010-02-08 21:41:54 -0800
commit4227e0fcd8ab454433d9c3d94da6eae68dfc1689 (patch)
tree97dc24869f546fd7032625f3b2159ab8afbd1000 /src/pkg/runtime/mgc0.c
parent572ffc76eca67ff28370cb29fc76ebcbe2aeb8cd (diff)
downloadgolang-4227e0fcd8ab454433d9c3d94da6eae68dfc1689.tar.gz
runtime: allow arbitrary return type in SetFinalizer.
finalize chan, to free OS X semaphore inside Lock. os: finalize File, to close fd. Fixes issue 503. R=ken2 CC=golang-dev http://codereview.appspot.com/204065
Diffstat (limited to 'src/pkg/runtime/mgc0.c')
-rw-r--r--src/pkg/runtime/mgc0.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 83d217320..bd5d2e25a 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -23,9 +23,17 @@ extern byte data[];
extern byte etext[];
extern byte end[];
-static void *finq[128]; // finalizer queue - two elements per entry
-static void **pfinq = finq;
-static void **efinq = finq+nelem(finq);
+typedef struct Finq Finq;
+struct Finq
+{
+ void (*fn)(void*);
+ void *p;
+ int32 nret;
+};
+
+static Finq finq[128]; // finalizer queue - two elements per entry
+static Finq *pfinq = finq;
+static Finq *efinq = finq+nelem(finq);
static void sweepblock(byte*, int64, uint32*, int32);
@@ -172,7 +180,7 @@ sweepblock(byte *p, int64 n, uint32 *gcrefp, int32 pass)
break;
case RefNone:
case RefNone|RefNoPointers:
- if(pass == 0 && getfinalizer(p, 0)) {
+ if(pass == 0 && getfinalizer(p, 0, nil)) {
// Tentatively mark as finalizable.
// Make sure anything it points at will not be collected.
if(Debug > 0)
@@ -192,8 +200,12 @@ sweepblock(byte *p, int64 n, uint32 *gcrefp, int32 pass)
if(pfinq < efinq) {
if(Debug > 0)
printf("finalize %p+%D\n", p, n);
- *pfinq++ = getfinalizer(p, 1);
- *pfinq++ = p;
+ pfinq->p = p;
+ pfinq->nret = 0;
+ pfinq->fn = getfinalizer(p, 1, &pfinq->nret);
+ if(pfinq->fn == nil)
+ throw("getfinalizer inconsistency");
+ pfinq++;
}
// Reset for next mark+sweep.
*gcrefp = RefNone | (gcref&RefNoPointers);
@@ -242,7 +254,7 @@ gc(int32 force)
{
int64 t0, t1;
byte *p;
- void **fp;
+ Finq *fp;
// The gc is turned off (via enablegc) until
// the bootstrap has completed.
@@ -283,10 +295,10 @@ gc(int32 force)
// kick off goroutines to run queued finalizers
m->locks++; // disable gc during the mallocs in newproc
- for(fp=finq; fp<pfinq; fp+=2) {
- ·newproc(sizeof(void*), fp[0], fp[1]);
- fp[0] = nil;
- fp[1] = nil;
+ for(fp=finq; fp<pfinq; fp++) {
+ newproc1((byte*)fp->fn, (byte*)&fp->p, sizeof(fp->p), fp->nret);
+ fp->fn = nil;
+ fp->p = nil;
}
pfinq = finq;
m->locks--;