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
This commit is contained in:
parent
2e30f1ee86
commit
38f08ec0bd
@ -1,4 +1,4 @@
|
||||
e148068360699f24118950b728f23a5c98e1f85e
|
||||
5e8a91bf239c253d7b5c84bd2c1dd3ecb18980e9
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -409,11 +409,15 @@ type g struct {
|
||||
// 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.
|
||||
|
@ -308,6 +308,7 @@ runtime_mcall(FuncVal *fv)
|
||||
// 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;
|
||||
@ -322,6 +323,7 @@ runtime_mcall(FuncVal *fv)
|
||||
// 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]));
|
||||
@ -500,6 +502,8 @@ runtime_mstart(void *arg)
|
||||
// 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
|
||||
@ -576,6 +580,8 @@ setGContext(void)
|
||||
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]));
|
||||
|
||||
@ -654,6 +660,7 @@ doentersyscall(uintptr pc, uintptr sp)
|
||||
void *v;
|
||||
|
||||
g->gcnextsp = (uintptr)(&v);
|
||||
g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -694,6 +701,7 @@ doentersyscallblock(uintptr pc, uintptr sp)
|
||||
void *v;
|
||||
|
||||
g->gcnextsp = (uintptr)(&v);
|
||||
g->gcnextsp2 = (uintptr)(secondary_stack_pointer());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -756,6 +764,7 @@ runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* re
|
||||
*ret_stacksize = (uintptr)stacksize;
|
||||
newg->gcinitialsp = *ret_stack;
|
||||
newg->gcstacksize = (uintptr)stacksize;
|
||||
newg->gcinitialsp2 = initial_secondary_stack_pointer(*ret_stack);
|
||||
#endif
|
||||
}
|
||||
return newg;
|
||||
@ -807,6 +816,7 @@ resetNewG(G *newg, void **sp, uintptr *spsize)
|
||||
if(*spsize == 0)
|
||||
runtime_throw("bad spsize in resetNewG");
|
||||
newg->gcnextsp = (uintptr)(*sp);
|
||||
newg->gcnextsp2 = (uintptr)(newg->gcinitialsp2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -437,6 +437,23 @@ void runtime_check(void)
|
||||
// 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 *);
|
||||
|
@ -34,6 +34,7 @@ void doscanstack(G *gp, void* gcw) {
|
||||
// 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);
|
||||
}
|
||||
@ -82,21 +83,32 @@ static void doscanstack1(G *gp, void *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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user