aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-02-14 00:38:07 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-02-14 00:38:07 +0000
commit4ea063cacb9088c9a1bb9980d3850a6af8b83a5d (patch)
tree9781b494c634c61dbb0c3c9e68e0efae56301b42 /libgo
parent09578bcd52d81e43a11caac178ee78073a2eb6fc (diff)
downloadgcc-4ea063cacb9088c9a1bb9980d3850a6af8b83a5d.zip
gcc-4ea063cacb9088c9a1bb9980d3850a6af8b83a5d.tar.gz
gcc-4ea063cacb9088c9a1bb9980d3850a6af8b83a5d.tar.bz2
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
Diffstat (limited to 'libgo')
-rw-r--r--libgo/runtime/proc.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 94c2a51..609920a 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");
}
}