Timekeeping items for 4.11
Subsystems (6)
Hey Thomas, Ingo,
Just a few items I have queued for 4.11.
Let me know if you have any objections
thanks
-john
The following changes since commit 0c744ea4f77d72b3dcebb7a8f2684633ec79be88:
Linux 4.10-rc2 (2017-01-01 14:31:53 -0800)
are available in the git repository at:
https://git.linaro.org/people/john.stultz/linux.git fortglx/4.11/time
for you to fetch changes up to b18b6a9cef7f30e9a8b7738d5fc8d568cf660855:
timers: Omit POSIX timer stuff from task_struct when disabled (2017-01-27 13:05:26 -0800)
----------------------------------------------------------------
Nicolas Pitre (1):
timers: Omit POSIX timer stuff from task_struct when disabled
Russell King (1):
delay: Add explanation of udelay() inaccuracy
Stephen Boyd (1):
timekeeping: Remove unused timekeeping_{get,set}_tai_offset()
fs/proc/base.c | 4 ++-- include/linux/delay.h | 11 +++++++++++ include/linux/init_task.h | 40 +++++++++++++++++++++++++--------------- include/linux/sched.h | 13 ++++++++++--- kernel/fork.c | 10 +++++++++- kernel/sched/rt.c | 4 ++++ kernel/sched/stats.h | 32 ++++++++++++++++++++------------ kernel/time/timekeeping.c | 39 +-------------------------------------- kernel/time/timekeeping.h | 2 -- 9 files changed, 82 insertions(+), 73 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/3 timekeeping: Remove unused timekeeping_{get,set}_tai_offset()
From: Stephen Boyd <[email protected]>
The last caller to timekeeping_set_tai_offset() was in commit 0b5154fb9040 (timekeeping: Simplify tai updating from do_adjtimex, 2013-03-22) and the last caller to timekeeping_get_tai_offset() was in commit 76f4108892d9 (hrtimer:
Cleanup hrtimer accessors to the timekepeing state, 2014-07-16). Remove these unused functions now that we handle TAI offsets differently.
--- kernel/time/timekeeping.c | 39 +-------------------------------------- kernel/time/timekeeping.h | 2 -- 2 files changed, 1 insertion(+), 40 deletions(-)
kernel/time/timekeeping.c +1 -38
@@ -1275,27 +1275,8 @@ int timekeeping_inject_offset(struct timespec *ts) }EXPORT_SYMBOL (timekeeping_inject_offset); - -/** -* timekeeping_get_tai_offset - Returns current TAI offset from UTC -* -*/ -s32 timekeeping_get_tai_offset (void ) -{ -struct timekeeper *tk = &tk_core.timekeeper; -unsigned int seq; -s32 ret; - -do { - seq =read_seqcount_begin (&tk_core.seq); - ret = tk->tai_offset; - }while (read_seqcount_retry (&tk_core.seq, seq)); - -return ret; -} -/** -* __timekeeping_set_tai_offset - Lock free worker function +* __timekeeping_set_tai_offset - Sets the TAI offset from UTC and monotonic * */ static void __timekeeping_set_tai_offset (struct timekeeper *tk,s32 tai_offset)
@@ -1305,24 +1286,6 @@ static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) }/** -* timekeeping_set_tai_offset - Sets the current TAI offset from UTC -* -*/ -void timekeeping_set_tai_offset (s32 tai_offset) -{ -struct timekeeper *tk = &tk_core.timekeeper; -unsigned long flags; - -raw_spin_lock_irqsave (&timekeeper_lock, flags); -write_seqcount_begin (&tk_core.seq); -__timekeeping_set_tai_offset (tk, tai_offset); -timekeeping_update (tk,TK_MIRROR |TK_CLOCK_WAS_SET ); -write_seqcount_end (&tk_core.seq); -raw_spin_unlock_irqrestore (&timekeeper_lock, flags); -clock_was_set (); -} - -/** * change_clocksource - Swaps clocksources if a new one is available * * Accumulates current time interval and initializes new clocksource
kernel/time/timekeeping.h +0 -2
@@ -11,8 +11,6 @@ extern ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq,extern int timekeeping_valid_for_hres (void );extern u64 timekeeping_max_deferment (void );extern int timekeeping_inject_offset (struct timespec *ts); -extern s32 timekeeping_get_tai_offset (void ); -extern void timekeeping_set_tai_offset (s32 tai_offset);extern int timekeeping_suspend (void );extern void timekeeping_resume (void );
Signature · 1 line
2.7.4
PATCH 2/3 delay: Add explanation of udelay() inaccuracy
In reply to John StultzFrom: Russell King <[email protected]>
There seems to be some misunderstanding that udelay() and friends will always guarantee the specified delay. This is a false understanding. When udelay() is based on CPU cycles, it can return early for many reasons which are detailed by Linus' reply to me in a thread in 2011:
http://lists.openwall.net/linux-kernel/2011/01/12/372
However, a udelay test module was created in 2014 which allows udelay() to only be 0.5% fast, which is outside of the CPU-cycles udelay() results I measured back in 2011, which were deemed to be in the "we don't care" region.
test_udelay() should be fixed to reflect the real allowable tolerance on udelay(), rather than 0.5%.
--- include/linux/delay.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
include/linux/delay.h +11 -0
@@ -5,6 +5,17 @@* Copyright (C) 1993 Linus Torvalds * * Delay routines, using a pre-computed "loops_per_jiffy" value. +* +* Please note that ndelay(), udelay() and mdelay() may return early for +* several reasons: +* 1. computed loops_per_jiffy too low (due to the time taken to +* execute the timer interrupt.) +* 2. cache behaviour affecting the time it takes to execute the +* loop function. +* 3. CPU clock rate changes. +* +* Please see this thread: +* http://lists.openwall.net/linux-kernel/2011/01/09/56 */ #include <linux/kernel.h>
Signature · 1 line
2.7.4
PATCH 3/3 timers: Omit POSIX timer stuff from task_struct when disabled
In reply to John StultzFrom: Nicolas Pitre <[email protected]>
When CONFIG_POSIX_TIMERS is disabled, it is preferable to remove related structures from struct task_struct and struct signal_struct as they won't contain anything useful and shouldn't be relied upon by mistake. Code still referencing those structures is also disabled here.
--- fs/proc/base.c | 4 ++-- include/linux/init_task.h | 40 +++++++++++++++++++++++++--------------- include/linux/sched.h | 13 ++++++++++--- kernel/fork.c | 10 +++++++++- kernel/sched/rt.c | 4 ++++ kernel/sched/stats.h | 32 ++++++++++++++++++++------------ 6 files changed, 70 insertions(+), 33 deletions(-)
fs/proc/base.c +2 -2
@@ -2179,7 +2179,7 @@ static const struct file_operations proc_map_files_operations = { .llseek = generic_file_llseek, }; -#ifdef CONFIG_CHECKPOINT_RESTORE +#if defined(CONFIG_CHECKPOINT_RESTORE) && defined(CONFIG_POSIX_TIMERS) struct timers_private { struct pid *pid; struct task_struct *task;
@@ -2936,7 +2936,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),#endif -#ifdef CONFIG_CHECKPOINT_RESTORE +#if defined(CONFIG_CHECKPOINT_RESTORE ) && defined(CONFIG_POSIX_TIMERS )REG ("timers" ,S_IRUGO , proc_timers_operations), #endif REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations),
include/linux/init_task.h +25 -15
@@ -42,6 +42,27 @@ extern struct fs_struct init_fs;#define INIT_PREV_CPUTIME (x)#endif +#ifdef CONFIG_POSIX_TIMERS +#define INIT_POSIX_TIMERS (s) \ + .posix_timers = LIST_HEAD_INIT(s.posix_timers), +#define INIT_CPU_TIMERS (s) \ + .cpu_timers = { \ + LIST_HEAD_INIT(s.cpu_timers[0]), \ + LIST_HEAD_INIT(s.cpu_timers[1]), \ + LIST_HEAD_INIT(s.cpu_timers[2]), \ + }, +#define INIT_CPUTIMER (s) \ + .cputimer = { \ + .cputime_atomic = INIT_CPUTIME_ATOMIC, \ + .running = false, \ + .checking_timer = false, \ + }, +#else +#define INIT_POSIX_TIMERS (s) +#define INIT_CPU_TIMERS (s) +#define INIT_CPUTIMER (s) +#endif +#define INIT_SIGNALS (sig) { \ .nr_threads = 1, \ .thread_head = LIST_HEAD_INIT(init_task.thread_node), \
@@ -49,14 +70,10 @@ extern struct fs_struct init_fs; .shared_pending = { \ .list = LIST_HEAD_INIT(sig.shared_pending.list), \ .signal = {{0}}}, \ - .posix_timers = LIST_HEAD_INIT(sig.posix_timers), \ - .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \ + INIT_POSIX_TIMERS(sig) \ + INIT_CPU_TIMERS(sig) \ .rlim = INIT_RLIMITS, \ - .cputimer = { \ - .cputime_atomic = INIT_CPUTIME_ATOMIC, \ - .running = false, \ - .checking_timer = false, \ - }, \ + INIT_CPUTIMER(sig) \ INIT_PREV_CPUTIME(sig) \ .cred_guard_mutex = \ __MUTEX_INITIALIZER(sig.cred_guard_mutex), \
@@ -247,7 +264,7 @@ extern struct task_group root_task_group; .blocked = {{0}}, \ .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock), \ .journal_info =NULL , \ - .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ +INIT_CPU_TIMERS (tsk) \ .pi_lock =__RAW_SPIN_LOCK_UNLOCKED (tsk.pi_lock), \ .timer_slack_ns = 50000, /* 50 usec default slack */ \ .pids = { \
@@ -274,13 +291,6 @@ extern struct task_group root_task_group; } -#define INIT_CPU_TIMERS (cpu_timers) \ -{ \ - LIST_HEAD_INIT(cpu_timers[0]), \ - LIST_HEAD_INIT(cpu_timers[1]), \ - LIST_HEAD_INIT(cpu_timers[2]), \ -} -/* Attach to the init_task data structure for proper alignment */ #define __init_task_data __attribute__((__section__(".data..init_task")))
include/linux/sched.h +10 -3
@@ -734,13 +734,14 @@ struct signal_struct { unsigned int is_child_subreaper:1; unsigned int has_child_subreaper:1; +#ifdef CONFIG_POSIX_TIMERS +/* POSIX.1b Interval Timers */ int posix_timer_id;struct list_head posix_timers;/* ITIMER_REAL timer for the process */ struct hrtimer real_timer; -struct pid *leader_pid;ktime_t it_real_incr;/*
@@ -759,12 +760,16 @@ struct signal_struct {/* Earliest-expiration cache. */ struct task_cputime cputime_expires; +struct list_head cpu_timers[3 ]; + +#endif + +struct pid *leader_pid; +#ifdef CONFIG_NO_HZ_FULL atomic_t tick_dep_mask;#endif -struct list_head cpu_timers[3 ]; -struct pid *tty_old_pgrp;/* boolean value for session group leader */
@@ -1681,8 +1686,10 @@ struct task_struct {/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt; +#ifdef CONFIG_POSIX_TIMERS struct task_cputime cputime_expires;struct list_head cpu_timers[3 ]; +#endif /* process credentials */ const struct cred __rcu *ptracer_cred;/* Tracer's credentials at attach */
kernel/fork.c +9 -1
@@ -1304,6 +1304,7 @@ void __cleanup_sighand(struct sighand_struct *sighand) } } +#ifdef CONFIG_POSIX_TIMERS /* * Initialize POSIX timer handling for a thread group. */
@@ -1322,6 +1323,9 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)INIT_LIST_HEAD (&sig->cpu_timers[1 ]); INIT_LIST_HEAD(&sig->cpu_timers[2]); } +#else +static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { } +#endif static int copy_signal (unsigned long clone_flags,struct task_struct *tsk) {
@@ -1346,11 +1350,11 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)init_waitqueue_head (&sig->wait_chldexit); sig->curr_target = tsk;init_sigpending (&sig->shared_pending); -INIT_LIST_HEAD (&sig->posix_timers);seqlock_init (&sig->stats_lock);prev_cputime_init (&sig->prev_cputime);#ifdef CONFIG_POSIX_TIMERS +INIT_LIST_HEAD (&sig->posix_timers);hrtimer_init (&sig->real_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL ); sig->real_timer.function = it_real_fn;#endif
@@ -1425,6 +1429,7 @@ static void rt_mutex_init_task(struct task_struct *p)#endif } +#ifdef CONFIG_POSIX_TIMERS /* * Initialize POSIX timer handling for a single task. */
@@ -1437,6 +1442,9 @@ static void posix_cpu_timers_init(struct task_struct *tsk)INIT_LIST_HEAD (&tsk->cpu_timers[1 ]); INIT_LIST_HEAD(&tsk->cpu_timers[2]); } +#else +static inline void posix_cpu_timers_init (struct task_struct *tsk) { } +#endif static inline void init_task_pid (struct task_struct *task,enum pid_type type,struct pid *pid)
kernel/sched/rt.c +4 -0
@@ -2246,6 +2246,7 @@ prio_changed_rt(struct rq *rq, struct task_struct *p, int oldprio) } } +#ifdef CONFIG_POSIX_TIMERS static void watchdog (struct rq *rq,struct task_struct *p) {unsigned long soft, hard;
@@ -2267,6 +2268,9 @@ static void watchdog(struct rq *rq, struct task_struct *p) p->cputime_expires.sched_exp = p->se.sum_exec_runtime; } } +#else +static inline void watchdog (struct rq *rq,struct task_struct *p) { } +#endif static void task_tick_rt (struct rq *rq,struct task_struct *p,int queued) {
kernel/sched/stats.h +20 -12
@@ -172,18 +172,19 @@ sched_info_switch(struct rq *rq,*/ /** -* cputimer_running - return true if cputimer is running +* get_running_cputimer - return &tsk->signal->cputimer if cputimer is running * * @tsk: Pointer to target task. */ -static inline bool cputimer_running (struct task_struct *tsk) - +#ifdef CONFIG_POSIX_TIMERS +static inline +struct thread_group_cputimer *get_running_cputimer (struct task_struct *tsk) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;/* Check if cputimer isn't running. This is accessed without locking. */ if (!READ_ONCE (cputimer->running)) -return false; +return NULL ;/* * After we flush the task's sum_exec_runtime to sig->sum_sched_runtime
@@ -200,10 +201,17 @@ static inline bool cputimer_running(struct task_struct *tsk)* clock delta is behind the expiring timer value. */ if (unlikely (!tsk->sighand)) -return false; +return NULL ; -return true; + return cputimer; +} +#else +static inline +struct thread_group_cputimer *get_running_cputimer (struct task_struct *tsk) +{ +return NULL ; } +#endif /** * account_group_user_time - Maintain utime for a thread group.
@@ -218,9 +226,9 @@ static inline bool cputimer_running(struct task_struct *tsk)static inline void account_group_user_time (struct task_struct *tsk,cputime_t cputime) { -struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; +struct thread_group_cputimer *cputimer =get_running_cputimer (tsk); -if (!cputimer_running (tsk)) +if (!cputimer)return ;atomic64_add (cputime, &cputimer->cputime_atomic.utime);
@@ -239,9 +247,9 @@ static inline void account_group_user_time(struct task_struct *tsk,static inline void account_group_system_time (struct task_struct *tsk,cputime_t cputime) { -struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; +struct thread_group_cputimer *cputimer =get_running_cputimer (tsk); -if (!cputimer_running (tsk)) +if (!cputimer)return ;atomic64_add (cputime, &cputimer->cputime_atomic.stime);
@@ -260,9 +268,9 @@ static inline void account_group_system_time(struct task_struct *tsk,static inline void account_group_exec_runtime (struct task_struct *tsk,unsigned long long ns) { -struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; +struct thread_group_cputimer *cputimer =get_running_cputimer (tsk); -if (!cputimer_running (tsk)) +if (!cputimer)return ;atomic64_add (ns, &cputimer->cputime_atomic.sum_exec_runtime);
Signature · 1 line
2.7.4