aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-02-10 10:37:31 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-11 08:04:19 -0500
commit3fccfd67df79c6351a156eb25a7a514e5f39c4d9 (patch)
treede4776e69e197119ac64097f3ff6239a55ad77be
parentff08f76d738d0ec0f334b187f61e160caa321d54 (diff)
timers: split process wide cpu clocks/timers, fix
To decrease the chance of a missed enable, always enable the timer when we sample it, we'll always disable it when we find that there are no active timers in the jiffy tick. This fixes a flood of warnings reported by Mike Galbraith. Reported-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/posix-cpu-timers.c42
2 files changed, 15 insertions, 28 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 79392916d6c9..5d10fa0b6002 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2209,6 +2209,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
2209 unsigned long flags; 2209 unsigned long flags;
2210 2210
2211 spin_lock_irqsave(&cputimer->lock, flags); 2211 spin_lock_irqsave(&cputimer->lock, flags);
2212 cputimer->running = 1;
2212 *times = cputimer->cputime; 2213 *times = cputimer->cputime;
2213 spin_unlock_irqrestore(&cputimer->lock, flags); 2214 spin_unlock_irqrestore(&cputimer->lock, flags);
2214} 2215}
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index db107c9bbc05..e5d7bfdfa7d4 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -488,7 +488,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
488{ 488{
489 struct task_cputime cputime; 489 struct task_cputime cputime;
490 490
491 thread_group_cputime(tsk, &cputime); 491 thread_group_cputimer(tsk, &cputime);
492 cleanup_timers(tsk->signal->cpu_timers, 492 cleanup_timers(tsk->signal->cpu_timers,
493 cputime.utime, cputime.stime, cputime.sum_exec_runtime); 493 cputime.utime, cputime.stime, cputime.sum_exec_runtime);
494} 494}
@@ -507,29 +507,6 @@ static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
507} 507}
508 508
509/* 509/*
510 * Enable the process wide cpu timer accounting.
511 *
512 * serialized using ->sighand->siglock
513 */
514static void start_process_timers(struct task_struct *tsk)
515{
516 tsk->signal->cputimer.running = 1;
517 barrier();
518}
519
520/*
521 * Release the process wide timer accounting -- timer stops ticking when
522 * nobody cares about it.
523 *
524 * serialized using ->sighand->siglock
525 */
526static void stop_process_timers(struct task_struct *tsk)
527{
528 tsk->signal->cputimer.running = 0;
529 barrier();
530}
531
532/*
533 * Insert the timer on the appropriate list before any timers that 510 * Insert the timer on the appropriate list before any timers that
534 * expire later. This must be called with the tasklist_lock held 511 * expire later. This must be called with the tasklist_lock held
535 * for reading, and interrupts disabled. 512 * for reading, and interrupts disabled.
@@ -549,9 +526,6 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
549 BUG_ON(!irqs_disabled()); 526 BUG_ON(!irqs_disabled());
550 spin_lock(&p->sighand->siglock); 527 spin_lock(&p->sighand->siglock);
551 528
552 if (!CPUCLOCK_PERTHREAD(timer->it_clock))
553 start_process_timers(p);
554
555 listpos = head; 529 listpos = head;
556 if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) { 530 if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
557 list_for_each_entry(next, head, entry) { 531 list_for_each_entry(next, head, entry) {
@@ -1021,6 +995,19 @@ static void check_thread_timers(struct task_struct *tsk,
1021 } 995 }
1022} 996}
1023 997
998static void stop_process_timers(struct task_struct *tsk)
999{
1000 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
1001 unsigned long flags;
1002
1003 if (!cputimer->running)
1004 return;
1005
1006 spin_lock_irqsave(&cputimer->lock, flags);
1007 cputimer->running = 0;
1008 spin_unlock_irqrestore(&cputimer->lock, flags);
1009}
1010
1024/* 1011/*
1025 * Check for any per-thread CPU timers that have fired and move them 1012 * Check for any per-thread CPU timers that have fired and move them
1026 * off the tsk->*_timers list onto the firing list. Per-thread timers 1013 * off the tsk->*_timers list onto the firing list. Per-thread timers
@@ -1427,7 +1414,6 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
1427 struct list_head *head; 1414 struct list_head *head;
1428 1415
1429 BUG_ON(clock_idx == CPUCLOCK_SCHED); 1416 BUG_ON(clock_idx == CPUCLOCK_SCHED);
1430 start_process_timers(tsk);
1431 cpu_timer_sample_group(clock_idx, tsk, &now); 1417 cpu_timer_sample_group(clock_idx, tsk, &now);
1432 1418
1433 if (oldval) { 1419 if (oldval) {