From 893fc6ef85e371839043ecc186ae25fa63ee624e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 29 Oct 2016 11:21:02 +1100 Subject: [PATCH 04/24] Create highres timeout variants of schedule_timeout functions. --- arch/x86/Kconfig | 12 ++++---- include/linux/freezer.h | 1 include/linux/sched.h | 31 +++++++++++++++++++- kernel/time/hrtimer.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 8 deletions(-) Index: linux-4.11-ck2/arch/x86/Kconfig =================================================================== --- linux-4.11-ck2.orig/arch/x86/Kconfig 2017-05-26 19:04:57.554243260 +1000 +++ linux-4.11-ck2/arch/x86/Kconfig 2017-05-26 19:04:57.544243330 +1000 @@ -1340,7 +1340,7 @@ config HIGHMEM64G endchoice choice - prompt "Memory split" + prompt "Memory split" if EXPERT default VMSPLIT_3G depends on X86_32 ---help--- @@ -1360,17 +1360,17 @@ choice option alone! config VMSPLIT_3G - bool "Default 896MB lowmem (3G/1G user/kernel split)" + bool "3G/1G user/kernel split" config VMSPLIT_3G_OPT depends on !X86_PAE - bool "1GB lowmem (3G/1G user/kernel split)" + bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G - bool "2GB lowmem (2G/2G user/kernel split)" + bool "2G/2G user/kernel split" config VMSPLIT_2G_OPT depends on !X86_PAE - bool "2GB lowmem (2G/2G user/kernel split)" + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G - bool "3GB lowmem (1G/3G user/kernel split)" + bool "1G/3G user/kernel split" endchoice config PAGE_OFFSET Index: linux-4.11-ck2/include/linux/freezer.h =================================================================== --- linux-4.11-ck2.orig/include/linux/freezer.h 2017-05-26 19:04:57.554243260 +1000 +++ linux-4.11-ck2/include/linux/freezer.h 2017-05-26 19:04:57.544243330 +1000 @@ -296,6 +296,7 @@ static inline void set_freezable(void) { #define wait_event_freezekillable_unsafe(wq, condition) \ wait_event_killable(wq, condition) +#define pm_freezing (false) #endif /* !CONFIG_FREEZER */ #endif /* FREEZER_H_INCLUDED */ Index: linux-4.11-ck2/include/linux/sched.h =================================================================== --- linux-4.11-ck2.orig/include/linux/sched.h 2017-05-26 19:04:57.554243260 +1000 +++ linux-4.11-ck2/include/linux/sched.h 2017-05-26 19:04:57.544243330 +1000 @@ -173,13 +173,40 @@ extern cpumask_var_t cpu_isolated_map; extern void scheduler_tick(void); -#define MAX_SCHEDULE_TIMEOUT LONG_MAX - +#define MAX_SCHEDULE_TIMEOUT LONG_MAX extern long schedule_timeout(long timeout); extern long schedule_timeout_interruptible(long timeout); extern long schedule_timeout_killable(long timeout); extern long schedule_timeout_uninterruptible(long timeout); extern long schedule_timeout_idle(long timeout); + +#ifdef CONFIG_HIGH_RES_TIMERS +extern long schedule_msec_hrtimeout(long timeout); +extern long schedule_min_hrtimeout(void); +extern long schedule_msec_hrtimeout_interruptible(long timeout); +extern long schedule_msec_hrtimeout_uninterruptible(long timeout); +#else +static inline long schedule_msec_hrtimeout(long timeout) +{ + return schedule_timeout(msecs_to_jiffies(timeout)); +} + +static inline long schedule_min_hrtimeout(void) +{ + return schedule_timeout(1); +} + +static inline long schedule_msec_hrtimeout_interruptible(long timeout) +{ + return schedule_timeout_interruptible(msecs_to_jiffies(timeout)); +} + +static inline long schedule_msec_hrtimeout_uninterruptible(long timeout) +{ + return schedule_timeout_uninterruptible(msecs_to_jiffies(timeout)); +} +#endif + asmlinkage void schedule(void); extern void schedule_preempt_disabled(void); Index: linux-4.11-ck2/kernel/time/hrtimer.c =================================================================== --- linux-4.11-ck2.orig/kernel/time/hrtimer.c 2017-05-26 19:04:57.554243260 +1000 +++ linux-4.11-ck2/kernel/time/hrtimer.c 2017-05-26 19:04:57.544243330 +1000 @@ -1770,3 +1770,74 @@ int __sched schedule_hrtimeout(ktime_t * return schedule_hrtimeout_range(expires, 0, mode); } EXPORT_SYMBOL_GPL(schedule_hrtimeout); + +/* + * As per schedule_hrtimeout but taskes a millisecond value and returns how + * many milliseconds are left. + */ +long __sched schedule_msec_hrtimeout(long timeout) +{ + struct hrtimer_sleeper t; + int delta, secs, jiffs; + ktime_t expires; + + if (!timeout) { + __set_current_state(TASK_RUNNING); + return 0; + } + + jiffs = msecs_to_jiffies(timeout); + /* + * If regular timer resolution is adequate or hrtimer resolution is not + * (yet) better than Hz, as would occur during startup, use regular + * timers. + */ + if (jiffs > 4 || hrtimer_resolution >= NSEC_PER_SEC / HZ) + return schedule_timeout(jiffs); + + secs = timeout / 1000; + delta = (timeout % 1000) * NSEC_PER_MSEC; + expires = ktime_set(secs, delta); + + hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_set_expires_range_ns(&t.timer, expires, delta); + + hrtimer_init_sleeper(&t, current); + + hrtimer_start_expires(&t.timer, HRTIMER_MODE_REL); + + if (likely(t.task)) + schedule(); + + hrtimer_cancel(&t.timer); + destroy_hrtimer_on_stack(&t.timer); + + __set_current_state(TASK_RUNNING); + + expires = hrtimer_expires_remaining(&t.timer); + timeout = ktime_to_ms(expires); + return timeout < 0 ? 0 : timeout; +} + +EXPORT_SYMBOL(schedule_msec_hrtimeout); + +long __sched schedule_min_hrtimeout(void) +{ + return schedule_msec_hrtimeout(1); +} + +EXPORT_SYMBOL(schedule_min_hrtimeout); + +long __sched schedule_msec_hrtimeout_interruptible(long timeout) +{ + __set_current_state(TASK_INTERRUPTIBLE); + return schedule_msec_hrtimeout(timeout); +} +EXPORT_SYMBOL(schedule_msec_hrtimeout_interruptible); + +long __sched schedule_msec_hrtimeout_uninterruptible(long timeout) +{ + __set_current_state(TASK_UNINTERRUPTIBLE); + return schedule_msec_hrtimeout(timeout); +} +EXPORT_SYMBOL(schedule_msec_hrtimeout_uninterruptible);