aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libgo/runtime/proc.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 8f54e51..1bc0876 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -1857,10 +1857,30 @@ 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.
m->locks++;
@@ -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