diff -r de64b19b480e libgo/runtime/proc.c --- a/libgo/runtime/proc.c Thu Mar 06 16:00:18 2014 -0800 +++ b/libgo/runtime/proc.c Thu Mar 06 20:55:49 2014 -0800 @@ -1857,10 +1857,30 @@ // entersyscall is going to return immediately after. void runtime_entersyscall(void) __attribute__ ((no_split_stack)); +static void doentersyscall(void) __attribute__ ((no_split_stack, noinline)); void runtime_entersyscall() { + // Save the registers in the g structure so that any pointers + // held in registers will be seen by the garbage collector. + getcontext(&g->gcregs); + + // Do the work in a separate function, so that this function + // doesn't save any registers on its own stack. If this + // function does save any registers, we might store the wrong + // value in the call to getcontext. + // + // FIXME: This assumes that we do not need to save any + // callee-saved registers to access the TLS variable g. We + // don't want to put the ucontext_t on the stack because it is + // large and we can not split the stack here. + doentersyscall(); +} + +static void +doentersyscall() +{ // Disable preemption because during this function g is in Gsyscall status, // but can have inconsistent g->sched, do not let GC observe it. m->locks++; @@ -1878,10 +1898,6 @@ } #endif - // Save the registers in the g structure so that any pointers - // held in registers will be seen by the garbage collector. - getcontext(&g->gcregs); - g->status = Gsyscall; if(runtime_atomicload(&runtime_sched.sysmonwait)) { // TODO: fast atomic