Commit 4da94d49b2ecb0a26e716a8811c3ecc542c2a65d

Authored by Peter Zijlstra
Committed by Ingo Molnar
1 parent 3fccfd67df

timers: fix TIMER_ABSTIME for process wide cpu timers

The POSIX timer interface allows for absolute time expiry values through the
TIMER_ABSTIME flag, therefore we have to synchronize the timer to the clock
every time we start it.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 2 changed files with 35 additions and 12 deletions Side-by-side Diff

include/linux/sched.h
... ... @@ -2201,18 +2201,7 @@
2201 2201 * Thread group CPU time accounting.
2202 2202 */
2203 2203 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
2204   -
2205   -static inline
2206   -void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
2207   -{
2208   - struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
2209   - unsigned long flags;
2210   -
2211   - spin_lock_irqsave(&cputimer->lock, flags);
2212   - cputimer->running = 1;
2213   - *times = cputimer->cputime;
2214   - spin_unlock_irqrestore(&cputimer->lock, flags);
2215   -}
  2204 +void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
2216 2205  
2217 2206 static inline void thread_group_cputime_init(struct signal_struct *sig)
2218 2207 {
kernel/posix-cpu-timers.c
... ... @@ -261,6 +261,40 @@
261 261 rcu_read_unlock();
262 262 }
263 263  
  264 +static void update_gt_cputime(struct task_cputime *a, struct task_cputime *b)
  265 +{
  266 + if (cputime_gt(b->utime, a->utime))
  267 + a->utime = b->utime;
  268 +
  269 + if (cputime_gt(b->stime, a->stime))
  270 + a->stime = b->stime;
  271 +
  272 + if (b->sum_exec_runtime > a->sum_exec_runtime)
  273 + a->sum_exec_runtime = b->sum_exec_runtime;
  274 +}
  275 +
  276 +void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
  277 +{
  278 + struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
  279 + struct task_cputime sum;
  280 + unsigned long flags;
  281 +
  282 + spin_lock_irqsave(&cputimer->lock, flags);
  283 + if (!cputimer->running) {
  284 + cputimer->running = 1;
  285 + /*
  286 + * The POSIX timer interface allows for absolute time expiry
  287 + * values through the TIMER_ABSTIME flag, therefore we have
  288 + * to synchronize the timer to the clock every time we start
  289 + * it.
  290 + */
  291 + thread_group_cputime(tsk, &sum);
  292 + update_gt_cputime(&cputimer->cputime, &sum);
  293 + }
  294 + *times = cputimer->cputime;
  295 + spin_unlock_irqrestore(&cputimer->lock, flags);
  296 +}
  297 +
264 298 /*
265 299 * Sample a process (thread group) clock for the given group_leader task.
266 300 * Must be called with tasklist_lock held for reading.