diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 8f54e51df35e..1bc0876d8e62 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -1857,9 +1857,29 @@ goexit0(G *gp) // 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. @@ -1878,10 +1898,6 @@ runtime_entersyscall() } #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