mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Don't sched_setaffinity in ptrace platform.
PiperOrigin-RevId: 330777900
This commit is contained in:
@@ -30,7 +30,6 @@ go_library(
|
||||
"//pkg/safecopy",
|
||||
"//pkg/seccomp",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/hostcpu",
|
||||
"//pkg/sentry/memmap",
|
||||
"//pkg/sentry/platform",
|
||||
"//pkg/sentry/platform/interrupt",
|
||||
|
||||
@@ -24,10 +24,9 @@ import (
|
||||
// SyscallFilters returns syscalls made exclusively by the ptrace platform.
|
||||
func (*PTrace) SyscallFilters() seccomp.SyscallRules {
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_GETCPU: {},
|
||||
unix.SYS_SCHED_SETAFFINITY: {},
|
||||
syscall.SYS_PTRACE: {},
|
||||
syscall.SYS_TGKILL: {},
|
||||
syscall.SYS_WAIT4: {},
|
||||
unix.SYS_GETCPU: {},
|
||||
syscall.SYS_PTRACE: {},
|
||||
syscall.SYS_TGKILL: {},
|
||||
syscall.SYS_WAIT4: {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,11 +518,6 @@ func (s *subprocess) switchToApp(c *context, ac arch.Context) bool {
|
||||
}
|
||||
defer c.interrupt.Disable()
|
||||
|
||||
// Ensure that the CPU set is bound appropriately; this makes the
|
||||
// emulation below several times faster, presumably by avoiding
|
||||
// interprocessor wakeups and by simplifying the schedule.
|
||||
t.bind()
|
||||
|
||||
// Set registers.
|
||||
if err := t.setRegs(regs); err != nil {
|
||||
panic(fmt.Sprintf("ptrace set regs (%+v) failed: %v", regs, err))
|
||||
|
||||
@@ -18,29 +18,12 @@
|
||||
package ptrace
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/sentry/hostcpu"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
// maskPool contains reusable CPU masks for setting affinity. Unfortunately,
|
||||
// runtime.NumCPU doesn't actually record the number of CPUs on the system, it
|
||||
// just records the number of CPUs available in the scheduler affinity set at
|
||||
// startup. This may a) change over time and b) gives a number far lower than
|
||||
// the maximum indexable CPU. To prevent lots of allocation in the hot path, we
|
||||
// use a pool to store large masks that we can reuse during bind.
|
||||
var maskPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
const maxCPUs = 1024 // Not a hard limit; see below.
|
||||
return make([]uintptr, maxCPUs/64)
|
||||
},
|
||||
}
|
||||
|
||||
// unmaskAllSignals unmasks all signals on the current thread.
|
||||
//
|
||||
//go:nosplit
|
||||
@@ -49,47 +32,3 @@ func unmaskAllSignals() syscall.Errno {
|
||||
_, _, errno := syscall.RawSyscall6(syscall.SYS_RT_SIGPROCMASK, linux.SIG_SETMASK, uintptr(unsafe.Pointer(&set)), 0, linux.SignalSetSize, 0, 0)
|
||||
return errno
|
||||
}
|
||||
|
||||
// setCPU sets the CPU affinity.
|
||||
func (t *thread) setCPU(cpu uint32) error {
|
||||
mask := maskPool.Get().([]uintptr)
|
||||
n := int(cpu / 64)
|
||||
v := uintptr(1 << uintptr(cpu%64))
|
||||
if n >= len(mask) {
|
||||
// See maskPool note above. We've actually exceeded the number
|
||||
// of available cores. Grow the mask and return it.
|
||||
mask = make([]uintptr, n+1)
|
||||
}
|
||||
mask[n] |= v
|
||||
if _, _, errno := syscall.RawSyscall(
|
||||
unix.SYS_SCHED_SETAFFINITY,
|
||||
uintptr(t.tid),
|
||||
uintptr(len(mask)*8),
|
||||
uintptr(unsafe.Pointer(&mask[0]))); errno != 0 {
|
||||
return errno
|
||||
}
|
||||
mask[n] &^= v
|
||||
maskPool.Put(mask)
|
||||
return nil
|
||||
}
|
||||
|
||||
// bind attempts to ensure that the thread is on the same CPU as the current
|
||||
// thread. This provides no guarantees as it is fundamentally a racy operation:
|
||||
// CPU sets may change and we may be rescheduled in the middle of this
|
||||
// operation. As a result, no failures are reported.
|
||||
//
|
||||
// Precondition: the current runtime thread should be locked.
|
||||
func (t *thread) bind() {
|
||||
currentCPU := hostcpu.GetCPU()
|
||||
|
||||
if oldCPU := atomic.SwapUint32(&t.cpu, currentCPU); oldCPU != currentCPU {
|
||||
// Set the affinity on the thread and save the CPU for next
|
||||
// round; we don't expect CPUs to bounce around too frequently.
|
||||
//
|
||||
// (It's worth noting that we could move CPUs between this point
|
||||
// and when the tracee finishes executing. But that would be
|
||||
// roughly the status quo anyways -- we're just maximizing our
|
||||
// chances of colocation, not guaranteeing it.)
|
||||
t.setCPU(currentCPU)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user