diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index e3fa92106ed7..2a3c9799d76b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1920,8 +1920,40 @@ static void update_rq_clock_task(struct rq *rq, s64 delta) | |||
1920 | sched_rt_avg_update(rq, irq_delta); | 1920 | sched_rt_avg_update(rq, irq_delta); |
1921 | } | 1921 | } |
1922 | 1922 | ||
1923 | static int irqtime_account_hi_update(void) | ||
1924 | { | ||
1925 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | ||
1926 | unsigned long flags; | ||
1927 | u64 latest_ns; | ||
1928 | int ret = 0; | ||
1929 | |||
1930 | local_irq_save(flags); | ||
1931 | latest_ns = this_cpu_read(cpu_hardirq_time); | ||
1932 | if (cputime64_gt(nsecs_to_cputime64(latest_ns), cpustat->irq)) | ||
1933 | ret = 1; | ||
1934 | local_irq_restore(flags); | ||
1935 | return ret; | ||
1936 | } | ||
1937 | |||
1938 | static int irqtime_account_si_update(void) | ||
1939 | { | ||
1940 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | ||
1941 | unsigned long flags; | ||
1942 | u64 latest_ns; | ||
1943 | int ret = 0; | ||
1944 | |||
1945 | local_irq_save(flags); | ||
1946 | latest_ns = this_cpu_read(cpu_softirq_time); | ||
1947 | if (cputime64_gt(nsecs_to_cputime64(latest_ns), cpustat->softirq)) | ||
1948 | ret = 1; | ||
1949 | local_irq_restore(flags); | ||
1950 | return ret; | ||
1951 | } | ||
1952 | |||
1923 | #else /* CONFIG_IRQ_TIME_ACCOUNTING */ | 1953 | #else /* CONFIG_IRQ_TIME_ACCOUNTING */ |
1924 | 1954 | ||
1955 | #define sched_clock_irqtime (0) | ||
1956 | |||
1925 | static void update_rq_clock_task(struct rq *rq, s64 delta) | 1957 | static void update_rq_clock_task(struct rq *rq, s64 delta) |
1926 | { | 1958 | { |
1927 | rq->clock_task += delta; | 1959 | rq->clock_task += delta; |
@@ -3621,6 +3653,65 @@ void account_system_time(struct task_struct *p, int hardirq_offset, | |||
3621 | __account_system_time(p, cputime, cputime_scaled, target_cputime64); | 3653 | __account_system_time(p, cputime, cputime_scaled, target_cputime64); |
3622 | } | 3654 | } |
3623 | 3655 | ||
3656 | #ifdef CONFIG_IRQ_TIME_ACCOUNTING | ||
3657 | /* | ||
3658 | * Account a tick to a process and cpustat | ||
3659 | * @p: the process that the cpu time gets accounted to | ||
3660 | * @user_tick: is the tick from userspace | ||
3661 | * @rq: the pointer to rq | ||
3662 | * | ||
3663 | * Tick demultiplexing follows the order | ||
3664 | * - pending hardirq update | ||
3665 | * - pending softirq update | ||
3666 | * - user_time | ||
3667 | * - idle_time | ||
3668 | * - system time | ||
3669 | * - check for guest_time | ||
3670 | * - else account as system_time | ||
3671 | * | ||
3672 | * Check for hardirq is done both for system and user time as there is | ||
3673 | * no timer going off while we are on hardirq and hence we may never get an | ||
3674 | * opportunity to update it solely in system time. | ||
3675 | * p->stime and friends are only updated on system time and not on irq | ||
3676 | * softirq as those do not count in task exec_runtime any more. | ||
3677 | */ | ||
3678 | static void irqtime_account_process_tick(struct task_struct *p, int user_tick, | ||
3679 | struct rq *rq) | ||
3680 | { | ||
3681 | cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); | ||
3682 | cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy); | ||
3683 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | ||
3684 | |||
3685 | if (irqtime_account_hi_update()) { | ||
3686 | cpustat->irq = cputime64_add(cpustat->irq, tmp); | ||
3687 | } else if (irqtime_account_si_update()) { | ||
3688 | cpustat->softirq = cputime64_add(cpustat->softirq, tmp); | ||
3689 | } else if (user_tick) { | ||
3690 | account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); | ||
3691 | } else if (p == rq->idle) { | ||
3692 | account_idle_time(cputime_one_jiffy); | ||
3693 | } else if (p->flags & PF_VCPU) { /* System time or guest time */ | ||
3694 | account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); | ||
3695 | } else { | ||
3696 | __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, | ||
3697 | &cpustat->system); | ||
3698 | } | ||
3699 | } | ||
3700 | |||
3701 | static void irqtime_account_idle_ticks(int ticks) | ||
3702 | { | ||
3703 | int i; | ||
3704 | struct rq *rq = this_rq(); | ||
3705 | |||
3706 | for (i = 0; i < ticks; i++) | ||
3707 | irqtime_account_process_tick(current, 0, rq); | ||
3708 | } | ||
3709 | #else | ||
3710 | static void irqtime_account_idle_ticks(int ticks) {} | ||
3711 | static void irqtime_account_process_tick(struct task_struct *p, int user_tick, | ||
3712 | struct rq *rq) {} | ||
3713 | #endif | ||
3714 | |||
3624 | /* | 3715 | /* |
3625 | * Account for involuntary wait time. | 3716 | * Account for involuntary wait time. |
3626 | * @steal: the cpu time spent in involuntary wait | 3717 | * @steal: the cpu time spent in involuntary wait |
@@ -3661,6 +3752,11 @@ void account_process_tick(struct task_struct *p, int user_tick) | |||
3661 | cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); | 3752 | cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); |
3662 | struct rq *rq = this_rq(); | 3753 | struct rq *rq = this_rq(); |
3663 | 3754 | ||
3755 | if (sched_clock_irqtime) { | ||
3756 | irqtime_account_process_tick(p, user_tick, rq); | ||
3757 | return; | ||
3758 | } | ||
3759 | |||
3664 | if (user_tick) | 3760 | if (user_tick) |
3665 | account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); | 3761 | account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); |
3666 | else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) | 3762 | else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) |
@@ -3686,6 +3782,12 @@ void account_steal_ticks(unsigned long ticks) | |||
3686 | */ | 3782 | */ |
3687 | void account_idle_ticks(unsigned long ticks) | 3783 | void account_idle_ticks(unsigned long ticks) |
3688 | { | 3784 | { |
3785 | |||
3786 | if (sched_clock_irqtime) { | ||
3787 | irqtime_account_idle_ticks(ticks); | ||
3788 | return; | ||
3789 | } | ||
3790 | |||
3689 | account_idle_time(jiffies_to_cputime(ticks)); | 3791 | account_idle_time(jiffies_to_cputime(ticks)); |
3690 | } | 3792 | } |
3691 | 3793 | ||