aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2013-02-25 11:25:39 -0500
committerFrederic Weisbecker <fweisbec@gmail.com>2013-03-07 11:10:32 -0500
commit9fbc42eac1f6917081dc3b39922b2f1c57fdff28 (patch)
tree9eef797db037ced359dc5abcc6945cfb8f303a09
parentb22366cd54c6fe05db426f20adb10f461c19ec06 (diff)
cputime: Dynamically scale cputime for full dynticks accounting
The full dynticks cputime accounting is able to account either using the tick or the context tracking subsystem. This way the housekeeping CPU can keep the low overhead tick based solution. This latter mode has a low jiffies resolution granularity and need to be scaled against CFS precise runtime accounting to improve its result. We are doing this for CONFIG_TICK_CPU_ACCOUNTING, now we also need to expand it to full dynticks accounting dynamic off-case as well. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Li Zhong <zhong@linux.vnet.ibm.com> Cc: Kevin Hilman <khilman@linaro.org> Cc: Mats Liljegren <mats.liljegren@enea.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--include/linux/sched.h4
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/sched/cputime.c154
3 files changed, 83 insertions, 77 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d35d2b6ddbfb..8d1b6034d80b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -570,7 +570,7 @@ struct signal_struct {
570 cputime_t utime, stime, cutime, cstime; 570 cputime_t utime, stime, cutime, cstime;
571 cputime_t gtime; 571 cputime_t gtime;
572 cputime_t cgtime; 572 cputime_t cgtime;
573#ifndef CONFIG_VIRT_CPU_ACCOUNTING 573#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
574 struct cputime prev_cputime; 574 struct cputime prev_cputime;
575#endif 575#endif
576 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; 576 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
@@ -1327,7 +1327,7 @@ struct task_struct {
1327 1327
1328 cputime_t utime, stime, utimescaled, stimescaled; 1328 cputime_t utime, stime, utimescaled, stimescaled;
1329 cputime_t gtime; 1329 cputime_t gtime;
1330#ifndef CONFIG_VIRT_CPU_ACCOUNTING 1330#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
1331 struct cputime prev_cputime; 1331 struct cputime prev_cputime;
1332#endif 1332#endif
1333#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 1333#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
diff --git a/kernel/fork.c b/kernel/fork.c
index 8d932b1c9056..f3146ed49074 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1230,7 +1230,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1230 1230
1231 p->utime = p->stime = p->gtime = 0; 1231 p->utime = p->stime = p->gtime = 0;
1232 p->utimescaled = p->stimescaled = 0; 1232 p->utimescaled = p->stimescaled = 0;
1233#ifndef CONFIG_VIRT_CPU_ACCOUNTING 1233#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
1234 p->prev_cputime.utime = p->prev_cputime.stime = 0; 1234 p->prev_cputime.utime = p->prev_cputime.stime = 0;
1235#endif 1235#endif
1236#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 1236#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index ed12cbb135f4..024fe1998ad5 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -388,82 +388,10 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_
388 struct rq *rq) {} 388 struct rq *rq) {}
389#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ 389#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
390 390
391#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
392/*
393 * Account a single tick of cpu time.
394 * @p: the process that the cpu time gets accounted to
395 * @user_tick: indicates if the tick is a user or a system tick
396 */
397void account_process_tick(struct task_struct *p, int user_tick)
398{
399 cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
400 struct rq *rq = this_rq();
401
402 if (vtime_accounting_enabled())
403 return;
404
405 if (sched_clock_irqtime) {
406 irqtime_account_process_tick(p, user_tick, rq);
407 return;
408 }
409
410 if (steal_account_process_tick())
411 return;
412
413 if (user_tick)
414 account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
415 else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
416 account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy,
417 one_jiffy_scaled);
418 else
419 account_idle_time(cputime_one_jiffy);
420}
421
422/*
423 * Account multiple ticks of steal time.
424 * @p: the process from which the cpu time has been stolen
425 * @ticks: number of stolen ticks
426 */
427void account_steal_ticks(unsigned long ticks)
428{
429 account_steal_time(jiffies_to_cputime(ticks));
430}
431
432/*
433 * Account multiple ticks of idle time.
434 * @ticks: number of stolen ticks
435 */
436void account_idle_ticks(unsigned long ticks)
437{
438
439 if (sched_clock_irqtime) {
440 irqtime_account_idle_ticks(ticks);
441 return;
442 }
443
444 account_idle_time(jiffies_to_cputime(ticks));
445}
446#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
447
448/* 391/*
449 * Use precise platform statistics if available: 392 * Use precise platform statistics if available:
450 */ 393 */
451#ifdef CONFIG_VIRT_CPU_ACCOUNTING 394#ifdef CONFIG_VIRT_CPU_ACCOUNTING
452void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
453{
454 *ut = p->utime;
455 *st = p->stime;
456}
457
458void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
459{
460 struct task_cputime cputime;
461
462 thread_group_cputime(p, &cputime);
463
464 *ut = cputime.utime;
465 *st = cputime.stime;
466}
467 395
468#ifndef __ARCH_HAS_VTIME_TASK_SWITCH 396#ifndef __ARCH_HAS_VTIME_TASK_SWITCH
469void vtime_task_switch(struct task_struct *prev) 397void vtime_task_switch(struct task_struct *prev)
@@ -518,8 +446,80 @@ void vtime_account_irq_enter(struct task_struct *tsk)
518} 446}
519EXPORT_SYMBOL_GPL(vtime_account_irq_enter); 447EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
520#endif /* __ARCH_HAS_VTIME_ACCOUNT */ 448#endif /* __ARCH_HAS_VTIME_ACCOUNT */
449#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
450
451
452#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
453void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
454{
455 *ut = p->utime;
456 *st = p->stime;
457}
521 458
522#else /* !CONFIG_VIRT_CPU_ACCOUNTING */ 459void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
460{
461 struct task_cputime cputime;
462
463 thread_group_cputime(p, &cputime);
464
465 *ut = cputime.utime;
466 *st = cputime.stime;
467}
468#else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
469/*
470 * Account a single tick of cpu time.
471 * @p: the process that the cpu time gets accounted to
472 * @user_tick: indicates if the tick is a user or a system tick
473 */
474void account_process_tick(struct task_struct *p, int user_tick)
475{
476 cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
477 struct rq *rq = this_rq();
478
479 if (vtime_accounting_enabled())
480 return;
481
482 if (sched_clock_irqtime) {
483 irqtime_account_process_tick(p, user_tick, rq);
484 return;
485 }
486
487 if (steal_account_process_tick())
488 return;
489
490 if (user_tick)
491 account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
492 else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
493 account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy,
494 one_jiffy_scaled);
495 else
496 account_idle_time(cputime_one_jiffy);
497}
498
499/*
500 * Account multiple ticks of steal time.
501 * @p: the process from which the cpu time has been stolen
502 * @ticks: number of stolen ticks
503 */
504void account_steal_ticks(unsigned long ticks)
505{
506 account_steal_time(jiffies_to_cputime(ticks));
507}
508
509/*
510 * Account multiple ticks of idle time.
511 * @ticks: number of stolen ticks
512 */
513void account_idle_ticks(unsigned long ticks)
514{
515
516 if (sched_clock_irqtime) {
517 irqtime_account_idle_ticks(ticks);
518 return;
519 }
520
521 account_idle_time(jiffies_to_cputime(ticks));
522}
523 523
524static cputime_t scale_stime(cputime_t stime, cputime_t rtime, cputime_t total) 524static cputime_t scale_stime(cputime_t stime, cputime_t rtime, cputime_t total)
525{ 525{
@@ -545,6 +545,12 @@ static void cputime_adjust(struct task_cputime *curr,
545{ 545{
546 cputime_t rtime, stime, total; 546 cputime_t rtime, stime, total;
547 547
548 if (vtime_accounting_enabled()) {
549 *ut = curr->utime;
550 *st = curr->stime;
551 return;
552 }
553
548 stime = curr->stime; 554 stime = curr->stime;
549 total = stime + curr->utime; 555 total = stime + curr->utime;
550 556
@@ -597,7 +603,7 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
597 thread_group_cputime(p, &cputime); 603 thread_group_cputime(p, &cputime);
598 cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); 604 cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
599} 605}
600#endif /* !CONFIG_VIRT_CPU_ACCOUNTING */ 606#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
601 607
602#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 608#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
603static unsigned long long vtime_delta(struct task_struct *tsk) 609static unsigned long long vtime_delta(struct task_struct *tsk)