diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-02-05 06:24:16 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-05 07:04:33 -0500 |
commit | 4cd4c1b40d40447fb5e7ba80746c6d7ba91d7a53 (patch) | |
tree | b1e580d5284648d6884e951d995509094a92cca4 /kernel/sched_stats.h | |
parent | 32bd671d6cbeda60dc73be77fa2b9037d9a9bfa0 (diff) |
timers: split process wide cpu clocks/timers
Change the process wide cpu timers/clocks so that we:
1) don't mess up the kernel with too many threads,
2) don't have a per-cpu allocation for each process,
3) have no impact when not used.
In order to accomplish this we're going to split it into two parts:
- clocks; which can take all the time they want since they run
from user context -- ie. sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
- timers; which need constant time sampling but since they're
explicity used, the user can pay the overhead.
The clock readout will go back to a full sum of the thread group, while the
timers will run of a global 'clock' that only runs when needed, so only
programs that make use of the facility pay the price.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched_stats.h')
-rw-r--r-- | kernel/sched_stats.h | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h index 8ab0cef8ecab..a8f93dd374e1 100644 --- a/kernel/sched_stats.h +++ b/kernel/sched_stats.h | |||
@@ -296,19 +296,21 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) | |||
296 | static inline void account_group_user_time(struct task_struct *tsk, | 296 | static inline void account_group_user_time(struct task_struct *tsk, |
297 | cputime_t cputime) | 297 | cputime_t cputime) |
298 | { | 298 | { |
299 | struct task_cputime *times; | 299 | struct thread_group_cputimer *cputimer; |
300 | struct signal_struct *sig; | ||
301 | 300 | ||
302 | /* tsk == current, ensure it is safe to use ->signal */ | 301 | /* tsk == current, ensure it is safe to use ->signal */ |
303 | if (unlikely(tsk->exit_state)) | 302 | if (unlikely(tsk->exit_state)) |
304 | return; | 303 | return; |
305 | 304 | ||
306 | sig = tsk->signal; | 305 | cputimer = &tsk->signal->cputimer; |
307 | times = &sig->cputime.totals; | ||
308 | 306 | ||
309 | spin_lock(×->lock); | 307 | if (!cputimer->running) |
310 | times->utime = cputime_add(times->utime, cputime); | 308 | return; |
311 | spin_unlock(×->lock); | 309 | |
310 | spin_lock(&cputimer->lock); | ||
311 | cputimer->cputime.utime = | ||
312 | cputime_add(cputimer->cputime.utime, cputime); | ||
313 | spin_unlock(&cputimer->lock); | ||
312 | } | 314 | } |
313 | 315 | ||
314 | /** | 316 | /** |
@@ -324,19 +326,21 @@ static inline void account_group_user_time(struct task_struct *tsk, | |||
324 | static inline void account_group_system_time(struct task_struct *tsk, | 326 | static inline void account_group_system_time(struct task_struct *tsk, |
325 | cputime_t cputime) | 327 | cputime_t cputime) |
326 | { | 328 | { |
327 | struct task_cputime *times; | 329 | struct thread_group_cputimer *cputimer; |
328 | struct signal_struct *sig; | ||
329 | 330 | ||
330 | /* tsk == current, ensure it is safe to use ->signal */ | 331 | /* tsk == current, ensure it is safe to use ->signal */ |
331 | if (unlikely(tsk->exit_state)) | 332 | if (unlikely(tsk->exit_state)) |
332 | return; | 333 | return; |
333 | 334 | ||
334 | sig = tsk->signal; | 335 | cputimer = &tsk->signal->cputimer; |
335 | times = &sig->cputime.totals; | 336 | |
337 | if (!cputimer->running) | ||
338 | return; | ||
336 | 339 | ||
337 | spin_lock(×->lock); | 340 | spin_lock(&cputimer->lock); |
338 | times->stime = cputime_add(times->stime, cputime); | 341 | cputimer->cputime.stime = |
339 | spin_unlock(×->lock); | 342 | cputime_add(cputimer->cputime.stime, cputime); |
343 | spin_unlock(&cputimer->lock); | ||
340 | } | 344 | } |
341 | 345 | ||
342 | /** | 346 | /** |
@@ -352,7 +356,7 @@ static inline void account_group_system_time(struct task_struct *tsk, | |||
352 | static inline void account_group_exec_runtime(struct task_struct *tsk, | 356 | static inline void account_group_exec_runtime(struct task_struct *tsk, |
353 | unsigned long long ns) | 357 | unsigned long long ns) |
354 | { | 358 | { |
355 | struct task_cputime *times; | 359 | struct thread_group_cputimer *cputimer; |
356 | struct signal_struct *sig; | 360 | struct signal_struct *sig; |
357 | 361 | ||
358 | sig = tsk->signal; | 362 | sig = tsk->signal; |
@@ -361,9 +365,12 @@ static inline void account_group_exec_runtime(struct task_struct *tsk, | |||
361 | if (unlikely(!sig)) | 365 | if (unlikely(!sig)) |
362 | return; | 366 | return; |
363 | 367 | ||
364 | times = &sig->cputime.totals; | 368 | cputimer = &sig->cputimer; |
369 | |||
370 | if (!cputimer->running) | ||
371 | return; | ||
365 | 372 | ||
366 | spin_lock(×->lock); | 373 | spin_lock(&cputimer->lock); |
367 | times->sum_exec_runtime += ns; | 374 | cputimer->cputime.sum_exec_runtime += ns; |
368 | spin_unlock(×->lock); | 375 | spin_unlock(&cputimer->lock); |
369 | } | 376 | } |