aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc1.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/proc1.go')
-rw-r--r--src/runtime/proc1.go76
1 files changed, 56 insertions, 20 deletions
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
index 5e5d0efa0b..0ff3bafbdb 100644
--- a/src/runtime/proc1.go
+++ b/src/runtime/proc1.go
@@ -720,7 +720,7 @@ func mstart1() {
initsig()
}
- if _g_.m.mstartfn != nil {
+ if _g_.m.mstartfn != 0 {
fn := *(*func())(unsafe.Pointer(&_g_.m.mstartfn))
fn()
}
@@ -971,17 +971,22 @@ func unlockextra(mp *m) {
}
// Create a new m. It will start off with a call to fn, or else the scheduler.
+// fn needs to be static and not a heap allocated closure.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func newm(fn func(), _p_ *p) {
mp := allocm(_p_)
- mp.nextp = _p_
- mp.mstartfn = *(*unsafe.Pointer)(unsafe.Pointer(&fn))
-
+ // procresize made _p_ reachable through allp, which doesn't change during GC, so WB can be eliminated
+ setPNoWriteBarrier(&mp.nextp, _p_)
+ // Store &fn as a uintptr since it is not heap allocated so the WB can be eliminated
+ mp.mstartfn = *(*uintptr)(unsafe.Pointer(&fn))
if iscgo {
var ts cgothreadstart
if _cgo_thread_start == nil {
throw("_cgo_thread_start missing")
}
- ts.g = mp.g0
+ // mp is reachable via allm and mp.g0 never changes, so WB can be eliminated.
+ setGNoWriteBarrier(&ts.g, mp.g0)
ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
ts.fn = unsafe.Pointer(funcPC(mstart))
asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
@@ -1029,6 +1034,8 @@ func mspinning() {
// 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 does nothing.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func startm(_p_ *p, spinning bool) {
lock(&sched.lock)
if _p_ == nil {
@@ -1058,7 +1065,8 @@ func startm(_p_ *p, spinning bool) {
throw("startm: m has p")
}
mp.spinning = spinning
- mp.nextp = _p_
+ // procresize made _p_ reachable through allp, which doesn't change during GC, so WB can be eliminated
+ setPNoWriteBarrier(&mp.nextp, _p_)
notewakeup(&mp.park)
}
@@ -1139,6 +1147,8 @@ func stoplockedm() {
}
// Schedules the locked m to run the locked gp.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func startlockedm(gp *g) {
_g_ := getg()
@@ -1152,7 +1162,8 @@ func startlockedm(gp *g) {
// directly handoff current P to the locked m
incidlelocked(-1)
_p_ := releasep()
- mp.nextp = _p_
+ // procresize made _p_ reachable through allp, which doesn't change during GC, so WB can be eliminated
+ setPNoWriteBarrier(&mp.nextp, _p_)
notewakeup(&mp.park)
stopm()
}
@@ -1805,7 +1816,11 @@ func exitsyscall(dummy int32) {
for oldp != nil && oldp.syscalltick == _g_.m.syscalltick {
osyield()
}
- systemstack(traceGoSysExit)
+ // This can't be done since the GC may be running and this code
+ // will invoke write barriers.
+ // TODO: Figure out how to get traceGoSysExit into the trace log or
+ // it is likely not to work as expected.
+ // systemstack(traceGoSysExit)
}
_g_.m.locks--
@@ -2569,6 +2584,8 @@ func procresize(nprocs int32) *p {
}
// Associate p and the current m.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func acquirep(_p_ *p) {
_g_ := getg()
@@ -2583,9 +2600,12 @@ func acquirep(_p_ *p) {
print("acquirep: p->m=", _p_.m, "(", id, ") p->status=", _p_.status, "\n")
throw("acquirep: invalid p state")
}
- _g_.m.mcache = _p_.mcache
- _g_.m.p = _p_
- _p_.m = _g_.m
+ // _p_.mcache holds the mcache and _p_ is in allp, so WB can be eliminated
+ setMcacheNoWriteBarrier(&_g_.m.mcache, _p_.mcache)
+ // _p_ is in allp so WB can be eliminated
+ setPNoWriteBarrier(&_g_.m.p, _p_)
+ // m is in _g_.m and is reachable through allg, so WB can be eliminated
+ setMNoWriteBarrier(&_p_.m, _g_.m)
_p_.status = _Prunning
if trace.enabled {
@@ -2991,19 +3011,26 @@ func schedtrace(detailed bool) {
// Put mp on midle list.
// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func mput(mp *m) {
- mp.schedlink = sched.midle
- sched.midle = mp
+ // sched.midle is reachable via allm, so WB can be eliminated.
+ setMNoWriteBarrier(&mp.schedlink, sched.midle)
+ // mp is reachable via allm, so WB can be eliminated.
+ setMNoWriteBarrier(&sched.midle, mp)
sched.nmidle++
checkdead()
}
// Try to get an m from midle list.
// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func mget() *m {
mp := sched.midle
if mp != nil {
- sched.midle = mp.schedlink
+ // mp.schedlink is reachable via mp, which is on allm, so WB can be eliminated.
+ setMNoWriteBarrier(&sched.midle, mp.schedlink)
sched.nmidle--
}
return mp
@@ -3011,14 +3038,17 @@ func mget() *m {
// Put gp on the global runnable queue.
// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func globrunqput(gp *g) {
gp.schedlink = nil
if sched.runqtail != nil {
- sched.runqtail.schedlink = gp
+ // gp is on allg, so these three WBs can be eliminated.
+ setGNoWriteBarrier(&sched.runqtail.schedlink, gp)
} else {
- sched.runqhead = gp
+ setGNoWriteBarrier(&sched.runqhead, gp)
}
- sched.runqtail = gp
+ setGNoWriteBarrier(&sched.runqtail, gp)
sched.runqsize++
}
@@ -3071,18 +3101,24 @@ func globrunqget(_p_ *p, max int32) *g {
// Put p to on _Pidle list.
// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func pidleput(_p_ *p) {
- _p_.link = sched.pidle
- sched.pidle = _p_
+ // sched.pidle, _p_.link and _p_ are reachable via allp, so WB can be eliminated.
+ setPNoWriteBarrier(&_p_.link, sched.pidle)
+ setPNoWriteBarrier(&sched.pidle, _p_)
xadd(&sched.npidle, 1) // TODO: fast atomic
}
// Try get a p from _Pidle list.
// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
func pidleget() *p {
_p_ := sched.pidle
if _p_ != nil {
- sched.pidle = _p_.link
+ // _p_.link is reachable via a _p_ in allp, so WB can be eliminated.
+ setPNoWriteBarrier(&sched.pidle, _p_.link)
xadd(&sched.npidle, -1) // TODO: fast atomic
}
return _p_