runtime: change some stack fields to uintptr
Because of how gccgo implements cgo calls, the code in dropm may not have any write barriers. As a step toward implementing that, change the gcstack, gcnextsegment, and gcnextsp fields of the g struct to uintptr, so that assignments to them do not require write barriers. The gcinitialsp field remains unsafe.Pointer, as on 32-bit systems that do not support split stack it points to a heap allocated space used for the goroutine stack. The test for this is runtime tests like TestCgoCallbackGC, which are not run today but will be run with a future gotools patch. Reviewed-on: https://go-review.googlesource.com/46396 From-SVN: r249561
This commit is contained in:
parent
a055692a25
commit
3b0ddadf74
@ -1,4 +1,4 @@
|
||||
73b14da15ec731837ce2a45db658142bfbf5fe22
|
||||
b5c9fe259ec43f8079581c3bea0f1d12d85213a7
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -1460,8 +1460,8 @@ func dropm() {
|
||||
// gccgo sets the stack to Gdead here, because the splitstack
|
||||
// context is not initialized.
|
||||
atomic.Store(&mp.curg.atomicstatus, _Gdead)
|
||||
mp.curg.gcstack = nil
|
||||
mp.curg.gcnextsp = nil
|
||||
mp.curg.gcstack = 0
|
||||
mp.curg.gcnextsp = 0
|
||||
|
||||
mnext := lockextra(true)
|
||||
mp.schedlink.set(mnext)
|
||||
@ -2591,8 +2591,8 @@ func exitsyscallclear(gp *g) {
|
||||
// clear syscallsp.
|
||||
gp.syscallsp = 0
|
||||
|
||||
gp.gcstack = nil
|
||||
gp.gcnextsp = nil
|
||||
gp.gcstack = 0
|
||||
gp.gcnextsp = 0
|
||||
memclrNoHeapPointers(unsafe.Pointer(&gp.gcregs), unsafe.Sizeof(gp.gcregs))
|
||||
}
|
||||
|
||||
|
@ -402,10 +402,10 @@ type g struct {
|
||||
isforeign bool // whether current exception is not from Go
|
||||
|
||||
// Fields that hold stack and context information if status is Gsyscall
|
||||
gcstack unsafe.Pointer
|
||||
gcstack uintptr
|
||||
gcstacksize uintptr
|
||||
gcnextsegment unsafe.Pointer
|
||||
gcnextsp unsafe.Pointer
|
||||
gcnextsegment uintptr
|
||||
gcnextsp uintptr
|
||||
gcinitialsp unsafe.Pointer
|
||||
gcregs g_ucontext_t
|
||||
|
||||
|
@ -316,7 +316,7 @@ runtime_mcall(FuncVal *fv)
|
||||
#else
|
||||
// We have to point to an address on the stack that is
|
||||
// below the saved registers.
|
||||
gp->gcnextsp = &afterregs;
|
||||
gp->gcnextsp = (uintptr)(&afterregs);
|
||||
#endif
|
||||
gp->fromgogo = false;
|
||||
getcontext(ucontext_arg(&gp->context[0]));
|
||||
@ -489,7 +489,7 @@ runtime_mstart(void *arg)
|
||||
// Setting gcstacksize to 0 is a marker meaning that gcinitialsp
|
||||
// is the top of the stack, not the bottom.
|
||||
gp->gcstacksize = 0;
|
||||
gp->gcnextsp = &arg;
|
||||
gp->gcnextsp = (uintptr)(&arg);
|
||||
#endif
|
||||
|
||||
// Save the currently active context. This will return
|
||||
@ -558,9 +558,9 @@ setGContext()
|
||||
__splitstack_block_signals(&val, nil);
|
||||
#else
|
||||
gp->gcinitialsp = &val;
|
||||
gp->gcstack = nil;
|
||||
gp->gcstack = 0;
|
||||
gp->gcstacksize = 0;
|
||||
gp->gcnextsp = &val;
|
||||
gp->gcnextsp = (uintptr)(&val);
|
||||
#endif
|
||||
getcontext(ucontext_arg(&gp->context[0]));
|
||||
|
||||
@ -628,16 +628,17 @@ doentersyscall(uintptr pc, uintptr sp)
|
||||
#ifdef USING_SPLIT_STACK
|
||||
{
|
||||
size_t gcstacksize;
|
||||
g->gcstack = __splitstack_find(nil, nil, &gcstacksize,
|
||||
&g->gcnextsegment, &g->gcnextsp,
|
||||
&g->gcinitialsp);
|
||||
g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize,
|
||||
(void**)(&g->gcnextsegment),
|
||||
(void**)(&g->gcnextsp),
|
||||
&g->gcinitialsp));
|
||||
g->gcstacksize = (uintptr)gcstacksize;
|
||||
}
|
||||
#else
|
||||
{
|
||||
void *v;
|
||||
|
||||
g->gcnextsp = (byte *) &v;
|
||||
g->gcnextsp = (uintptr)(&v);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -667,9 +668,10 @@ doentersyscallblock(uintptr pc, uintptr sp)
|
||||
#ifdef USING_SPLIT_STACK
|
||||
{
|
||||
size_t gcstacksize;
|
||||
g->gcstack = __splitstack_find(nil, nil, &gcstacksize,
|
||||
&g->gcnextsegment, &g->gcnextsp,
|
||||
&g->gcinitialsp);
|
||||
g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize,
|
||||
(void**)(&g->gcnextsegment),
|
||||
(void**)(&g->gcnextsp),
|
||||
&g->gcinitialsp));
|
||||
g->gcstacksize = (uintptr)gcstacksize;
|
||||
}
|
||||
#else
|
||||
@ -765,7 +767,7 @@ resetNewG(G *newg, void **sp, uintptr *spsize)
|
||||
*spsize = newg->gcstacksize;
|
||||
if(*spsize == 0)
|
||||
runtime_throw("bad spsize in resetNewG");
|
||||
newg->gcnextsp = *sp;
|
||||
newg->gcnextsp = (uintptr)(*sp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -60,12 +60,12 @@ static void doscanstack1(G *gp, void *gcw) {
|
||||
// as schedlock and may have needed to start a new stack segment.
|
||||
// Use the stack segment and stack pointer at the time of
|
||||
// the system call instead, since that won't change underfoot.
|
||||
if(gp->gcstack != nil) {
|
||||
sp = gp->gcstack;
|
||||
if(gp->gcstack != 0) {
|
||||
sp = (void*)(gp->gcstack);
|
||||
spsize = gp->gcstacksize;
|
||||
next_segment = gp->gcnextsegment;
|
||||
next_sp = gp->gcnextsp;
|
||||
initial_sp = gp->gcinitialsp;
|
||||
next_segment = (void*)(gp->gcnextsegment);
|
||||
next_sp = (void*)(gp->gcnextsp);
|
||||
initial_sp = (void*)(gp->gcinitialsp);
|
||||
} else {
|
||||
sp = __splitstack_find_context((void**)(&gp->stackcontext[0]),
|
||||
&spsize, &next_segment,
|
||||
@ -89,11 +89,11 @@ static void doscanstack1(G *gp, void *gcw) {
|
||||
} else {
|
||||
// Scanning another goroutine's stack.
|
||||
// The goroutine is usually asleep (the world is stopped).
|
||||
bottom = (byte*)gp->gcnextsp;
|
||||
bottom = (void*)gp->gcnextsp;
|
||||
if(bottom == nil)
|
||||
return;
|
||||
}
|
||||
top = (byte*)gp->gcinitialsp + gp->gcstacksize;
|
||||
top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize;
|
||||
if(top > bottom)
|
||||
scanstackblock(bottom, (uintptr)(top - bottom), gcw);
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user