summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/syscalls/linux
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2018-08-23 16:31:25 -0700
committerShentubot <shentubot@google.com>2018-08-23 16:32:36 -0700
commit64403265a04aa0c8be3ebb652a09f6e2d7a84ca7 (patch)
tree8191f06fca712de5588cd418a70707e9df0f2c25 /pkg/sentry/syscalls/linux
parente855e9cebc45f5fd7a9583f476c8965fc395a15e (diff)
Implement POSIX per-process interval timers.
PiperOrigin-RevId: 210021612 Change-Id: If7c161e6fd08cf17942bfb6bc5a8d2c4e271c61e
Diffstat (limited to 'pkg/sentry/syscalls/linux')
-rw-r--r--pkg/sentry/syscalls/linux/linux64.go10
-rw-r--r--pkg/sentry/syscalls/linux/sys_timer.go85
-rw-r--r--pkg/sentry/syscalls/linux/sys_timerfd.go33
3 files changed, 100 insertions, 28 deletions
diff --git a/pkg/sentry/syscalls/linux/linux64.go b/pkg/sentry/syscalls/linux/linux64.go
index c102af101..4465549ad 100644
--- a/pkg/sentry/syscalls/linux/linux64.go
+++ b/pkg/sentry/syscalls/linux/linux64.go
@@ -266,11 +266,11 @@ var AMD64 = &kernel.SyscallTable{
219: RestartSyscall,
// 220: Semtimedop, TODO
221: Fadvise64,
- // 222: TimerCreate, TODO
- // 223: TimerSettime, TODO
- // 224: TimerGettime, TODO
- // 225: TimerGetoverrun, TODO
- // 226: TimerDelete, TODO
+ 222: TimerCreate,
+ 223: TimerSettime,
+ 224: TimerGettime,
+ 225: TimerGetoverrun,
+ 226: TimerDelete,
227: ClockSettime,
228: ClockGettime,
229: ClockGetres,
diff --git a/pkg/sentry/syscalls/linux/sys_timer.go b/pkg/sentry/syscalls/linux/sys_timer.go
index 4ed077626..aaed75c81 100644
--- a/pkg/sentry/syscalls/linux/sys_timer.go
+++ b/pkg/sentry/syscalls/linux/sys_timer.go
@@ -166,3 +166,88 @@ func Alarm(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return uintptr(sec), nil, nil
}
+
+// TimerCreate implements linux syscall timer_create(2).
+func TimerCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ clockID := args[0].Int()
+ sevp := args[1].Pointer()
+ timerIDp := args[2].Pointer()
+
+ c, err := getClock(t, clockID)
+ if err != nil {
+ return 0, nil, err
+ }
+
+ var sev *linux.Sigevent
+ if sevp != 0 {
+ sev = &linux.Sigevent{}
+ if _, err = t.CopyIn(sevp, sev); err != nil {
+ return 0, nil, err
+ }
+ }
+
+ id, err := t.IntervalTimerCreate(c, sev)
+ if err != nil {
+ return 0, nil, err
+ }
+
+ if _, err := t.CopyOut(timerIDp, &id); err != nil {
+ t.IntervalTimerDelete(id)
+ return 0, nil, err
+ }
+
+ return uintptr(id), nil, nil
+}
+
+// TimerSettime implements linux syscall timer_settime(2).
+func TimerSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ timerID := linux.TimerID(args[0].Value)
+ flags := args[1].Int()
+ newValAddr := args[2].Pointer()
+ oldValAddr := args[3].Pointer()
+
+ var newVal linux.Itimerspec
+ if _, err := t.CopyIn(newValAddr, &newVal); err != nil {
+ return 0, nil, err
+ }
+ oldVal, err := t.IntervalTimerSettime(timerID, newVal, flags&linux.TIMER_ABSTIME != 0)
+ if err != nil {
+ return 0, nil, err
+ }
+ if oldValAddr != 0 {
+ if _, err := t.CopyOut(oldValAddr, &oldVal); err != nil {
+ return 0, nil, err
+ }
+ }
+ return 0, nil, nil
+}
+
+// TimerGettime implements linux syscall timer_gettime(2).
+func TimerGettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ timerID := linux.TimerID(args[0].Value)
+ curValAddr := args[1].Pointer()
+
+ curVal, err := t.IntervalTimerGettime(timerID)
+ if err != nil {
+ return 0, nil, err
+ }
+ _, err = t.CopyOut(curValAddr, &curVal)
+ return 0, nil, err
+}
+
+// TimerGetoverrun implements linux syscall timer_getoverrun(2).
+func TimerGetoverrun(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ timerID := linux.TimerID(args[0].Value)
+
+ o, err := t.IntervalTimerGetoverrun(timerID)
+ if err != nil {
+ return 0, nil, err
+ }
+ return uintptr(o), nil, nil
+}
+
+// TimerDelete implements linux syscall timer_delete(2).
+func TimerDelete(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ timerID := linux.TimerID(args[0].Value)
+ return 0, nil, t.IntervalTimerDelete(timerID)
+}
diff --git a/pkg/sentry/syscalls/linux/sys_timerfd.go b/pkg/sentry/syscalls/linux/sys_timerfd.go
index cb81d42b9..92c6a3d60 100644
--- a/pkg/sentry/syscalls/linux/sys_timerfd.go
+++ b/pkg/sentry/syscalls/linux/sys_timerfd.go
@@ -85,28 +85,18 @@ func TimerfdSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
if _, err := t.CopyIn(newValAddr, &newVal); err != nil {
return 0, nil, err
}
- var s ktime.Setting
- var err error
- if flags&linux.TFD_TIMER_ABSTIME != 0 {
- s, err = ktime.SettingFromAbsSpec(ktime.FromTimespec(newVal.Value),
- newVal.Interval.ToDuration())
- } else {
- s, err = ktime.SettingFromSpec(newVal.Value.ToDuration(),
- newVal.Interval.ToDuration(), tf.Clock())
- }
+ newS, err := ktime.SettingFromItimerspec(newVal, flags&linux.TFD_TIMER_ABSTIME != 0, tf.Clock())
if err != nil {
return 0, nil, err
}
- valueNS, intervalNS := ktime.SpecFromSetting(tf.SetTime(s))
- if oldValAddr == 0 {
- return 0, nil, nil
- }
- oldVal := linux.Itimerspec{
- Interval: linux.DurationToTimespec(intervalNS),
- Value: linux.DurationToTimespec(valueNS),
+ tm, oldS := tf.SetTime(newS)
+ if oldValAddr != 0 {
+ oldVal := ktime.ItimerspecFromSetting(tm, oldS)
+ if _, err := t.CopyOut(oldValAddr, &oldVal); err != nil {
+ return 0, nil, err
+ }
}
- _, err = t.CopyOut(oldValAddr, &oldVal)
- return 0, nil, err
+ return 0, nil, nil
}
// TimerfdGettime implements Linux syscall timerfd_gettime(2).
@@ -125,11 +115,8 @@ func TimerfdGettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
return 0, nil, syserror.EINVAL
}
- valueNS, intervalNS := ktime.SpecFromSetting(tf.GetTime())
- curVal := linux.Itimerspec{
- Interval: linux.DurationToTimespec(intervalNS),
- Value: linux.DurationToTimespec(valueNS),
- }
+ tm, s := tf.GetTime()
+ curVal := ktime.ItimerspecFromSetting(tm, s)
_, err := t.CopyOut(curValAddr, &curVal)
return 0, nil, err
}