summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/syscalls
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2018-10-17 15:48:55 -0700
committerShentubot <shentubot@google.com>2018-10-17 15:50:02 -0700
commitb2a88ff4713325fca736f6a3bf200be02d2d72a7 (patch)
tree489e54828c2bfe0bf326976920e5d5e612f877a0 /pkg/sentry/syscalls
parent6922eee6499212a009fdc254224f916bd1c46f29 (diff)
Check thread group CPU timers in the CPU clock ticker.
This reduces the number of goroutines and runtime timers when ITIMER_VIRTUAL or ITIMER_PROF are enabled, or when RLIMIT_CPU is set. This also ensures that thread group CPU timers only advance if running tasks are observed at the time the CPU clock advances, mostly eliminating the possibility that a CPU timer expiration observes no running tasks and falls back to the group leader. PiperOrigin-RevId: 217603396 Change-Id: Ia24ce934d5574334857d9afb5ad8ca0b6a6e65f4
Diffstat (limited to 'pkg/sentry/syscalls')
-rw-r--r--pkg/sentry/syscalls/linux/sys_rlimit.go2
-rw-r--r--pkg/sentry/syscalls/linux/sys_timer.go61
2 files changed, 13 insertions, 50 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_rlimit.go b/pkg/sentry/syscalls/linux/sys_rlimit.go
index 481e79eaa..d806b58ab 100644
--- a/pkg/sentry/syscalls/linux/sys_rlimit.go
+++ b/pkg/sentry/syscalls/linux/sys_rlimit.go
@@ -111,7 +111,7 @@ func prlimit64(t *kernel.Task, resource limits.LimitType, newLim *limits.Limit)
}
if resource == limits.CPU {
- t.ThreadGroup().SetCPUTimer(newLim)
+ t.NotifyRlimitCPUUpdated()
}
return oldLim, nil
}
diff --git a/pkg/sentry/syscalls/linux/sys_timer.go b/pkg/sentry/syscalls/linux/sys_timer.go
index a12d12d9d..c41074d54 100644
--- a/pkg/sentry/syscalls/linux/sys_timer.go
+++ b/pkg/sentry/syscalls/linux/sys_timer.go
@@ -21,7 +21,6 @@ import (
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/sentry/arch"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
- ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
)
@@ -70,34 +69,15 @@ func copyItimerValOut(t *kernel.Task, addr usermem.Addr, itv *linux.ItimerVal) e
}
}
-func findTimer(t *kernel.Task, which int32) (*ktime.Timer, error) {
- switch which {
- case linux.ITIMER_REAL:
- return t.ThreadGroup().Timer().RealTimer, nil
- case linux.ITIMER_VIRTUAL:
- return t.ThreadGroup().Timer().VirtualTimer, nil
- case linux.ITIMER_PROF:
- return t.ThreadGroup().Timer().ProfTimer, nil
- default:
- return nil, syscall.EINVAL
- }
-}
-
// Getitimer implements linux syscall getitimer(2).
func Getitimer(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
timerID := args[0].Int()
val := args[1].Pointer()
- timer, err := findTimer(t, timerID)
+ olditv, err := t.Getitimer(timerID)
if err != nil {
return 0, nil, err
}
- value, interval := ktime.SpecFromSetting(timer.Get())
- olditv := linux.ItimerVal{
- Value: linux.DurationToTimeval(value),
- Interval: linux.DurationToTimeval(interval),
- }
-
return 0, nil, copyItimerValOut(t, val, &olditv)
}
@@ -107,29 +87,14 @@ func Setitimer(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
newVal := args[1].Pointer()
oldVal := args[2].Pointer()
- timer, err := findTimer(t, timerID)
+ newitv, err := copyItimerValIn(t, newVal)
if err != nil {
return 0, nil, err
}
-
- itv, err := copyItimerValIn(t, newVal)
+ olditv, err := t.Setitimer(timerID, newitv)
if err != nil {
return 0, nil, err
}
- // Just like linux, we cap the timer value and interval with the max
- // number that int64 can represent which is roughly 292 years.
- s, err := ktime.SettingFromSpec(itv.Value.ToDuration(),
- itv.Interval.ToDuration(), timer.Clock())
- if err != nil {
- return 0, nil, err
- }
-
- valueNS, intervalNS := ktime.SpecFromSetting(timer.Swap(s))
- olditv := linux.ItimerVal{
- Value: linux.DurationToTimeval(valueNS),
- Interval: linux.DurationToTimeval(intervalNS),
- }
-
return 0, nil, copyItimerValOut(t, oldVal, &olditv)
}
@@ -137,21 +102,19 @@ func Setitimer(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
func Alarm(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
duration := time.Duration(args[0].Uint()) * time.Second
- timer := t.ThreadGroup().Timer().RealTimer
- s, err := ktime.SettingFromSpec(duration, 0, timer.Clock())
+ olditv, err := t.Setitimer(linux.ITIMER_REAL, linux.ItimerVal{
+ Value: linux.DurationToTimeval(duration),
+ })
if err != nil {
return 0, nil, err
}
-
- value, _ := ktime.SpecFromSetting(timer.Swap(s))
- sec := int64(value) / nsecPerSec
- nsec := int64(value) % nsecPerSec
- // We can't return 0 if we have an alarm pending ...
- if (sec == 0 && nsec > 0) || nsec >= nsecPerSec/2 {
- sec++
+ olddur := olditv.Value.ToDuration()
+ secs := olddur.Round(time.Second).Nanoseconds() / nsecPerSec
+ if secs == 0 && olddur != 0 {
+ // We can't return 0 if an alarm was previously scheduled.
+ secs = 1
}
-
- return uintptr(sec), nil, nil
+ return uintptr(secs), nil, nil
}
// TimerCreate implements linux syscall timer_create(2).