diff options
Diffstat (limited to 'kernel/sched/cputime.c')
-rw-r--r-- | kernel/sched/cputime.c | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index 5849448b981e..1c964eced92c 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/tsacct_kern.h> | 3 | #include <linux/tsacct_kern.h> |
4 | #include <linux/kernel_stat.h> | 4 | #include <linux/kernel_stat.h> |
5 | #include <linux/static_key.h> | 5 | #include <linux/static_key.h> |
6 | #include <linux/context_tracking.h> | ||
6 | #include "sched.h" | 7 | #include "sched.h" |
7 | 8 | ||
8 | 9 | ||
@@ -479,7 +480,9 @@ void vtime_task_switch(struct task_struct *prev) | |||
479 | else | 480 | else |
480 | vtime_account_system(prev); | 481 | vtime_account_system(prev); |
481 | 482 | ||
483 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
482 | vtime_account_user(prev); | 484 | vtime_account_user(prev); |
485 | #endif | ||
483 | arch_vtime_task_switch(prev); | 486 | arch_vtime_task_switch(prev); |
484 | } | 487 | } |
485 | #endif | 488 | #endif |
@@ -495,10 +498,24 @@ void vtime_task_switch(struct task_struct *prev) | |||
495 | #ifndef __ARCH_HAS_VTIME_ACCOUNT | 498 | #ifndef __ARCH_HAS_VTIME_ACCOUNT |
496 | void vtime_account(struct task_struct *tsk) | 499 | void vtime_account(struct task_struct *tsk) |
497 | { | 500 | { |
498 | if (in_interrupt() || !is_idle_task(tsk)) | 501 | if (!in_interrupt()) { |
499 | vtime_account_system(tsk); | 502 | /* |
500 | else | 503 | * If we interrupted user, context_tracking_in_user() |
501 | vtime_account_idle(tsk); | 504 | * is 1 because the context tracking don't hook |
505 | * on irq entry/exit. This way we know if | ||
506 | * we need to flush user time on kernel entry. | ||
507 | */ | ||
508 | if (context_tracking_in_user()) { | ||
509 | vtime_account_user(tsk); | ||
510 | return; | ||
511 | } | ||
512 | |||
513 | if (is_idle_task(tsk)) { | ||
514 | vtime_account_idle(tsk); | ||
515 | return; | ||
516 | } | ||
517 | } | ||
518 | vtime_account_system(tsk); | ||
502 | } | 519 | } |
503 | EXPORT_SYMBOL_GPL(vtime_account); | 520 | EXPORT_SYMBOL_GPL(vtime_account); |
504 | #endif /* __ARCH_HAS_VTIME_ACCOUNT */ | 521 | #endif /* __ARCH_HAS_VTIME_ACCOUNT */ |
@@ -583,3 +600,39 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime | |||
583 | cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); | 600 | cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); |
584 | } | 601 | } |
585 | #endif | 602 | #endif |
603 | |||
604 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN | ||
605 | static DEFINE_PER_CPU(unsigned long long, cputime_snap); | ||
606 | |||
607 | static cputime_t get_vtime_delta(void) | ||
608 | { | ||
609 | unsigned long long delta; | ||
610 | |||
611 | delta = sched_clock() - __this_cpu_read(cputime_snap); | ||
612 | __this_cpu_add(cputime_snap, delta); | ||
613 | |||
614 | /* CHECKME: always safe to convert nsecs to cputime? */ | ||
615 | return nsecs_to_cputime(delta); | ||
616 | } | ||
617 | |||
618 | void vtime_account_system(struct task_struct *tsk) | ||
619 | { | ||
620 | cputime_t delta_cpu = get_vtime_delta(); | ||
621 | |||
622 | account_system_time(tsk, irq_count(), delta_cpu, cputime_to_scaled(delta_cpu)); | ||
623 | } | ||
624 | |||
625 | void vtime_account_user(struct task_struct *tsk) | ||
626 | { | ||
627 | cputime_t delta_cpu = get_vtime_delta(); | ||
628 | |||
629 | account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu)); | ||
630 | } | ||
631 | |||
632 | void vtime_account_idle(struct task_struct *tsk) | ||
633 | { | ||
634 | cputime_t delta_cpu = get_vtime_delta(); | ||
635 | |||
636 | account_idle_time(delta_cpu); | ||
637 | } | ||
638 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */ | ||