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
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");
}
}