re PR go/50654 (Many Go tests fail on emutls targets)

PR go/50654
runtime: Reload m and g if necessary after getcontext returns.

From-SVN: r184188
This commit is contained in:
Ian Lance Taylor 2012-02-14 00:38:07 +00:00
parent 09578bcd52
commit 4ea063cacb
1 changed files with 31 additions and 12 deletions

View File

@ -309,6 +309,8 @@ static void runtime_mcall(void (*)(G*)) __attribute__ ((noinline));
static void static void
runtime_mcall(void (*pfn)(G*)) runtime_mcall(void (*pfn)(G*))
{ {
M *mp;
G *gp;
#ifndef USING_SPLIT_STACK #ifndef USING_SPLIT_STACK
int i; int i;
#endif #endif
@ -317,28 +319,45 @@ runtime_mcall(void (*pfn)(G*))
// collector. // collector.
__builtin_unwind_init(); __builtin_unwind_init();
if(g == m->g0) mp = m;
gp = g;
if(gp == mp->g0)
runtime_throw("runtime: mcall called on m->g0 stack"); runtime_throw("runtime: mcall called on m->g0 stack");
if(g != nil) { if(gp != nil) {
#ifdef USING_SPLIT_STACK #ifdef USING_SPLIT_STACK
__splitstack_getcontext(&g->stack_context[0]); __splitstack_getcontext(&g->stack_context[0]);
#else #else
g->gcnext_sp = &i; gp->gcnext_sp = &i;
#endif #endif
g->fromgogo = false; gp->fromgogo = false;
getcontext(&g->context); 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 #ifdef USING_SPLIT_STACK
__splitstack_setcontext(&m->g0->stack_context[0]); __splitstack_setcontext(&mp->g0->stack_context[0]);
#endif #endif
m->g0->entry = (byte*)pfn; mp->g0->entry = (byte*)pfn;
m->g0->param = g; mp->g0->param = gp;
g = m->g0;
fixcontext(&m->g0->context); // It's OK to set g directly here because this case
setcontext(&m->g0->context); // 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"); runtime_throw("runtime: mcall function returned");
} }
} }