From: Russ Cox Date: Thu, 29 Feb 2024 21:51:44 +0000 (-0500) Subject: runtime: introduce timers.lock, timers.unlock methods X-Git-Tag: go1.23rc1~945 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c961ab3fe9b0355320cde28a588a687dc0d5261f;p=gostls13.git runtime: introduce timers.lock, timers.unlock methods No semantic changes here. Cleaning up for next change. Change-Id: I9706009739677ff9eb893bcc007d805f7877511e Reviewed-on: https://go-review.googlesource.com/c/go/+/568335 Reviewed-by: Austin Clements Auto-Submit: Russ Cox Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI --- diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 33fdf864ff..a49a282bb7 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -5435,7 +5435,7 @@ func (pp *p) init(id int32) { pp.raceprocctx = raceproccreate() } } - lockInit(&pp.timers.lock, lockRankTimers) + lockInit(&pp.timers.mu, lockRankTimers) // This P may get timers when it starts running. Set the mask here // since the P may not go through pidleget (notably P 0 on startup). diff --git a/src/runtime/time.go b/src/runtime/time.go index 6db964ff07..cae3a3db47 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -54,9 +54,9 @@ type timer struct { // A timers is a per-P set of timers. type timers struct { - // lock protects timers; timers are per-P, but the scheduler can + // mu protects timers; timers are per-P, but the scheduler can // access the timers of another P, so we have to lock. - lock mutex + mu mutex // heap is the set of timers, ordered by t.when. // Must hold lock to access. @@ -84,6 +84,14 @@ type timers struct { minNextWhen atomic.Int64 } +func (ts *timers) lock() { + lock(&ts.mu) +} + +func (ts *timers) unlock() { + unlock(&ts.mu) +} + // Timer state field. // Note that state 0 must be "unlocked, not in heap" and usable, // at least for time.Timer.Stop. See go.dev/issue/21874. @@ -159,7 +167,7 @@ func (t *timer) unlock(state uint32, mp *m) { // temporarily not maintaining its invariant, such as during timers.adjust). func (t *timer) updateHeap(state uint32, ts *timers) (newState uint32, updated bool) { if ts != nil { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) } if state&timerZombie != 0 { // Take timer out of heap, applying final t.when update first. @@ -294,7 +302,7 @@ func goroutineReady(arg any, seq uintptr) { // Callers that are not sure can call t.maybeAdd instead, // but note that maybeAdd has different locking requirements. func (ts *timers) addHeap(t *timer) { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) // Timers rely on the network poller, so make sure the poller // has started. if netpollInited.Load() == 0 { @@ -343,7 +351,7 @@ func (t *timer) stop() bool { // deleteMin removes timer 0 from ts. // ts must be locked. func (ts *timers) deleteMin() { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) t := ts.heap[0] if t.ts != ts { throw("wrong timers") @@ -453,7 +461,7 @@ func (t *timer) needsAdd(state uint32) bool { // t is not in a heap on entry to t.maybeAdd. func (t *timer) maybeAdd() { ts := &getg().m.p.ptr().timers - lock(&ts.lock) + ts.lock() state, mp := t.lock() when := int64(0) if t.needsAdd(state) { @@ -462,7 +470,7 @@ func (t *timer) maybeAdd() { when = t.when } t.unlock(state, mp) - unlock(&ts.lock) + ts.unlock() if when > 0 { wakeNetPoller(when) } @@ -480,7 +488,7 @@ func (t *timer) reset(when int64) bool { // slows down heap operations. // The caller must have locked ts. func (ts *timers) cleanHead() { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) gp := getg() for { if len(ts.heap) == 0 { @@ -528,15 +536,15 @@ func (ts *timers) take(src *timers) { // protect against sysmon calling timeSleepUntil. // This is the only case where we hold more than one ts.lock, // so there are no deadlock concerns. - lock(&src.lock) - lock(&ts.lock) + src.lock() + ts.lock() ts.move(src.heap) src.heap = nil src.len.Store(0) src.zombies.Store(0) src.minWhen.Store(0) - unlock(&ts.lock) - unlock(&src.lock) + ts.unlock() + src.unlock() } } @@ -545,7 +553,7 @@ func (ts *timers) take(src *timers) { // This is currently called when the world is stopped, but the caller // is expected to have locked ts. func (ts *timers) move(timers []*timer) { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) for _, t := range timers { state, mp := t.lock() t.ts = nil @@ -563,7 +571,7 @@ func (ts *timers) move(timers []*timer) { // it also moves timers that have been modified to run later, // and removes deleted timers. The caller must have locked ts. func (ts *timers) adjust(now int64, force bool) { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) // If we haven't yet reached the time of the earliest modified // timer, don't do anything. This speeds up programs that adjust // a lot of timers back and forth if the timers rarely expire. @@ -720,7 +728,7 @@ func (ts *timers) check(now int64) (rnow, pollUntil int64, ran bool) { return now, next, false } - lock(&ts.lock) + ts.lock() if len(ts.heap) > 0 { ts.adjust(now, force) for len(ts.heap) > 0 { @@ -734,8 +742,7 @@ func (ts *timers) check(now int64) (rnow, pollUntil int64, ran bool) { ran = true } } - - unlock(&ts.lock) + ts.unlock() return now, pollUntil, ran } @@ -749,7 +756,7 @@ func (ts *timers) check(now int64) (rnow, pollUntil int64, ran bool) { // //go:systemstack func (ts *timers) run(now int64) int64 { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) Redo: if len(ts.heap) == 0 { return -1 @@ -784,7 +791,7 @@ Redo: } ts.unlockAndRun(t, now, state, mp) - assertLockHeld(&ts.lock) // t is unlocked now, but not ts + assertLockHeld(&ts.mu) // t is unlocked now, but not ts return 0 } @@ -794,7 +801,7 @@ Redo: // //go:systemstack func (ts *timers) unlockAndRun(t *timer, now int64, state uint32, mp *m) { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) if raceenabled { tsLocal := &getg().m.p.ptr().timers if tsLocal.raceCtx == 0 { @@ -843,9 +850,9 @@ func (ts *timers) unlockAndRun(t *timer, now int64, state uint32, mp *m) { gp.racectx = gp.m.p.ptr().timers.raceCtx } - unlock(&ts.lock) + ts.unlock() f(arg, seq) - lock(&ts.lock) + ts.lock() if raceenabled { gp := getg() @@ -886,18 +893,18 @@ func updateTimerPMask(pp *p) { // Looks like there are no timers, however another P // may be adding one at this very moment. // Take the lock to synchronize. - lock(&pp.timers.lock) + pp.timers.lock() if len(pp.timers.heap) == 0 { timerpMask.clear(pp.id) } - unlock(&pp.timers.lock) + pp.timers.unlock() } // verifyTimerHeap verifies that the timers is in a valid state. // This is only for debugging, and is only called if verifyTimers is true. // The caller must have locked ts. func (ts *timers) verify() { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) for i, t := range ts.heap { if i == 0 { // First timer has no parent. @@ -920,7 +927,7 @@ func (ts *timers) verify() { // updateMinWhen sets ts.minWhen to ts.heap[0].when. // The caller must have locked ts. func (ts *timers) updateMinWhen() { - assertLockHeld(&ts.lock) + assertLockHeld(&ts.mu) if len(ts.heap) == 0 { ts.minWhen.Store(0) } else {