diff options
author | Russ Cox <rsc@golang.org> | 2010-03-15 20:29:17 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2010-03-15 20:29:17 -0700 |
commit | 1fbc0657c8e7cb26b47288c4aa771f4cdac70481 (patch) | |
tree | 5acb3aa658fb8b49d4da7fa3dec27596141d0541 /src/pkg/runtime/mfinal.c | |
parent | 084a45074dc9cbb1beda41ecb9fc863a8b06d9b0 (diff) | |
download | golang-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.c | 22 |
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; } |