From: KOSAKI Motohiro <kosaki.motoh...@jp.fujitsu.com> Currently glibc's rt/tst-cputimer1 testcase is spradically fail because a timer created by timer_create() may fire earlier than it's specified.
posix_cpu_timer_set() uses "val" as current time for three purpose. 1) initialize sig->cputimer. 2) calculation "old" val. 3) calculations an expires time. (1) and (2) should be used only committed time (i.e. without delta_exec) because run_posix_cpu_timers() don't care of delta_exec and we need consistency. But (3) need exact current time (aka cpu clock time) beucase an expires should be "now + timeout" by definition. This patch makes separete two kind of "now". Cc: Olivier Langlois <oliv...@trillion01.com> CC: Martin Schwidefsky <schwidef...@de.ibm.com> Cc: Steven Rostedt <rost...@goodmis.org> Cc: David Miller <da...@davemloft.net> Cc: Thomas Gleixner <t...@linutronix.de> Cc: Frederic Weisbecker <fweis...@gmail.com> Cc: Ingo Molnar <mi...@kernel.org> Cc: Peter Zijlstra <pet...@infradead.org> Signed-off-by: KOSAKI Motohiro <kosaki.motoh...@jp.fujitsu.com> --- include/linux/kernel_stat.h | 5 ----- kernel/posix-cpu-timers.c | 14 ++++++++++++-- kernel/sched/core.c | 13 ------------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index ed5f6ed..f5d4fdf 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -117,11 +117,6 @@ static inline unsigned int kstat_cpu_irqs_sum(unsigned int cpu) return kstat_cpu(cpu).irqs_sum; } -/* - * Lock/unlock the current runqueue - to extract task statistics: - */ -extern unsigned long long task_delta_exec(struct task_struct *); - extern void account_user_time(struct task_struct *, cputime_t, cputime_t); extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t); extern void account_steal_time(cputime_t); diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index e56be4c..98f354e 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -635,7 +635,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock, cpu->cpu = cputime.utime; break; case CPUCLOCK_SCHED: - cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p); + cpu->sched = cputime.sum_exec_runtime; break; } return 0; @@ -749,7 +749,17 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, } if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) { - cpu_time_add(timer->it_clock, &new_expires, val); + union cpu_time_count now; + + /* + * The expires is "now + timeout" by definition. So, + * we need exact current time. + */ + if (CPUCLOCK_PERTHREAD(timer->it_clock)) + now = val; + else + cpu_clock_sample_group(timer->it_clock, p, &now); + cpu_time_add(timer->it_clock, &new_expires, now); } /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ad3339f..b817e6d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2646,19 +2646,6 @@ static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) return ns; } -unsigned long long task_delta_exec(struct task_struct *p) -{ - unsigned long flags; - struct rq *rq; - u64 ns = 0; - - rq = task_rq_lock(p, &flags); - ns = do_task_delta_exec(p, rq); - task_rq_unlock(rq, p, &flags); - - return ns; -} - /* * Return accounted runtime for the task. * In case the task is currently running, return the runtime plus current's -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/