summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/mfinal.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-03-15 20:29:17 -0700
committerRuss Cox <rsc@golang.org>2010-03-15 20:29:17 -0700
commit1fbc0657c8e7cb26b47288c4aa771f4cdac70481 (patch)
tree5acb3aa658fb8b49d4da7fa3dec27596141d0541 /src/pkg/runtime/mfinal.c
parent084a45074dc9cbb1beda41ecb9fc863a8b06d9b0 (diff)
downloadgolang-1fbc0657c8e7cb26b47288c4aa771f4cdac70481.tar.gz
runtime: lock finalizer table accesses
R=r CC=golang-dev http://codereview.appspot.com/462043
Diffstat (limited to 'src/pkg/runtime/mfinal.c')
-rw-r--r--src/pkg/runtime/mfinal.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c
index 959174723..53a2a4bbe 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;
}