summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/platform
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-03-29 18:03:29 +0000
committergVisor bot <gvisor-bot@google.com>2021-03-29 18:03:29 +0000
commit6a422755602daeaef4be60969c1acddc8b7b3041 (patch)
tree5d27f2afe4fbe83ddb8bb612b0631e9c9d4da9d3 /pkg/sentry/platform
parent9cecf76d42ee48bf2314d3ce5aeb86a2029516cc (diff)
parentb125afba416ebeba906ea595a44a55afe4729d64 (diff)
Merge release-20210322.0-28-gb125afba4 (automated)
Diffstat (limited to 'pkg/sentry/platform')
-rw-r--r--pkg/sentry/platform/kvm/machine.go2
-rw-r--r--pkg/sentry/platform/ptrace/subprocess.go56
2 files changed, 35 insertions, 23 deletions
diff --git a/pkg/sentry/platform/kvm/machine.go b/pkg/sentry/platform/kvm/machine.go
index 0e4cf01e1..5d586f257 100644
--- a/pkg/sentry/platform/kvm/machine.go
+++ b/pkg/sentry/platform/kvm/machine.go
@@ -436,7 +436,7 @@ func (m *machine) Get() *vCPU {
}
// The vCPU is not be able to transition to
- // vCPUGuest|vCPUUser or to vCPUUser because that
+ // vCPUGuest|vCPUWaiter or to vCPUUser because that
// transition requires holding the machine mutex, as we
// do now. There is no path to register a waiter on
// just the vCPUReady state.
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
}