runtime: move mstart from Go to C

The assignments done in mstart must be done without write barriers, as
mstart is running without an m or p.  In the gc toolchain the
equivalent code to intialize g and g->m is written in assembler;
on GNU/Linux, it's in the clone function.

Change-Id: Id84d2897e2a72a7ff906c763cf4524e956b709e7
Reviewed-on: https://go-review.googlesource.com/40989
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index 9f467ee..0907afc 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -35,7 +35,6 @@
 //go:linkname stopTheWorldWithSema runtime.stopTheWorldWithSema
 //go:linkname startTheWorldWithSema runtime.startTheWorldWithSema
 //go:linkname kickoff runtime.kickoff
-//go:linkname mstart runtime.mstart
 //go:linkname mstart1 runtime.mstart1
 //go:linkname globrunqput runtime.globrunqput
 //go:linkname pidleget runtime.pidleget
@@ -54,7 +53,6 @@
 func gogo(*g)
 func setGContext()
 func makeGContext(*g, unsafe.Pointer, uintptr)
-func mstartInitContext(*g, unsafe.Pointer)
 func getTraceback(me, gp *g)
 func gtraceback(*g)
 func _cgo_notify_runtime_init_done()
@@ -988,26 +986,7 @@
 	goexit1()
 }
 
-// Called to start an M.
-// For gccgo this is called directly by pthread_create.
-//go:nosplit
-func mstart(mpu unsafe.Pointer) unsafe.Pointer {
-	mp := (*m)(mpu)
-	_g_ := mp.g0
-	_g_.m = mp
-	setg(_g_)
-
-	_g_.entry = nil
-	_g_.param = nil
-
-	mstartInitContext(_g_, unsafe.Pointer(&mp))
-
-	// This is never reached, but is required because pthread_create
-	// expects a function that returns a pointer.
-	return nil
-}
-
-// This is called from mstartInitContext.
+// This is called from mstart.
 func mstart1() {
 	_g_ := getg()
 
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 10dd0a8..23cfb73 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -459,14 +459,22 @@
 	runtime_gogo(traceback->gp);
 }
 
-// Called to set up the context information for a new M.
-
-void mstartInitContext(G*, void*)
-	__asm__(GOSYM_PREFIX "runtime.mstartInitContext");
-
-void
-mstartInitContext(G *gp, void *stack __attribute__ ((unused)))
+// Called by pthread_create to start an M.
+void*
+runtime_mstart(void *arg)
 {
+	M* mp;
+	G* gp;
+
+	mp = (M*)(arg);
+	gp = mp->g0;
+	gp->m = mp;
+
+	g = gp;
+
+	gp->entry = nil;
+	gp->param = nil;
+
 	initcontext();
 
 	// Record top of stack for use by mcall.
@@ -475,11 +483,11 @@
 #ifdef USING_SPLIT_STACK
 	__splitstack_getcontext(&gp->stackcontext[0]);
 #else
-	gp->gcinitialsp = stack;
+	gp->gcinitialsp = &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 = stack;
+	gp->gcnextsp = &arg;
 #endif
 
 	// Save the currently active context.  This will return
@@ -493,7 +501,7 @@
 		gtraceback(gp);
 	}
 
-	if(gp->entry != 0) {
+	if(gp->entry != nil) {
 		// Got here from mcall.
 		FuncVal *fv = gp->entry;
 		void (*pfn)(G*) = (void (*)(G*))fv->fn;
@@ -514,6 +522,10 @@
 #endif
 
 	mstart1();
+
+	// mstart1 does not return, but we need a return statement
+	// here to avoid a compiler warning.
+	return nil;
 }
 
 typedef struct CgoThreadStart CgoThreadStart;
@@ -550,7 +562,7 @@
 #endif
 	getcontext(ucontext_arg(&gp->context[0]));
 
-	if(gp->entry != 0) {
+	if(gp->entry != nil) {
 		// Got here from mcall.
 		FuncVal *fv = gp->entry;
 		void (*pfn)(G*) = (void (*)(G*))fv->fn;
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index ac86fa4..e38bf06 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -293,8 +293,7 @@
   __asm__ (GOSYM_PREFIX "runtime.ready");
 String	runtime_getenv(const char*);
 int32	runtime_atoi(const byte*, intgo);
-void*	runtime_mstart(void*)
-	__asm__(GOSYM_PREFIX "runtime.mstart");
+void*	runtime_mstart(void*);
 G*	runtime_malg(bool, bool, byte**, uintptr*)
 	__asm__(GOSYM_PREFIX "runtime.malg");
 void	runtime_minit(void)