Commit 3fccfd67df79c6351a156eb25a7a514e5f39c4d9

Authored by Peter Zijlstra
Committed by Ingo Molnar
1 parent ff08f76d73

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>

Showing 2 changed files with 15 additions and 28 deletions Side-by-side Diff

include/linux/sched.h
... ... @@ -2209,6 +2209,7 @@
2209 2209 unsigned long flags;
2210 2210  
2211 2211 spin_lock_irqsave(&cputimer->lock, flags);
  2212 + cputimer->running = 1;
2212 2213 *times = cputimer->cputime;
2213 2214 spin_unlock_irqrestore(&cputimer->lock, flags);
2214 2215 }
kernel/posix-cpu-timers.c
... ... @@ -488,7 +488,7 @@
488 488 {
489 489 struct task_cputime cputime;
490 490  
491   - thread_group_cputime(tsk, &cputime);
  491 + thread_group_cputimer(tsk, &cputime);
492 492 cleanup_timers(tsk->signal->cpu_timers,
493 493 cputime.utime, cputime.stime, cputime.sum_exec_runtime);
494 494 }
... ... @@ -507,29 +507,6 @@
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 510 * Insert the timer on the appropriate list before any timers that
534 511 * expire later. This must be called with the tasklist_lock held
535 512 * for reading, and interrupts disabled.
... ... @@ -549,9 +526,6 @@
549 526 BUG_ON(!irqs_disabled());
550 527 spin_lock(&p->sighand->siglock);
551 528  
552   - if (!CPUCLOCK_PERTHREAD(timer->it_clock))
553   - start_process_timers(p);
554   -
555 529 listpos = head;
556 530 if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
557 531 list_for_each_entry(next, head, entry) {
... ... @@ -1021,6 +995,19 @@
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 1012 * Check for any per-thread CPU timers that have fired and move them
1026 1013 * off the tsk->*_timers list onto the firing list. Per-thread timers
... ... @@ -1427,7 +1414,6 @@
1427 1414 struct list_head *head;
1428 1415  
1429 1416 BUG_ON(clock_idx == CPUCLOCK_SCHED);
1430   - start_process_timers(tsk);
1431 1417 cpu_timer_sample_group(clock_idx, tsk, &now);
1432 1418  
1433 1419 if (oldval) {