Use embedded mutex pattern

PiperOrigin-RevId: 375728461
This commit is contained in:
Tamir Duberstein
2021-05-25 09:55:45 -07:00
committed by gVisor bot
parent 38d158fe83
commit d55f3a6b5e
+30 -35
View File
@@ -323,26 +323,21 @@ type Rand interface {
type NUDState struct {
rng Rand
// mu protects the fields below.
//
// It is necessary for NUDState to handle its own locking since neighbor
// entries may access the NUD state from within the goroutine spawned by
// time.AfterFunc(). This goroutine may run concurrently with the main
// process for controlling the neighbor cache and would otherwise introduce
// race conditions if NUDState was not locked properly.
mu sync.RWMutex
mu struct {
sync.RWMutex
config NUDConfigurations
config NUDConfigurations
// reachableTime is the duration to wait for a REACHABLE entry to
// transition into STALE after inactivity. This value is calculated with
// the algorithm defined in RFC 4861 section 6.3.2.
reachableTime time.Duration
// reachableTime is the duration to wait for a REACHABLE entry to
// transition into STALE after inactivity. This value is calculated with
// the algorithm defined in RFC 4861 section 6.3.2.
reachableTime time.Duration
expiration time.Time
prevBaseReachableTime time.Duration
prevMinRandomFactor float32
prevMaxRandomFactor float32
expiration time.Time
prevBaseReachableTime time.Duration
prevMinRandomFactor float32
prevMaxRandomFactor float32
}
}
// NewNUDState returns new NUDState using c as configuration and the specified
@@ -351,7 +346,7 @@ func NewNUDState(c NUDConfigurations, rng Rand) *NUDState {
s := &NUDState{
rng: rng,
}
s.config = c
s.mu.config = c
return s
}
@@ -359,14 +354,14 @@ func NewNUDState(c NUDConfigurations, rng Rand) *NUDState {
func (s *NUDState) Config() NUDConfigurations {
s.mu.RLock()
defer s.mu.RUnlock()
return s.config
return s.mu.config
}
// SetConfig replaces the existing NUD configurations with c.
func (s *NUDState) SetConfig(c NUDConfigurations) {
s.mu.Lock()
defer s.mu.Unlock()
s.config = c
s.mu.config = c
}
// ReachableTime returns the duration to wait for a REACHABLE entry to
@@ -377,13 +372,13 @@ func (s *NUDState) ReachableTime() time.Duration {
s.mu.Lock()
defer s.mu.Unlock()
if time.Now().After(s.expiration) ||
s.config.BaseReachableTime != s.prevBaseReachableTime ||
s.config.MinRandomFactor != s.prevMinRandomFactor ||
s.config.MaxRandomFactor != s.prevMaxRandomFactor {
if time.Now().After(s.mu.expiration) ||
s.mu.config.BaseReachableTime != s.mu.prevBaseReachableTime ||
s.mu.config.MinRandomFactor != s.mu.prevMinRandomFactor ||
s.mu.config.MaxRandomFactor != s.mu.prevMaxRandomFactor {
s.recomputeReachableTimeLocked()
}
return s.reachableTime
return s.mu.reachableTime
}
// recomputeReachableTimeLocked forces a recalculation of ReachableTime using
@@ -408,23 +403,23 @@ func (s *NUDState) ReachableTime() time.Duration {
//
// s.mu MUST be locked for writing.
func (s *NUDState) recomputeReachableTimeLocked() {
s.prevBaseReachableTime = s.config.BaseReachableTime
s.prevMinRandomFactor = s.config.MinRandomFactor
s.prevMaxRandomFactor = s.config.MaxRandomFactor
s.mu.prevBaseReachableTime = s.mu.config.BaseReachableTime
s.mu.prevMinRandomFactor = s.mu.config.MinRandomFactor
s.mu.prevMaxRandomFactor = s.mu.config.MaxRandomFactor
randomFactor := s.config.MinRandomFactor + s.rng.Float32()*(s.config.MaxRandomFactor-s.config.MinRandomFactor)
randomFactor := s.mu.config.MinRandomFactor + s.rng.Float32()*(s.mu.config.MaxRandomFactor-s.mu.config.MinRandomFactor)
// Check for overflow, given that minRandomFactor and maxRandomFactor are
// guaranteed to be positive numbers.
if float32(math.MaxInt64)/randomFactor < float32(s.config.BaseReachableTime) {
s.reachableTime = time.Duration(math.MaxInt64)
if math.MaxInt64/randomFactor < float32(s.mu.config.BaseReachableTime) {
s.mu.reachableTime = time.Duration(math.MaxInt64)
} else if randomFactor == 1 {
// Avoid loss of precision when a large base reachable time is used.
s.reachableTime = s.config.BaseReachableTime
s.mu.reachableTime = s.mu.config.BaseReachableTime
} else {
reachableTime := int64(float32(s.config.BaseReachableTime) * randomFactor)
s.reachableTime = time.Duration(reachableTime)
reachableTime := int64(float32(s.mu.config.BaseReachableTime) * randomFactor)
s.mu.reachableTime = time.Duration(reachableTime)
}
s.expiration = time.Now().Add(2 * time.Hour)
s.mu.expiration = time.Now().Add(2 * time.Hour)
}