Commit 4da94d49b2ecb0a26e716a8811c3ecc542c2a65d
Committed by
Ingo Molnar
1 parent
3fccfd67df
Exists in
master
and in
4 other branches
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. |