2014-02-21 17:57:16

by Thomas Gleixner

[permalink] [raw]
Subject: [RFC patch 4/5] posix-timers: Expose deferrable mode to user space

Expose the deferrable timer mode to user space by adding a new
TIMER_IS_DEFERRABLE flag.

The deferrable mode is available for the syscalls clock_nanosleep()
and timer_settime(). For both syscalls TIMER_IS_DEFERRABLE is handed
in via the 'flags' argument. TIMER_ABSTIME and TIMER_IS_DEFERRABLE can
be ored together.

If a timer is started with this flag, the expiry of the timer is
relaxed. The timer is guaranteed to not expire before the given expiry
time, but the expiry can be delayed to the point where a non
deferrable timer expires. Deferred timers are not waking up a cpu from
a deep idle period.

Applications using the TIMER_IS_DEFERRABLE flag work on older kernels
as well, but the timers won't have the deferrable functionality.

Signed-off-by: Thomas Gleixner <[email protected]>
Cc: Michael Kerrisk <[email protected]>
---
include/uapi/linux/time.h | 4 ++++
kernel/posix-timers.c | 10 +++++++---
2 files changed, 11 insertions(+), 3 deletions(-)

Index: tip/include/uapi/linux/time.h
===================================================================
--- tip.orig/include/uapi/linux/time.h
+++ tip/include/uapi/linux/time.h
@@ -63,7 +63,11 @@ struct itimerval {

/*
* The various flags for setting POSIX.1b interval timers:
+ *
+ * We keep that in sync with the TFD_TIMER_ flags
*/
#define TIMER_ABSTIME 0x01
+/* Reserved for TFD_ONLY flag 0x02 */
+#define TIMER_IS_DEFERRABLE 0x04

#endif /* _UAPI_LINUX_TIME_H */
Index: tip/kernel/posix-timers.c
===================================================================
--- tip.orig/kernel/posix-timers.c
+++ tip/kernel/posix-timers.c
@@ -846,6 +846,7 @@ common_timer_set(struct k_itimer *timr,
return 0;

mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL;
+ mode |= flags & TIMER_DEFERRABLE ? HRTIMER_MODE_DEFERRABLE : 0;
hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
timr->it.real.timer.function = posix_timer_fn;

@@ -1079,9 +1080,12 @@ SYSCALL_DEFINE2(clock_getres, const cloc
static int common_nsleep(const clockid_t which_clock, int flags,
struct timespec *tsave, struct timespec __user *rmtp)
{
- return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
- HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
- which_clock);
+ enum hrtimer_mode mode;
+
+ mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL;
+ mode |= flags & TIMER_DEFERRABLE ? HRTIMER_MODE_DEFERRABLE : 0;
+
+ return hrtimer_nanosleep(tsave, rmtp, mode, which_clock);
}

SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,