-e148068360699f24118950b728f23a5c98e1f85e
+5e8a91bf239c253d7b5c84bd2c1dd3ecb18980e9
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
// gcnextsegment: unused
// gcnextsp: current SP while executing a syscall
// gcinitialsp: g0: top of stack; others: start of stack memory
+ // gcnextsp2: current secondary stack pointer (if present)
+ // gcinitialsp2: start of secondary stack (if present)
gcstack uintptr
gcstacksize uintptr
gcnextsegment uintptr
gcnextsp uintptr
gcinitialsp unsafe.Pointer
+ gcnextsp2 uintptr
+ gcinitialsp2 unsafe.Pointer
// gcregs holds the register values while executing a syscall.
// This is set by getcontext and scanned by the garbage collector.
// Ensure that all registers are on the stack for the garbage
// collector.
__builtin_unwind_init();
+ flush_registers_to_secondary_stack();
gp = g;
mp = gp->m;
// We have to point to an address on the stack that is
// below the saved registers.
gp->gcnextsp = (uintptr)(&afterregs);
+ gp->gcnextsp2 = (uintptr)(secondary_stack_pointer());
#endif
gp->fromgogo = false;
getcontext(ucontext_arg(&gp->context[0]));
// is the top of the stack, not the bottom.
gp->gcstacksize = 0;
gp->gcnextsp = (uintptr)(&arg);
+ gp->gcinitialsp2 = secondary_stack_pointer();
+ gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2);
#endif
// Save the currently active context. This will return
gp->gcstack = 0;
gp->gcstacksize = 0;
gp->gcnextsp = (uintptr)(&val);
+ gp->gcinitialsp2 = secondary_stack_pointer();
+ gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2);
#endif
getcontext(ucontext_arg(&gp->context[0]));
void *v;
g->gcnextsp = (uintptr)(&v);
+ g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
}
#endif
void *v;
g->gcnextsp = (uintptr)(&v);
+ g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
}
#endif
*ret_stacksize = (uintptr)stacksize;
newg->gcinitialsp = *ret_stack;
newg->gcstacksize = (uintptr)stacksize;
+ newg->gcinitialsp2 = initial_secondary_stack_pointer(*ret_stack);
#endif
}
return newg;
if(*spsize == 0)
runtime_throw("bad spsize in resetNewG");
newg->gcnextsp = (uintptr)(*sp);
+ newg->gcnextsp2 = (uintptr)(newg->gcinitialsp2);
#endif
}
// the stacks are allocated by the splitstack library.
extern uintptr runtime_stacks_sys;
+/*
+ * ia64's register file is spilled to a separate stack, the register backing
+ * store, on window overflow, and must also be scanned. This occupies the other
+ * end of the normal stack allocation, growing upwards.
+ * We also need to ensure all register windows are flushed to the backing
+ * store, as unlike SPARC, __builtin_unwind_init doesn't do this on ia64.
+ */
+#ifdef __ia64__
+# define secondary_stack_pointer() __builtin_ia64_bsp()
+# define initial_secondary_stack_pointer(stack_alloc) (stack_alloc)
+# define flush_registers_to_secondary_stack() __builtin_ia64_flushrs()
+#else
+# define secondary_stack_pointer() nil
+# define initial_secondary_stack_pointer(stack_alloc) nil
+# define flush_registers_to_secondary_stack()
+#endif
+
struct backtrace_state;
extern struct backtrace_state *__go_get_backtrace_state(void);
extern _Bool __go_file_line(uintptr, int, String*, String*, intgo *);
// Save registers on the stack, so that if we are scanning our
// own stack we will see them.
__builtin_unwind_init();
+ flush_registers_to_secondary_stack();
doscanstack1(gp, gcw);
}
#else
byte* bottom;
byte* top;
+ byte* nextsp2;
+ byte* initialsp2;
if(gp == runtime_g()) {
// Scanning our own stack.
bottom = (byte*)&gp;
+ nextsp2 = secondary_stack_pointer();
} else {
// Scanning another goroutine's stack.
// The goroutine is usually asleep (the world is stopped).
bottom = (void*)gp->gcnextsp;
if(bottom == nil)
return;
+ nextsp2 = (void*)gp->gcnextsp2;
}
top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize;
if(top > bottom)
scanstackblock(bottom, (uintptr)(top - bottom), gcw);
else
scanstackblock(top, (uintptr)(bottom - top), gcw);
+ if (nextsp2 != nil) {
+ initialsp2 = (byte*)(void*)(gp->gcinitialsp2);
+ if(initialsp2 > nextsp2)
+ scanstackblock(nextsp2, (uintptr)(initialsp2 - nextsp2), gcw);
+ else
+ scanstackblock(initialsp2, (uintptr)(nextsp2 - initialsp2), gcw);
+ }
#endif
}