github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/subsystem/linux/path_coincidence.go (about) 1 // Copyright 2023 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package linux 5 6 import ( 7 "io/fs" 8 "regexp" 9 "runtime" 10 "sync" 11 12 "github.com/google/syzkaller/pkg/subsystem" 13 ) 14 15 func BuildCoincidenceMatrix(root fs.FS, list []*subsystem.Subsystem, 16 excludeRe *regexp.Regexp) (*CoincidenceMatrix, error) { 17 // Create a matcher. 18 matcher := subsystem.MakePathMatcher(list) 19 chPaths, chResult := extractSubsystems(matcher) 20 // The final consumer goroutine. 21 cm := MakeCoincidenceMatrix() 22 ready := make(chan struct{}) 23 go func() { 24 for items := range chResult { 25 cm.Record(items...) 26 } 27 ready <- struct{}{} 28 }() 29 // Source of data. 30 err := fs.WalkDir(root, ".", func(path string, info fs.DirEntry, err error) error { 31 if err != nil || info.IsDir() { 32 return err 33 } 34 if !includePathRe.MatchString(path) || 35 (excludeRe != nil && excludeRe.MatchString(path)) { 36 return nil 37 } 38 chPaths <- path 39 return nil 40 }) 41 close(chPaths) 42 <-ready 43 return cm, err 44 } 45 46 var ( 47 includePathRe = regexp.MustCompile(`(?:/|\.(?:c|h|S))$`) 48 ) 49 50 func extractSubsystems(matcher *subsystem.PathMatcher) (chan<- string, <-chan []*subsystem.Subsystem) { 51 procs := runtime.NumCPU() 52 paths, output := make(chan string, procs), make(chan []*subsystem.Subsystem, procs) 53 var wg sync.WaitGroup 54 for i := 0; i < procs; i++ { 55 wg.Add(1) 56 go func() { 57 defer wg.Done() 58 for path := range paths { 59 output <- matcher.Match(path) 60 } 61 }() 62 } 63 go func() { 64 wg.Wait() 65 close(output) 66 }() 67 return paths, output 68 }