diff --git a/pkg/sentry/kernel/task_block.go b/pkg/sentry/kernel/task_block.go index d1bdbdb06..37c662d11 100644 --- a/pkg/sentry/kernel/task_block.go +++ b/pkg/sentry/kernel/task_block.go @@ -102,15 +102,23 @@ func (t *Task) BlockWithDeadline(C <-chan struct{}, haveDeadline bool, deadline return err } -// BlockWithTimer blocks t until an event is received from C or tchan, or t is -// interrupted. It returns nil if an event is received from C, ETIMEDOUT if an -// event is received from tchan, and linuxerr.ErrInterrupted if t is -// interrupted. +// BlockWithDeadlineFrom is similar to BlockWithDeadline, except it uses the +// passed clock (instead of application monotonic clock). // // Most clients should use BlockWithDeadline or BlockWithTimeout instead. // // Preconditions: The caller must be running on the task goroutine. -func (t *Task) BlockWithTimer(C <-chan struct{}, tchan <-chan struct{}) error { +func (t *Task) BlockWithDeadlineFrom(C <-chan struct{}, clock ktime.Clock, haveDeadline bool, deadline ktime.Time) error { + if !haveDeadline { + return t.block(C, nil) + } + notifier, tchan := ktime.NewChannelNotifier() + timer := ktime.NewTimer(clock, notifier) + timer.Swap(ktime.Setting{ + Enabled: true, + Next: deadline, + }) + defer timer.Destroy() return t.block(C, tchan) } diff --git a/pkg/sentry/syscalls/linux/sys_futex.go b/pkg/sentry/syscalls/linux/sys_futex.go index d89178bbd..bdff515c5 100644 --- a/pkg/sentry/syscalls/linux/sys_futex.go +++ b/pkg/sentry/syscalls/linux/sys_futex.go @@ -61,14 +61,7 @@ func futexWaitAbsolute(t *kernel.Task, clockRealtime bool, ts linux.Timespec, fo if forever { err = t.Block(w.C) } else if clockRealtime { - notifier, tchan := ktime.NewChannelNotifier() - timer := ktime.NewTimer(t.Kernel().RealtimeClock(), notifier) - timer.Swap(ktime.Setting{ - Enabled: true, - Next: ktime.FromTimespec(ts), - }) - err = t.BlockWithTimer(w.C, tchan) - timer.Destroy() + err = t.BlockWithDeadlineFrom(w.C, t.Kernel().RealtimeClock(), true, ktime.FromTimespec(ts)) } else { err = t.BlockWithDeadline(w.C, true, ktime.FromTimespec(ts)) } @@ -138,14 +131,7 @@ func futexLockPI(t *kernel.Task, ts linux.Timespec, forever bool, addr hostarch. if forever { err = t.Block(w.C) } else { - notifier, tchan := ktime.NewChannelNotifier() - timer := ktime.NewTimer(t.Kernel().RealtimeClock(), notifier) - timer.Swap(ktime.Setting{ - Enabled: true, - Next: ktime.FromTimespec(ts), - }) - err = t.BlockWithTimer(w.C, tchan) - timer.Destroy() + err = t.BlockWithDeadlineFrom(w.C, t.Kernel().RealtimeClock(), true, ktime.FromTimespec(ts)) } t.Futex().WaitComplete(w, t) diff --git a/pkg/sentry/syscalls/linux/sys_time.go b/pkg/sentry/syscalls/linux/sys_time.go index 8c2d5eafb..c59b7bf1a 100644 --- a/pkg/sentry/syscalls/linux/sys_time.go +++ b/pkg/sentry/syscalls/linux/sys_time.go @@ -245,15 +245,7 @@ func clockNanosleepUntil(t *kernel.Task, c ktime.Clock, end ktime.Time, rem host if c == t.Kernel().MonotonicClock() { err = t.BlockWithDeadline(nil, true, end) } else { - notifier, tchan := ktime.NewChannelNotifier() - timer := ktime.NewTimer(c, notifier) - timer.Swap(ktime.Setting{ - Period: 0, - Enabled: true, - Next: end, - }) - err = t.BlockWithTimer(nil, tchan) - timer.Destroy() + err = t.BlockWithDeadlineFrom(nil, c, true, end) } switch {