aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/cputime.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2012-07-16 12:00:34 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2013-01-27 13:23:29 -0500
commit3f4724ea85b7d9055a9976fa8f30b471bdfbca93 (patch)
treeaaa1792d0b78ea33c07ee6f5e707a07d9ef1795e /kernel/sched/cputime.c
parentabf917cd91cbb73952758f9741e2fa65002a48ee (diff)
cputime: Allow dynamic switch between tick/virtual based cputime accounting
Allow to dynamically switch between tick and virtual based cputime accounting. This way we can provide a kind of "on-demand" virtual based cputime accounting. In this mode, the kernel relies on the context tracking subsystem to dynamically probe on kernel boundaries. This is in preparation for being able to stop the timer tick in more places than just the idle state. Doing so will depend on CONFIG_VIRT_CPU_ACCOUNTING_GEN which makes it possible to account the cputime without the tick by hooking on kernel/user boundaries. Depending whether the tick is stopped or not, we can switch between tick and vtime based accounting anytime in order to minimize the overhead associated to user hooks. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Li Zhong <zhong@linux.vnet.ibm.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/sched/cputime.c')
-rw-r--r--kernel/sched/cputime.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 1c964eced92c..e1939d38bf73 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -317,8 +317,6 @@ out:
317 rcu_read_unlock(); 317 rcu_read_unlock();
318} 318}
319 319
320#ifndef CONFIG_VIRT_CPU_ACCOUNTING
321
322#ifdef CONFIG_IRQ_TIME_ACCOUNTING 320#ifdef CONFIG_IRQ_TIME_ACCOUNTING
323/* 321/*
324 * Account a tick to a process and cpustat 322 * Account a tick to a process and cpustat
@@ -383,11 +381,12 @@ static void irqtime_account_idle_ticks(int ticks)
383 irqtime_account_process_tick(current, 0, rq); 381 irqtime_account_process_tick(current, 0, rq);
384} 382}
385#else /* CONFIG_IRQ_TIME_ACCOUNTING */ 383#else /* CONFIG_IRQ_TIME_ACCOUNTING */
386static void irqtime_account_idle_ticks(int ticks) {} 384static inline void irqtime_account_idle_ticks(int ticks) {}
387static void irqtime_account_process_tick(struct task_struct *p, int user_tick, 385static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
388 struct rq *rq) {} 386 struct rq *rq) {}
389#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ 387#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
390 388
389#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
391/* 390/*
392 * Account a single tick of cpu time. 391 * Account a single tick of cpu time.
393 * @p: the process that the cpu time gets accounted to 392 * @p: the process that the cpu time gets accounted to
@@ -398,6 +397,9 @@ void account_process_tick(struct task_struct *p, int user_tick)
398 cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); 397 cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
399 struct rq *rq = this_rq(); 398 struct rq *rq = this_rq();
400 399
400 if (vtime_accounting_enabled())
401 return;
402
401 if (sched_clock_irqtime) { 403 if (sched_clock_irqtime) {
402 irqtime_account_process_tick(p, user_tick, rq); 404 irqtime_account_process_tick(p, user_tick, rq);
403 return; 405 return;
@@ -439,8 +441,7 @@ void account_idle_ticks(unsigned long ticks)
439 441
440 account_idle_time(jiffies_to_cputime(ticks)); 442 account_idle_time(jiffies_to_cputime(ticks));
441} 443}
442 444#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
443#endif
444 445
445/* 446/*
446 * Use precise platform statistics if available: 447 * Use precise platform statistics if available:
@@ -475,6 +476,9 @@ EXPORT_SYMBOL_GPL(vtime_account_system_irqsafe);
475#ifndef __ARCH_HAS_VTIME_TASK_SWITCH 476#ifndef __ARCH_HAS_VTIME_TASK_SWITCH
476void vtime_task_switch(struct task_struct *prev) 477void vtime_task_switch(struct task_struct *prev)
477{ 478{
479 if (!vtime_accounting_enabled())
480 return;
481
478 if (is_idle_task(prev)) 482 if (is_idle_task(prev))
479 vtime_account_idle(prev); 483 vtime_account_idle(prev);
480 else 484 else
@@ -498,6 +502,9 @@ void vtime_task_switch(struct task_struct *prev)
498#ifndef __ARCH_HAS_VTIME_ACCOUNT 502#ifndef __ARCH_HAS_VTIME_ACCOUNT
499void vtime_account(struct task_struct *tsk) 503void vtime_account(struct task_struct *tsk)
500{ 504{
505 if (!vtime_accounting_enabled())
506 return;
507
501 if (!in_interrupt()) { 508 if (!in_interrupt()) {
502 /* 509 /*
503 * If we interrupted user, context_tracking_in_user() 510 * If we interrupted user, context_tracking_in_user()
@@ -520,7 +527,7 @@ void vtime_account(struct task_struct *tsk)
520EXPORT_SYMBOL_GPL(vtime_account); 527EXPORT_SYMBOL_GPL(vtime_account);
521#endif /* __ARCH_HAS_VTIME_ACCOUNT */ 528#endif /* __ARCH_HAS_VTIME_ACCOUNT */
522 529
523#else 530#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
524 531
525static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) 532static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total)
526{ 533{
@@ -599,7 +606,7 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
599 thread_group_cputime(p, &cputime); 606 thread_group_cputime(p, &cputime);
600 cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); 607 cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
601} 608}
602#endif 609#endif /* !CONFIG_VIRT_CPU_ACCOUNTING */
603 610
604#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 611#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
605static DEFINE_PER_CPU(unsigned long long, cputime_snap); 612static DEFINE_PER_CPU(unsigned long long, cputime_snap);
@@ -617,14 +624,23 @@ static cputime_t get_vtime_delta(void)
617 624
618void vtime_account_system(struct task_struct *tsk) 625void vtime_account_system(struct task_struct *tsk)
619{ 626{
620 cputime_t delta_cpu = get_vtime_delta(); 627 cputime_t delta_cpu;
628
629 if (!vtime_accounting_enabled())
630 return;
621 631
632 delta_cpu = get_vtime_delta();
622 account_system_time(tsk, irq_count(), delta_cpu, cputime_to_scaled(delta_cpu)); 633 account_system_time(tsk, irq_count(), delta_cpu, cputime_to_scaled(delta_cpu));
623} 634}
624 635
625void vtime_account_user(struct task_struct *tsk) 636void vtime_account_user(struct task_struct *tsk)
626{ 637{
627 cputime_t delta_cpu = get_vtime_delta(); 638 cputime_t delta_cpu;
639
640 if (!vtime_accounting_enabled())
641 return;
642
643 delta_cpu = get_vtime_delta();
628 644
629 account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu)); 645 account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu));
630} 646}
@@ -635,4 +651,9 @@ void vtime_account_idle(struct task_struct *tsk)
635 651
636 account_idle_time(delta_cpu); 652 account_idle_time(delta_cpu);
637} 653}
654
655bool vtime_accounting_enabled(void)
656{
657 return context_tracking_active();
658}
638#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */ 659#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */