Commit 38f08ec0 by Ian Lance Taylor

runtime: scan register backing store on ia64

    
    On ia64, a separate stack is used for saving/restoring register frames,
    occupying the other end of the stack mapping. This must also be scanned
    for pointers into the heap.
    
    Reviewed-on: https://go-review.googlesource.com/85276

From-SVN: r257323
parent 2e30f1ee
e148068360699f24118950b728f23a5c98e1f85e 5e8a91bf239c253d7b5c84bd2c1dd3ecb18980e9
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -409,11 +409,15 @@ type g struct { ...@@ -409,11 +409,15 @@ type g struct {
// gcnextsegment: unused // gcnextsegment: unused
// gcnextsp: current SP while executing a syscall // gcnextsp: current SP while executing a syscall
// gcinitialsp: g0: top of stack; others: start of stack memory // 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 gcstack uintptr
gcstacksize uintptr gcstacksize uintptr
gcnextsegment uintptr gcnextsegment uintptr
gcnextsp uintptr gcnextsp uintptr
gcinitialsp unsafe.Pointer gcinitialsp unsafe.Pointer
gcnextsp2 uintptr
gcinitialsp2 unsafe.Pointer
// gcregs holds the register values while executing a syscall. // gcregs holds the register values while executing a syscall.
// This is set by getcontext and scanned by the garbage collector. // This is set by getcontext and scanned by the garbage collector.
......
...@@ -308,6 +308,7 @@ runtime_mcall(FuncVal *fv) ...@@ -308,6 +308,7 @@ runtime_mcall(FuncVal *fv)
// Ensure that all registers are on the stack for the garbage // Ensure that all registers are on the stack for the garbage
// collector. // collector.
__builtin_unwind_init(); __builtin_unwind_init();
flush_registers_to_secondary_stack();
gp = g; gp = g;
mp = gp->m; mp = gp->m;
...@@ -322,6 +323,7 @@ runtime_mcall(FuncVal *fv) ...@@ -322,6 +323,7 @@ runtime_mcall(FuncVal *fv)
// We have to point to an address on the stack that is // We have to point to an address on the stack that is
// below the saved registers. // below the saved registers.
gp->gcnextsp = (uintptr)(&afterregs); gp->gcnextsp = (uintptr)(&afterregs);
gp->gcnextsp2 = (uintptr)(secondary_stack_pointer());
#endif #endif
gp->fromgogo = false; gp->fromgogo = false;
getcontext(ucontext_arg(&gp->context[0])); getcontext(ucontext_arg(&gp->context[0]));
...@@ -500,6 +502,8 @@ runtime_mstart(void *arg) ...@@ -500,6 +502,8 @@ runtime_mstart(void *arg)
// is the top of the stack, not the bottom. // is the top of the stack, not the bottom.
gp->gcstacksize = 0; gp->gcstacksize = 0;
gp->gcnextsp = (uintptr)(&arg); gp->gcnextsp = (uintptr)(&arg);
gp->gcinitialsp2 = secondary_stack_pointer();
gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2);
#endif #endif
// Save the currently active context. This will return // Save the currently active context. This will return
...@@ -576,6 +580,8 @@ setGContext(void) ...@@ -576,6 +580,8 @@ setGContext(void)
gp->gcstack = 0; gp->gcstack = 0;
gp->gcstacksize = 0; gp->gcstacksize = 0;
gp->gcnextsp = (uintptr)(&val); gp->gcnextsp = (uintptr)(&val);
gp->gcinitialsp2 = secondary_stack_pointer();
gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2);
#endif #endif
getcontext(ucontext_arg(&gp->context[0])); getcontext(ucontext_arg(&gp->context[0]));
...@@ -654,6 +660,7 @@ doentersyscall(uintptr pc, uintptr sp) ...@@ -654,6 +660,7 @@ doentersyscall(uintptr pc, uintptr sp)
void *v; void *v;
g->gcnextsp = (uintptr)(&v); g->gcnextsp = (uintptr)(&v);
g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
} }
#endif #endif
...@@ -694,6 +701,7 @@ doentersyscallblock(uintptr pc, uintptr sp) ...@@ -694,6 +701,7 @@ doentersyscallblock(uintptr pc, uintptr sp)
void *v; void *v;
g->gcnextsp = (uintptr)(&v); g->gcnextsp = (uintptr)(&v);
g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
} }
#endif #endif
...@@ -756,6 +764,7 @@ runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* re ...@@ -756,6 +764,7 @@ runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* re
*ret_stacksize = (uintptr)stacksize; *ret_stacksize = (uintptr)stacksize;
newg->gcinitialsp = *ret_stack; newg->gcinitialsp = *ret_stack;
newg->gcstacksize = (uintptr)stacksize; newg->gcstacksize = (uintptr)stacksize;
newg->gcinitialsp2 = initial_secondary_stack_pointer(*ret_stack);
#endif #endif
} }
return newg; return newg;
...@@ -807,6 +816,7 @@ resetNewG(G *newg, void **sp, uintptr *spsize) ...@@ -807,6 +816,7 @@ resetNewG(G *newg, void **sp, uintptr *spsize)
if(*spsize == 0) if(*spsize == 0)
runtime_throw("bad spsize in resetNewG"); runtime_throw("bad spsize in resetNewG");
newg->gcnextsp = (uintptr)(*sp); newg->gcnextsp = (uintptr)(*sp);
newg->gcnextsp2 = (uintptr)(newg->gcinitialsp2);
#endif #endif
} }
......
...@@ -437,6 +437,23 @@ void runtime_check(void) ...@@ -437,6 +437,23 @@ void runtime_check(void)
// the stacks are allocated by the splitstack library. // the stacks are allocated by the splitstack library.
extern uintptr runtime_stacks_sys; 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; struct backtrace_state;
extern struct backtrace_state *__go_get_backtrace_state(void); extern struct backtrace_state *__go_get_backtrace_state(void);
extern _Bool __go_file_line(uintptr, int, String*, String*, intgo *); extern _Bool __go_file_line(uintptr, int, String*, String*, intgo *);
......
...@@ -34,6 +34,7 @@ void doscanstack(G *gp, void* gcw) { ...@@ -34,6 +34,7 @@ void doscanstack(G *gp, void* gcw) {
// Save registers on the stack, so that if we are scanning our // Save registers on the stack, so that if we are scanning our
// own stack we will see them. // own stack we will see them.
__builtin_unwind_init(); __builtin_unwind_init();
flush_registers_to_secondary_stack();
doscanstack1(gp, gcw); doscanstack1(gp, gcw);
} }
...@@ -82,21 +83,32 @@ static void doscanstack1(G *gp, void *gcw) { ...@@ -82,21 +83,32 @@ static void doscanstack1(G *gp, void *gcw) {
#else #else
byte* bottom; byte* bottom;
byte* top; byte* top;
byte* nextsp2;
byte* initialsp2;
if(gp == runtime_g()) { if(gp == runtime_g()) {
// Scanning our own stack. // Scanning our own stack.
bottom = (byte*)&gp; bottom = (byte*)&gp;
nextsp2 = secondary_stack_pointer();
} else { } else {
// Scanning another goroutine's stack. // Scanning another goroutine's stack.
// The goroutine is usually asleep (the world is stopped). // The goroutine is usually asleep (the world is stopped).
bottom = (void*)gp->gcnextsp; bottom = (void*)gp->gcnextsp;
if(bottom == nil) if(bottom == nil)
return; return;
nextsp2 = (void*)gp->gcnextsp2;
} }
top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize; top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize;
if(top > bottom) if(top > bottom)
scanstackblock(bottom, (uintptr)(top - bottom), gcw); scanstackblock(bottom, (uintptr)(top - bottom), gcw);
else else
scanstackblock(top, (uintptr)(bottom - top), gcw); 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 #endif
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment