diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-14 00:38:07 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-14 00:38:07 +0000 |
commit | 53cb58a1f20cba86ecbd208e618a6c576726d3aa (patch) | |
tree | 9781b494c634c61dbb0c3c9e68e0efae56301b42 | |
parent | 4748ab553361ac89a311d8b2933ab91fbbb5dee7 (diff) | |
download | gcc-53cb58a1f20cba86ecbd208e618a6c576726d3aa.tar.gz |
PR go/50654
runtime: Reload m and g if necessary after getcontext returns.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184188 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libgo/runtime/proc.c | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 94c2a51730e..609920a5619 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -309,6 +309,8 @@ static void runtime_mcall(void (*)(G*)) __attribute__ ((noinline)); static void runtime_mcall(void (*pfn)(G*)) { + M *mp; + G *gp; #ifndef USING_SPLIT_STACK int i; #endif @@ -317,28 +319,45 @@ runtime_mcall(void (*pfn)(G*)) // collector. __builtin_unwind_init(); - if(g == m->g0) + mp = m; + gp = g; + if(gp == mp->g0) runtime_throw("runtime: mcall called on m->g0 stack"); - if(g != nil) { + if(gp != nil) { #ifdef USING_SPLIT_STACK __splitstack_getcontext(&g->stack_context[0]); #else - g->gcnext_sp = &i; + gp->gcnext_sp = &i; #endif - g->fromgogo = false; - getcontext(&g->context); + gp->fromgogo = false; + getcontext(&gp->context); + + // When we return from getcontext, we may be running + // in a new thread. That means that m and g may have + // changed. They are global variables so we will + // reload them, but the addresses of m and g may be + // cached in our local stack frame, and those + // addresses may be wrong. Call functions to reload + // the values for this thread. + mp = runtime_m(); + gp = runtime_g(); } - if (g == nil || !g->fromgogo) { + if (gp == nil || !gp->fromgogo) { #ifdef USING_SPLIT_STACK - __splitstack_setcontext(&m->g0->stack_context[0]); + __splitstack_setcontext(&mp->g0->stack_context[0]); #endif - m->g0->entry = (byte*)pfn; - m->g0->param = g; - g = m->g0; - fixcontext(&m->g0->context); - setcontext(&m->g0->context); + mp->g0->entry = (byte*)pfn; + mp->g0->param = gp; + + // It's OK to set g directly here because this case + // can not occur if we got here via a setcontext to + // the getcontext call just above. + g = mp->g0; + + fixcontext(&mp->g0->context); + setcontext(&mp->g0->context); runtime_throw("runtime: mcall function returned"); } } |