aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/runtime/go-go.c7
-rw-r--r--libgo/runtime/thread.c16
2 files changed, 17 insertions, 6 deletions
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c
index 3146268..8c2de28 100644
--- a/libgo/runtime/go-go.c
+++ b/libgo/runtime/go-go.c
@@ -94,6 +94,13 @@ remove_current_thread (void)
runtime_MCache_ReleaseAll (mcache);
+ /* As soon as we release this look, a GC could run. Since this
+ thread is no longer on the list, the GC will not find our M
+ structure, so it could get freed at any time. That means that
+ any code from here to thread exit must not assume that the m is
+ valid. */
+ m = NULL;
+
i = pthread_mutex_unlock (&__go_thread_ids_lock);
__go_assert (i == 0);
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index 99a0d68..c4e7f6c 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -38,9 +38,11 @@ runtime_lock_full(Lock *l)
void
runtime_lock(Lock *l)
{
- if(m->locks < 0)
- runtime_throw("lock count");
- m->locks++;
+ if(m != nil) {
+ if(m->locks < 0)
+ runtime_throw("lock count");
+ m->locks++;
+ }
if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
runtime_lock_full(l);
@@ -58,9 +60,11 @@ runtime_unlock_full(Lock *l)
void
runtime_unlock(Lock *l)
{
- m->locks--;
- if(m->locks < 0)
- runtime_throw("lock count");
+ if(m != nil) {
+ m->locks--;
+ if(m->locks < 0)
+ runtime_throw("lock count");
+ }
if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
runtime_unlock_full(l);