From acfd7b8d128ceb4ed80be82ff37d1b58379ec734 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 15 Mar 2010 20:29:17 -0700 Subject: [PATCH] runtime: lock finalizer table accesses R=r CC=golang-dev https://golang.org/cl/462043 --- src/pkg/runtime/mfinal.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c index 95917472314..53a2a4bbe9c 100644 --- a/src/pkg/runtime/mfinal.c +++ b/src/pkg/runtime/mfinal.c @@ -5,6 +5,8 @@ #include "runtime.h" #include "malloc.h" +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 @@ -97,18 +99,24 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) uint32 *ref; byte *base; - if(!mlookup(p, &base, nil, nil, &ref) || p != base) + lock(&finlock); + if(!mlookup(p, &base, nil, nil, &ref) || p != base) { + unlock(&finlock); throw("addfinalizer on invalid pointer"); + } if(f == nil) { if(*ref & RefHasFinalizer) { - getfinalizer(p, 1, nil); + lookfintab(&fintab, p, 1, nil); *ref &= ~RefHasFinalizer; } + unlock(&finlock); return; } - if(*ref & RefHasFinalizer) + if(*ref & RefHasFinalizer) { + unlock(&finlock); throw("double finalizer"); + } *ref |= RefHasFinalizer; if(fintab.nkey >= fintab.max/2+fintab.max/4) { @@ -141,6 +149,7 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) } addfintab(&fintab, p, f, nret); + unlock(&finlock); } // get finalizer; if del, delete finalizer. @@ -148,5 +157,10 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) void* getfinalizer(void *p, bool del, int32 *nret) { - return lookfintab(&fintab, p, del, nret); + void *f; + + lock(&finlock); + f = lookfintab(&fintab, p, del, nret); + unlock(&finlock); + return f; }