libgo patch committed: Change some stack fields to uintptr

Ian Lance Taylor iant@golang.org
Thu Jun 22 14:44:00 GMT 2017


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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
-------------- next part --------------
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 249559)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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.
Index: libgo/go/runtime/proc.go
===================================================================
--- libgo/go/runtime/proc.go	(revision 249205)
+++ libgo/go/runtime/proc.go	(working copy)
@@ -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))
 }
 
Index: libgo/go/runtime/runtime2.go
===================================================================
--- libgo/go/runtime/runtime2.go	(revision 249558)
+++ libgo/go/runtime/runtime2.go	(working copy)
@@ -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
 
Index: libgo/runtime/proc.c
===================================================================
--- libgo/runtime/proc.c	(revision 249205)
+++ libgo/runtime/proc.c	(working copy)
@@ -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
 #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 *s
   *spsize = newg->gcstacksize;
   if(*spsize == 0)
     runtime_throw("bad spsize in resetNewG");
-  newg->gcnextsp = *sp;
+  newg->gcnextsp = (uintptr)(*sp);
 #endif
 }
 
Index: libgo/runtime/stack.c
===================================================================
--- libgo/runtime/stack.c	(revision 249205)
+++ libgo/runtime/stack.c	(working copy)
@@ -60,12 +60,12 @@ static void doscanstack1(G *gp, void *gc
 		// 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 *gc
 	} 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


More information about the Gcc-patches mailing list