diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-03-29 18:03:29 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-03-29 18:03:29 +0000 |
commit | 6a422755602daeaef4be60969c1acddc8b7b3041 (patch) | |
tree | 5d27f2afe4fbe83ddb8bb612b0631e9c9d4da9d3 /pkg/sentry/platform/ptrace | |
parent | 9cecf76d42ee48bf2314d3ce5aeb86a2029516cc (diff) | |
parent | b125afba416ebeba906ea595a44a55afe4729d64 (diff) |
Merge release-20210322.0-28-gb125afba4 (automated)
Diffstat (limited to 'pkg/sentry/platform/ptrace')
-rw-r--r-- | pkg/sentry/platform/ptrace/subprocess.go | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/pkg/sentry/platform/ptrace/subprocess.go b/pkg/sentry/platform/ptrace/subprocess.go index acccbfe2e..d2284487a 100644 --- a/pkg/sentry/platform/ptrace/subprocess.go +++ b/pkg/sentry/platform/ptrace/subprocess.go @@ -69,7 +69,7 @@ type thread struct { // threadPool is a collection of threads. type threadPool struct { // mu protects below. - mu sync.Mutex + mu sync.RWMutex // threads is the collection of threads. // @@ -85,30 +85,42 @@ type threadPool struct { // // Precondition: the runtime OS thread must be locked. func (tp *threadPool) lookupOrCreate(currentTID int32, newThread func() *thread) *thread { - tp.mu.Lock() + // The overwhelming common case is that the thread is already created. + // Optimistically attempt the lookup by only locking for reading. + tp.mu.RLock() t, ok := tp.threads[currentTID] - if !ok { - // Before creating a new thread, see if we can find a thread - // whose system tid has disappeared. - // - // TODO(b/77216482): Other parts of this package depend on - // threads never exiting. - for origTID, t := range tp.threads { - // Signal zero is an easy existence check. - if err := unix.Tgkill(unix.Getpid(), int(origTID), 0); err != nil { - // This thread has been abandoned; reuse it. - delete(tp.threads, origTID) - tp.threads[currentTID] = t - tp.mu.Unlock() - return t - } - } + tp.mu.RUnlock() + if ok { + return t + } - // Create a new thread. - t = newThread() - tp.threads[currentTID] = t + tp.mu.Lock() + defer tp.mu.Unlock() + + // Another goroutine might have created the thread for currentTID in between + // mu.RUnlock() and mu.Lock(). + if t, ok = tp.threads[currentTID]; ok { + return t + } + + // Before creating a new thread, see if we can find a thread + // whose system tid has disappeared. + // + // TODO(b/77216482): Other parts of this package depend on + // threads never exiting. + for origTID, t := range tp.threads { + // Signal zero is an easy existence check. + if err := unix.Tgkill(unix.Getpid(), int(origTID), 0); err != nil { + // This thread has been abandoned; reuse it. + delete(tp.threads, origTID) + tp.threads[currentTID] = t + return t + } } - tp.mu.Unlock() + + // Create a new thread. + t = newThread() + tp.threads[currentTID] = t return t } |