summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-03-01 11:44:43 -0500
committerRuss Cox <rsc@golang.org>2013-03-01 11:44:43 -0500
commitcb8284ee27ef8c5fdca051d117e5ad2bb7604ebd (patch)
tree26acc30fed5da6375665e0e1966d31357a3dfce1
parente7ab68bb8037c3978e9e9c245fefadc7eefa4c77 (diff)
downloadgo-cb8284ee27ef8c5fdca051d117e5ad2bb7604ebd.tar.gz
runtime: start all threads with runtime.mstart
Putting the M initialization in multiple places will not scale. Various code assumes mstart is the start already. Make it so. R=golang-dev, devon.odell CC=golang-dev https://codereview.appspot.com/7420048
-rw-r--r--src/pkg/runtime/proc.c43
-rw-r--r--src/pkg/runtime/runtime.h3
-rw-r--r--src/pkg/runtime/sys_freebsd_386.s7
-rw-r--r--src/pkg/runtime/sys_freebsd_amd64.s9
-rw-r--r--src/pkg/runtime/sys_freebsd_arm.s5
-rw-r--r--src/pkg/runtime/sys_windows_386.s7
-rw-r--r--src/pkg/runtime/sys_windows_amd64.s6
-rw-r--r--src/pkg/runtime/thread_darwin.c8
-rw-r--r--src/pkg/runtime/thread_freebsd.c19
-rw-r--r--src/pkg/runtime/thread_linux.c8
-rw-r--r--src/pkg/runtime/thread_netbsd.c8
-rw-r--r--src/pkg/runtime/thread_openbsd.c6
-rw-r--r--src/pkg/runtime/thread_plan9.c6
-rw-r--r--src/pkg/runtime/thread_windows.c8
14 files changed, 64 insertions, 79 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 4341ed356..b0511cacb 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -84,7 +84,7 @@ static void schedule(void);
static void procresize(int32);
static void acquirep(P*);
static P* releasep(void);
-static void newm(void(*)(void), P*, bool, bool);
+static void newm(void(*)(void), P*);
static void goidle(void);
static void stopm(void);
static void startm(P*, bool);
@@ -161,7 +161,7 @@ static FuncVal scavenger = {runtime·MHeap_Scavenger};
void
runtime·main(void)
{
- newm(sysmon, nil, false, false);
+ newm(sysmon, nil);
// Lock the main goroutine onto this, the main OS thread,
// during initialization. Most programs won't care, but a few
@@ -381,6 +381,12 @@ runtime·stoptheworld(void)
}
}
+static void
+mhelpgc(void)
+{
+ m->helpgc = 1;
+}
+
void
runtime·starttheworld(void)
{
@@ -428,7 +434,7 @@ runtime·starttheworld(void)
// coordinate. This lazy approach works out in practice:
// we don't mind if the first couple gc rounds don't have quite
// the maximum number of procs.
- newm(runtime·mstart, nil, true, false);
+ newm(mhelpgc, nil);
}
}
@@ -460,6 +466,9 @@ runtime·mstart(void)
if(runtime·iscgo)
runtime·newextram();
}
+
+ if(m->mstartfn)
+ m->mstartfn();
if(m->helpgc) {
m->helpgc = false;
@@ -726,16 +735,15 @@ unlockextra(M *mp)
}
-// Create a new m. It will start off with a call to fn.
+// Create a new m. It will start off with a call to fn, or else the scheduler.
static void
-newm(void(*fn)(void), P *p, bool helpgc, bool spinning)
+newm(void(*fn)(void), P *p)
{
M *mp;
mp = runtime·allocm(p);
mp->nextp = p;
- mp->helpgc = helpgc;
- mp->spinning = spinning;
+ mp->mstartfn = fn;
if(runtime·iscgo) {
CgoThreadStart ts;
@@ -744,11 +752,11 @@ newm(void(*fn)(void), P *p, bool helpgc, bool spinning)
runtime·throw("_cgo_thread_start missing");
ts.m = mp;
ts.g = mp->g0;
- ts.fn = fn;
+ ts.fn = runtime·mstart;
runtime·asmcgocall(_cgo_thread_start, &ts);
return;
}
- runtime·newosproc(mp, mp->g0, (byte*)mp->g0->stackbase, fn);
+ runtime·newosproc(mp, (byte*)mp->g0->stackbase);
}
// Stops execution of the current m until new work is available.
@@ -781,12 +789,19 @@ retry:
m->nextp = nil;
}
+static void
+mspinning(void)
+{
+ m->spinning = true;
+}
+
// Schedules some M to run the p (creates an M if necessary).
// If p==nil, tries to get an idle P, if no idle P's returns false.
static void
startm(P *p, bool spinning)
{
M *mp;
+ void (*fn)(void);
runtime·lock(&runtime·sched);
if(p == nil) {
@@ -801,7 +816,10 @@ startm(P *p, bool spinning)
mp = mget();
runtime·unlock(&runtime·sched);
if(mp == nil) {
- newm(runtime·mstart, p, false, spinning);
+ fn = nil;
+ if(spinning)
+ fn = mspinning;
+ newm(fn, p);
return;
}
if(mp->spinning)
@@ -1887,11 +1905,6 @@ sysmon(void)
uint32 idle, delay;
uint32 ticks[MaxGomaxprocs];
- // This is a special dedicated thread that retakes P's from blocking syscalls.
- // It works w/o mcache nor stackalloc, it may work concurrently with GC.
- runtime·asminit();
- runtime·minit();
-
idle = 0; // how many cycles in succession we had not wokeup somebody
delay = 0;
for(;;) {
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 444080831..602b185ad 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -702,7 +702,8 @@ void runtime·exit1(int32);
void runtime·ready(G*);
byte* runtime·getenv(int8*);
int32 runtime·atoi(byte*);
-void runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void));
+void runtime·newosproc(M *mp, void *stk);
+void runtime·mstart(void);
G* runtime·malg(int32);
void runtime·asminit(void);
void runtime·mpreinit(M*);
diff --git a/src/pkg/runtime/sys_freebsd_386.s b/src/pkg/runtime/sys_freebsd_386.s
index 0b472e307..d5370267a 100644
--- a/src/pkg/runtime/sys_freebsd_386.s
+++ b/src/pkg/runtime/sys_freebsd_386.s
@@ -38,12 +38,7 @@ TEXT runtime·thr_start(SB),7,$0
MOVL AX, m(CX)
CALL runtime·stackcheck(SB) // smashes AX
-
- // newosproc left the function we should call in mp->mstartfn.
- get_tls(CX)
- MOVL m(CX), AX
- MOVL m_mstartfn(AX), AX
- CALL AX
+ CALL runtime·mstart(SB)
MOVL 0, AX // crash (not reached)
diff --git a/src/pkg/runtime/sys_freebsd_amd64.s b/src/pkg/runtime/sys_freebsd_amd64.s
index 218851b78..40c6237e2 100644
--- a/src/pkg/runtime/sys_freebsd_amd64.s
+++ b/src/pkg/runtime/sys_freebsd_amd64.s
@@ -38,13 +38,8 @@ TEXT runtime·thr_start(SB),7,$0
MOVQ m_g0(R13), DI
MOVQ DI, g(CX)
- CALL runtime·stackcheck(SB)
-
- // newosproc left the function we should call in mp->mstartfn.
- get_tls(CX)
- MOVQ m(CX), AX
- MOVQ m_mstartfn(AX), AX
- CALL AX
+ CALL runtime·stackcheck(SB)
+ CALL runtime·mstart(SB)
MOVQ 0, AX // crash (not reached)
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s
index d9e333932..77050e8d0 100644
--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -33,10 +33,7 @@ TEXT runtime·thr_start(SB),7,$0
// set up g
MOVW m_g0(R9), R10
BL runtime·emptyfunc(SB) // fault if stack check is wrong
-
- // newosproc left the function we should call in mp->tls[2] for us.
- MOVW (m_tls+8)(m), R0
- BL (R0)
+ BL runtime·mstart(SB)
MOVW $2, R9 // crash (not reached)
MOVW R9, (R9)
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s
index 2c3c5d465..ca59f0a1d 100644
--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -259,12 +259,7 @@ TEXT runtime·tstart(SB),7,$0
CLD
CALL runtime·stackcheck(SB) // clobbers AX,CX
-
- // newosproc left the function we should call in mp->mstartfn.
- get_tls(CX)
- MOVL m(CX), AX
- MOVL m_mstartfn(AX), AX
- CALL AX
+ CALL runtime·mstart(SB)
RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s
index dc9c94ae4..fe88f3b75 100644
--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -329,11 +329,7 @@ TEXT runtime·tstart_stdcall(SB),7,$0
CLD
CALL runtime·stackcheck(SB) // clobbers AX,CX
-
- get_tls(CX)
- MOVQ m(CX), AX
- MOVQ m_mstartfn(AX), AX
- CALL AX
+ CALL runtime·mstart(SB)
XORL AX, AX // return 0 == success
RET
diff --git a/src/pkg/runtime/thread_darwin.c b/src/pkg/runtime/thread_darwin.c
index 1400e6e7b..adb1ffe6a 100644
--- a/src/pkg/runtime/thread_darwin.c
+++ b/src/pkg/runtime/thread_darwin.c
@@ -87,19 +87,19 @@ runtime·goenvs(void)
}
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
int32 errno;
Sigset oset;
mp->tls[0] = mp->id; // so 386 asm can find it
if(0){
- runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, mp->id, (int32)mp->tls[0], &mp);
+ runtime·printf("newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+ stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
}
runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
- errno = runtime·bsdthread_create(stk, mp, gp, fn);
+ errno = runtime·bsdthread_create(stk, mp, mp->g0, runtime·mstart);
runtime·sigprocmask(SIG_SETMASK, &oset, nil);
if(errno < 0) {
diff --git a/src/pkg/runtime/thread_freebsd.c b/src/pkg/runtime/thread_freebsd.c
index aae52ea37..3ae14ee0a 100644
--- a/src/pkg/runtime/thread_freebsd.c
+++ b/src/pkg/runtime/thread_freebsd.c
@@ -77,18 +77,14 @@ runtime·futexwakeup(uint32 *addr, uint32 cnt)
void runtime·thr_start(void*);
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
ThrParam param;
Sigset oset;
- // thr_start assumes gp == mp->g0
- if(gp != mp->g0)
- runtime·throw("invalid newosproc gp");
-
if(0){
- runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, mp->id, (int32)mp->tls[0], &mp);
+ runtime·printf("newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+ stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
}
runtime·sigprocmask(&sigset_all, &oset);
@@ -96,15 +92,18 @@ runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
param.start_func = runtime·thr_start;
param.arg = (byte*)mp;
- param.stack_base = (void*)gp->stackbase;
- param.stack_size = (byte*)stk - (byte*)gp->stackbase;
+
+ // NOTE(rsc): This code is confused. stackbase is the top of the stack
+ // and is equal to stk. However, it's working, so I'm not changing it.
+ param.stack_base = (void*)mp->g0->stackbase;
+ param.stack_size = (byte*)stk - (byte*)mp->g0->stackbase;
+
param.child_tid = (intptr*)&mp->procid;
param.parent_tid = nil;
param.tls_base = (void*)&mp->tls[0];
param.tls_size = sizeof mp->tls;
mp->tls[0] = mp->id; // so 386 asm can find it
- mp->mstartfn = fn;
runtime·thr_new(&param, sizeof param);
runtime·sigprocmask(&oset, nil);
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/thread_linux.c
index 3f4505806..78ddef878 100644
--- a/src/pkg/runtime/thread_linux.c
+++ b/src/pkg/runtime/thread_linux.c
@@ -124,7 +124,7 @@ enum
};
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
int32 ret;
int32 flags;
@@ -142,14 +142,14 @@ runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
mp->tls[0] = mp->id; // so 386 asm can find it
if(0){
- runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, runtime·clone, mp->id, (int32)mp->tls[0], &mp);
+ runtime·printf("newosproc stk=%p m=%p g=%p clone=%p id=%d/%d ostk=%p\n",
+ stk, mp, mp->g0, runtime·clone, mp->id, (int32)mp->tls[0], &mp);
}
// Disable signals during clone, so that the new thread starts
// with signals disabled. It will enable them in minit.
runtime·rtsigprocmask(SIG_SETMASK, &sigset_all, &oset, sizeof oset);
- ret = runtime·clone(flags, stk, mp, gp, fn);
+ ret = runtime·clone(flags, stk, mp, mp->g0, runtime·mstart);
runtime·rtsigprocmask(SIG_SETMASK, &oset, nil, sizeof oset);
if(ret < 0) {
diff --git a/src/pkg/runtime/thread_netbsd.c b/src/pkg/runtime/thread_netbsd.c
index b9ec33acd..f333c6dd8 100644
--- a/src/pkg/runtime/thread_netbsd.c
+++ b/src/pkg/runtime/thread_netbsd.c
@@ -145,15 +145,15 @@ runtime·semawakeup(M *mp)
}
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
UcontextT uc;
int32 ret;
if(0) {
runtime·printf(
- "newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, mp->id, (int32)mp->tls[0], &mp);
+ "newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+ stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
}
mp->tls[0] = mp->id; // so 386 asm can find it
@@ -164,7 +164,7 @@ runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
uc.uc_link = nil;
uc.uc_sigmask = sigset_all;
- runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, gp, fn);
+ runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart);
ret = runtime·lwp_create(&uc, 0, &mp->procid);
diff --git a/src/pkg/runtime/thread_openbsd.c b/src/pkg/runtime/thread_openbsd.c
index f35c3bb44..9150efaa1 100644
--- a/src/pkg/runtime/thread_openbsd.c
+++ b/src/pkg/runtime/thread_openbsd.c
@@ -123,7 +123,7 @@ runtime·semawakeup(M *mp)
}
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
Tfork param;
Sigset oset;
@@ -132,7 +132,7 @@ runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
if(0) {
runtime·printf(
"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, mp->id, (int32)mp->tls[0], &mp);
+ stk, mp, mp->g0, fn, mp->id, (int32)mp->tls[0], &mp);
}
mp->tls[0] = mp->id; // so 386 asm can find it
@@ -142,7 +142,7 @@ runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
param.tf_stack = stk;
oset = runtime·sigprocmask(SIG_SETMASK, sigset_all);
- ret = runtime·tfork((byte*)&param, sizeof(param), mp, gp, fn);
+ ret = runtime·tfork((byte*)&param, sizeof(param), mp, mp->g0, runtime·mstart);
runtime·sigprocmask(SIG_SETMASK, oset);
if(ret < 0) {
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c
index 866b1e780..e1c7334cf 100644
--- a/src/pkg/runtime/thread_plan9.c
+++ b/src/pkg/runtime/thread_plan9.c
@@ -223,15 +223,15 @@ runtime·exit(int32 e)
}
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
mp->tls[0] = mp->id; // so 386 asm can find it
if(0){
runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
- stk, mp, gp, fn, runtime·rfork, mp->id, (int32)mp->tls[0], &mp);
+ stk, mp, mp->g0, fn, runtime·rfork, mp->id, (int32)mp->tls[0], &mp);
}
- if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, gp, fn) < 0)
+ if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, mp->g0, runtime·mstart) < 0)
runtime·throw("newosproc: rfork failed");
}
diff --git a/src/pkg/runtime/thread_windows.c b/src/pkg/runtime/thread_windows.c
index 06326c218..ae4e82e50 100644
--- a/src/pkg/runtime/thread_windows.c
+++ b/src/pkg/runtime/thread_windows.c
@@ -187,18 +187,12 @@ runtime·semacreate(void)
#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
void
-runtime·newosproc(M *mp, G *gp, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
{
void *thandle;
USED(stk);
- // assume gp == mp->g0
- if(gp != mp->g0)
- runtime·throw("invalid newosproc gp");
-
- mp->mstartfn = fn;
-
thandle = runtime·stdcall(runtime·CreateThread, 6,
nil, (uintptr)0x20000, runtime·tstart_stdcall, mp,
STACK_SIZE_PARAM_IS_A_RESERVATION, nil);