mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-21 15:29:27 +00:00
discover:add mutex and lock/unlock logics for revalidationList.nextTime
This commit is contained in:
parent
77dc1acafa
commit
a04615cbab
1 changed files with 17 additions and 0 deletions
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
|
|
@ -78,18 +79,29 @@ func (tr *tableRevalidation) nodeEndpointChanged(tab *Table, n *tableNode) {
|
||||||
// to schedule a timer. However, run can be called at any time.
|
// to schedule a timer. However, run can be called at any time.
|
||||||
func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) (nextTime mclock.AbsTime) {
|
func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) (nextTime mclock.AbsTime) {
|
||||||
reval := func(list *revalidationList) {
|
reval := func(list *revalidationList) {
|
||||||
|
// nextTime locked for reading, unlock in the end of function or before schedule to prevent deadlock
|
||||||
|
list.ntLock.RLock()
|
||||||
if list.nextTime <= now {
|
if list.nextTime <= now {
|
||||||
if n := list.get(&tab.rand, tr.activeReq); n != nil {
|
if n := list.get(&tab.rand, tr.activeReq); n != nil {
|
||||||
tr.startRequest(tab, n)
|
tr.startRequest(tab, n)
|
||||||
}
|
}
|
||||||
// Update nextTime regardless if any requests were started because
|
// Update nextTime regardless if any requests were started because
|
||||||
// current value has passed.
|
// current value has passed.
|
||||||
|
// unlock before schedule to prevent deadlock with write lock, return to prevent double unlock
|
||||||
|
list.ntLock.RUnlock()
|
||||||
list.schedule(now, &tab.rand)
|
list.schedule(now, &tab.rand)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
// in case of false if verification, unlock nextTime
|
||||||
|
list.ntLock.RUnlock()
|
||||||
}
|
}
|
||||||
reval(&tr.fast)
|
reval(&tr.fast)
|
||||||
reval(&tr.slow)
|
reval(&tr.slow)
|
||||||
|
|
||||||
|
tr.fast.ntLock.RLock()
|
||||||
|
tr.slow.ntLock.RLock()
|
||||||
|
defer tr.fast.ntLock.RUnlock()
|
||||||
|
defer tr.slow.ntLock.RUnlock()
|
||||||
return min(tr.fast.nextTime, tr.slow.nextTime)
|
return min(tr.fast.nextTime, tr.slow.nextTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,6 +210,7 @@ func (tr *tableRevalidation) moveToList(dest *revalidationList, n *tableNode, no
|
||||||
type revalidationList struct {
|
type revalidationList struct {
|
||||||
nodes []*tableNode
|
nodes []*tableNode
|
||||||
nextTime mclock.AbsTime
|
nextTime mclock.AbsTime
|
||||||
|
ntLock sync.RWMutex
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +231,8 @@ func (list *revalidationList) get(rand randomSource, exclude map[enode.ID]struct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *revalidationList) schedule(now mclock.AbsTime, rand randomSource) {
|
func (list *revalidationList) schedule(now mclock.AbsTime, rand randomSource) {
|
||||||
|
list.ntLock.Lock()
|
||||||
|
defer list.ntLock.Unlock()
|
||||||
list.nextTime = now.Add(time.Duration(rand.Int63n(int64(list.interval))))
|
list.nextTime = now.Add(time.Duration(rand.Int63n(int64(list.interval))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,6 +251,8 @@ func (list *revalidationList) remove(n *tableNode) {
|
||||||
}
|
}
|
||||||
list.nodes = slices.Delete(list.nodes, i, i+1)
|
list.nodes = slices.Delete(list.nodes, i, i+1)
|
||||||
if len(list.nodes) == 0 {
|
if len(list.nodes) == 0 {
|
||||||
|
list.ntLock.Lock()
|
||||||
|
defer list.ntLock.Unlock()
|
||||||
list.nextTime = never
|
list.nextTime = never
|
||||||
}
|
}
|
||||||
n.revalList = nil
|
n.revalList = nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue