aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/malloc.c
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-08-28 13:23:10 -0700
committerKeith Randall <khr@golang.org>2014-08-28 13:23:10 -0700
commitc46bcd4d13492d3588638ea3ea4c752166709044 (patch)
tree0ba3a23a9483c1c666cea054c45276a7538fb382 /src/pkg/runtime/malloc.c
parente66ff2b9080669373704914191abf2ee5f65eb75 (diff)
downloadgo-c46bcd4d13492d3588638ea3ea4c752166709044.tar.xz
runtime: move finalizer thread to Go.
LGTM=dvyukov R=golang-codereviews, dvyukov, khr CC=golang-codereviews https://golang.org/cl/124630043
Diffstat (limited to 'src/pkg/runtime/malloc.c')
-rw-r--r--src/pkg/runtime/malloc.c107
1 files changed, 18 insertions, 89 deletions
diff --git a/src/pkg/runtime/malloc.c b/src/pkg/runtime/malloc.c
index 8eeebe4692..143d9e5e9e 100644
--- a/src/pkg/runtime/malloc.c
+++ b/src/pkg/runtime/malloc.c
@@ -423,107 +423,36 @@ runtime·cnewarray(Type *typ, intgo n)
return cnew(typ, n);
}
-static void
-setFinalizer(Eface obj, Eface finalizer)
+void
+runtime·setFinalizer_m(void)
{
- byte *base;
- uintptr size;
- FuncType *ft;
- int32 i;
+ FuncVal *fn;
+ void *arg;
uintptr nret;
- Type *t;
Type *fint;
PtrType *ot;
- Iface iface;
-
- if(obj.type == nil) {
- runtime·printf("runtime.SetFinalizer: first argument is nil interface\n");
- goto throw;
- }
- if((obj.type->kind&KindMask) != KindPtr) {
- runtime·printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
- goto throw;
- }
- ot = (PtrType*)obj.type;
- // As an implementation detail we do not run finalizers for zero-sized objects,
- // because we use &runtime·zerobase for all such allocations.
- if(ot->elem != nil && ot->elem->size == 0)
- return;
- // The following check is required for cases when a user passes a pointer to composite literal,
- // but compiler makes it a pointer to global. For example:
- // var Foo = &Object{}
- // func main() {
- // runtime.SetFinalizer(Foo, nil)
- // }
- // See issue 7656.
- if((byte*)obj.data < runtime·mheap.arena_start || runtime·mheap.arena_used <= (byte*)obj.data)
- return;
- if(!runtime·mlookup(obj.data, &base, &size, nil) || obj.data != base) {
- // As an implementation detail we allow to set finalizers for an inner byte
- // of an object if it could come from tiny alloc (see mallocgc for details).
- if(ot->elem == nil || (ot->elem->kind&KindNoPointers) == 0 || ot->elem->size >= TinySize) {
- runtime·printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.data);
- goto throw;
- }
- }
- if(finalizer.type != nil) {
- runtime·createfing();
- if((finalizer.type->kind&KindMask) != KindFunc)
- goto badfunc;
- ft = (FuncType*)finalizer.type;
- if(ft->dotdotdot || ft->in.len != 1)
- goto badfunc;
- fint = *(Type**)ft->in.array;
- if(fint == obj.type) {
- // ok - same type
- } else if((fint->kind&KindMask) == KindPtr && (fint->x == nil || fint->x->name == nil || obj.type->x == nil || obj.type->x->name == nil) && ((PtrType*)fint)->elem == ((PtrType*)obj.type)->elem) {
- // ok - not same type, but both pointers,
- // one or the other is unnamed, and same element type, so assignable.
- } else if((fint->kind&KindMask) == KindInterface && ((InterfaceType*)fint)->mhdr.len == 0) {
- // ok - satisfies empty interface
- } else if((fint->kind&KindMask) == KindInterface && runtime·ifaceE2I2((InterfaceType*)fint, obj, &iface)) {
- // ok - satisfies non-empty interface
- } else
- goto badfunc;
- // compute size needed for return parameters
- nret = 0;
- for(i=0; i<ft->out.len; i++) {
- t = ((Type**)ft->out.array)[i];
- nret = ROUND(nret, t->align) + t->size;
- }
- nret = ROUND(nret, sizeof(void*));
- ot = (PtrType*)obj.type;
- if(!runtime·addfinalizer(obj.data, finalizer.data, nret, fint, ot)) {
- runtime·printf("runtime.SetFinalizer: finalizer already set\n");
- goto throw;
- }
- } else {
- // NOTE: asking to remove a finalizer when there currently isn't one set is OK.
- runtime·removefinalizer(obj.data);
- }
- return;
+ fn = g->m->ptrarg[0];
+ arg = g->m->ptrarg[1];
+ nret = g->m->scalararg[0];
+ fint = g->m->ptrarg[2];
+ ot = g->m->ptrarg[3];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+ g->m->ptrarg[2] = nil;
+ g->m->ptrarg[3] = nil;
-badfunc:
- runtime·printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *obj.type->string, *finalizer.type->string);
-throw:
- runtime·throw("runtime.SetFinalizer");
+ g->m->scalararg[0] = runtime·addfinalizer(arg, fn, nret, fint, ot);
}
void
-runtime·setFinalizer_m(void)
+runtime·removeFinalizer_m(void)
{
- Eface obj, finalizer;
+ void *p;
- obj.type = g->m->ptrarg[0];
- obj.data = g->m->ptrarg[1];
- finalizer.type = g->m->ptrarg[2];
- finalizer.data = g->m->ptrarg[3];
+ p = g->m->ptrarg[0];
g->m->ptrarg[0] = nil;
- g->m->ptrarg[1] = nil;
- g->m->ptrarg[2] = nil;
- g->m->ptrarg[3] = nil;
- setFinalizer(obj, finalizer);
+ runtime·removefinalizer(p);
}
// mcallable cache refill