/* * CPU accounting code for task groups. * * Based on the work by Paul Menage (menage@google.com) and Balbir Singh * (balbir@in.ibm.com).
*/ #include <linux/sched/cputime.h> #include"sched.h"
/* Time spent by the tasks of the CPU accounting group executing in ... */ enum cpuacct_stat_index {
CPUACCT_STAT_USER, /* ... user mode */
CPUACCT_STAT_SYSTEM, /* ... kernel mode */
/* track CPU usage of a group of tasks and its child groups */ struct cpuacct { struct cgroup_subsys_state css; /* cpuusage holds pointer to a u64-type object on every CPU */
u64 __percpu *cpuusage; struct kernel_cpustat __percpu *cpustat;
};
/* Return CPU accounting group to which this task belongs */ staticinlinestruct cpuacct *task_ca(struct task_struct *tsk)
{ return css_ca(task_css(tsk, cpuacct_cgrp_id));
}
/* Create a new CPU accounting group */ staticstruct cgroup_subsys_state *
cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)
{ struct cpuacct *ca;
if (!parent_css) return &root_cpuacct.css;
ca = kzalloc(sizeof(*ca), GFP_KERNEL); if (!ca) goto out;
ca->cpuusage = alloc_percpu(u64); if (!ca->cpuusage) goto out_free_ca;
ca->cpustat = alloc_percpu(struct kernel_cpustat); if (!ca->cpustat) goto out_free_cpuusage;
/* * We allow index == CPUACCT_STAT_NSTATS here to read * the sum of usages.
*/ if (WARN_ON_ONCE(index > CPUACCT_STAT_NSTATS)) return 0;
#ifndef CONFIG_64BIT /* * Take rq->lock to make 64-bit read safe on 32-bit platforms.
*/
raw_spin_rq_lock_irq(cpu_rq(cpu)); #endif
switch (index) { case CPUACCT_STAT_USER:
data = cpustat[CPUTIME_USER] + cpustat[CPUTIME_NICE]; break; case CPUACCT_STAT_SYSTEM:
data = cpustat[CPUTIME_SYSTEM] + cpustat[CPUTIME_IRQ] +
cpustat[CPUTIME_SOFTIRQ]; break; case CPUACCT_STAT_NSTATS:
data = *cpuusage; break;
}
/* Return total CPU usage (in nanoseconds) of a group */ static u64 __cpuusage_read(struct cgroup_subsys_state *css, enum cpuacct_stat_index index)
{ struct cpuacct *ca = css_ca(css);
u64 totalcpuusage = 0; int i;
for_each_possible_cpu(i)
totalcpuusage += cpuacct_cpuusage_read(ca, i, index);
/* * charge this task's execution time to its accounting group. * * called with rq->lock held.
*/ void cpuacct_charge(struct task_struct *tsk, u64 cputime)
{ unsignedint cpu = task_cpu(tsk); struct cpuacct *ca;
lockdep_assert_rq_held(cpu_rq(cpu));
for (ca = task_ca(tsk); ca; ca = parent_ca(ca))
*per_cpu_ptr(ca->cpuusage, cpu) += cputime;
}
/* * Add user/system time to cpuacct. * * Note: it's the caller that updates the account of the root cgroup.
*/ void cpuacct_account_field(struct task_struct *tsk, int index, u64 val)
{ struct cpuacct *ca;
for (ca = task_ca(tsk); ca != &root_cpuacct; ca = parent_ca(ca))
__this_cpu_add(ca->cpustat->cpustat[index], val);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.