aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-03-25 15:59:22 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-03-25 15:44:47 +0000
commit77a8ddb5b3e19ad8aaf44ceaabf2427cc1963cb5 (patch)
tree4a3b3be1d0682fd4eaef20fe99f0b652d8677cec
parentcc1f7e7eff5c7f35b3f3c8f1f00e44fb03de74fb (diff)
syz-manager: take fuzzer out of the mutex
An atomic pointer is enough for our use cases. This should somewhat reduce the lock contention.
-rw-r--r--syz-manager/manager.go35
1 files changed, 17 insertions, 18 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index 26466ecfb..4a9392c20 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -73,7 +73,7 @@ type Manager struct {
dash *dashapi.Dashboard
mu sync.Mutex
- fuzzer *fuzzer.Fuzzer
+ fuzzer atomic.Pointer[fuzzer.Fuzzer]
phase int
targetEnabledSyscalls map[*prog.Syscall]bool
@@ -281,7 +281,7 @@ func (mgr *Manager) initBench() {
vals["corpus"] = uint64(stat.Progs)
vals["uptime"] = uint64(time.Since(mgr.firstConnect)) / 1e9
vals["fuzzing"] = uint64(mgr.fuzzingTime) / 1e9
- vals["candidates"] = uint64(mgr.fuzzer.Stats().Candidates)
+ vals["candidates"] = uint64(mgr.fuzzer.Load().Stats().Candidates)
mgr.mu.Unlock()
data, err := json.MarshalIndent(vals, "", " ")
@@ -674,7 +674,7 @@ func (mgr *Manager) loadCorpus() {
panic(fmt.Sprintf("loadCorpus: bad phase %v", mgr.phase))
}
mgr.phase = phaseLoadedCorpus
- mgr.fuzzer.AddCandidates(candidates)
+ mgr.fuzzer.Load().AddCandidates(candidates)
}
// Returns (delete item from the corpus, a fuzzer.Candidate object).
@@ -1247,15 +1247,14 @@ func (mgr *Manager) getMinimizedCorpus() (corpus, repros [][]byte) {
}
func (mgr *Manager) addNewCandidates(candidates []fuzzer.Candidate) {
- mgr.mu.Lock()
- defer mgr.mu.Unlock()
-
if mgr.cfg.Experimental.ResetAccState {
// Don't accept new candidates -- the execution is already very slow,
// syz-hub will just overwhelm us.
return
}
- mgr.fuzzer.AddCandidates(candidates)
+ mgr.fuzzer.Load().AddCandidates(candidates)
+ mgr.mu.Lock()
+ defer mgr.mu.Unlock()
if mgr.phase == phaseTriagedCorpus {
mgr.phase = phaseQueriedHub
}
@@ -1391,7 +1390,7 @@ func (mgr *Manager) machineChecked(a *rpctype.CheckArgs, enabledSyscalls map[*pr
for _, id := range a.EnabledCalls[mgr.cfg.Sandbox] {
calls[mgr.target.Syscalls[id]] = true
}
- mgr.fuzzer = fuzzer.NewFuzzer(context.Background(), &fuzzer.Config{
+ fuzzerObj := fuzzer.NewFuzzer(context.Background(), &fuzzer.Config{
Corpus: mgr.corpus,
Coverage: mgr.cfg.Cover,
FaultInjection: a.Features[host.FeatureFault].Enabled,
@@ -1412,19 +1411,19 @@ func (mgr *Manager) machineChecked(a *rpctype.CheckArgs, enabledSyscalls map[*pr
return !mgr.saturatedCalls[input.StringCall()]
},
}, rnd, mgr.target)
+ mgr.fuzzer.Store(fuzzerObj)
mgr.loadCorpus()
- go mgr.fuzzerLoop()
- go mgr.fuzzerSignalRotation()
+ go mgr.fuzzerLoop(fuzzerObj)
+ go mgr.fuzzerSignalRotation(fuzzerObj)
}
+// We need this method since we're not supposed to access Manager fields from RPCServer.
func (mgr *Manager) getFuzzer() *fuzzer.Fuzzer {
- mgr.mu.Lock()
- defer mgr.mu.Unlock()
- return mgr.fuzzer
+ return mgr.fuzzer.Load()
}
-func (mgr *Manager) fuzzerSignalRotation() {
+func (mgr *Manager) fuzzerSignalRotation(fuzzer *fuzzer.Fuzzer) {
const (
rotateSignals = 1000
timeBetweenRotates = 15 * time.Minute
@@ -1449,24 +1448,24 @@ func (mgr *Manager) fuzzerSignalRotation() {
if time.Since(lastRotation) < timeBetweenRotates {
continue
}
- mgr.fuzzer.RotateMaxSignal(rotateSignals)
+ fuzzer.RotateMaxSignal(rotateSignals)
lastRotation = time.Now()
lastExecTotal = mgr.stats.execTotal.get()
}
}
-func (mgr *Manager) fuzzerLoop() {
+func (mgr *Manager) fuzzerLoop(fuzzer *fuzzer.Fuzzer) {
for {
time.Sleep(time.Second / 2)
// Distribute new max signal over all instances.
- newSignal, dropSignal := mgr.fuzzer.Cover.GrabSignalDelta()
+ newSignal, dropSignal := fuzzer.Cover.GrabSignalDelta()
log.Logf(2, "distributing %d new signal, %d dropped signal",
len(newSignal), len(dropSignal))
mgr.serv.distributeSignalDelta(newSignal, dropSignal)
// Collect statistics.
- fuzzerStats := mgr.fuzzer.Stats()
+ fuzzerStats := fuzzer.Stats()
mgr.stats.setNamed(fuzzerStats.Named)
mgr.stats.corpusCover.set(fuzzerStats.Cover)
mgr.stats.corpusSignal.set(fuzzerStats.Signal)