diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-02-10 10:37:31 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-11 08:04:19 -0500 |
commit | 3fccfd67df79c6351a156eb25a7a514e5f39c4d9 (patch) | |
tree | de4776e69e197119ac64097f3ff6239a55ad77be | |
parent | ff08f76d738d0ec0f334b187f61e160caa321d54 (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.h | 1 | ||||
-rw-r--r-- | kernel/posix-cpu-timers.c | 42 |
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 | */ | ||
514 | static 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 | */ | ||
526 | static 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 | ||
998 | static 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) { |