Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-s…
Browse files Browse the repository at this point in the history
…ched

* git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched:
  sched: cpu accounting controller (V2)
  • Loading branch information
Linus Torvalds committed Dec 3, 2007
2 parents 26145f7 + d842de8 commit ca6435f
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 26 deletions.
7 changes: 7 additions & 0 deletions include/linux/cgroup_subsys.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ SUBSYS(cpu_cgroup)
#endif

/* */

#ifdef CONFIG_CGROUP_CPUACCT
SUBSYS(cpuacct)
#endif

/* */

7 changes: 7 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,13 @@ config FAIR_CGROUP_SCHED

endchoice

config CGROUP_CPUACCT
bool "Simple CPU accounting cgroup subsystem"
depends on CGROUPS
help
Provides a simple Resource Controller for monitoring the
total CPU consumed by the tasks in a cgroup

config SYSFS_DEPRECATED
bool "Create deprecated sysfs files"
default y
Expand Down
155 changes: 129 additions & 26 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,12 @@ iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
struct rq_iterator *iterator);
#endif

#ifdef CONFIG_CGROUP_CPUACCT
static void cpuacct_charge(struct task_struct *tsk, u64 cputime);
#else
static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {}
#endif

#include "sched_stats.h"
#include "sched_idletask.c"
#include "sched_fair.c"
Expand Down Expand Up @@ -7221,38 +7227,12 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
return (u64) tg->shares;
}

static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft)
{
struct task_group *tg = cgroup_tg(cgrp);
unsigned long flags;
u64 res = 0;
int i;

for_each_possible_cpu(i) {
/*
* Lock to prevent races with updating 64-bit counters
* on 32-bit arches.
*/
spin_lock_irqsave(&cpu_rq(i)->lock, flags);
res += tg->se[i]->sum_exec_runtime;
spin_unlock_irqrestore(&cpu_rq(i)->lock, flags);
}
/* Convert from ns to ms */
do_div(res, NSEC_PER_MSEC);

return res;
}

static struct cftype cpu_files[] = {
{
.name = "shares",
.read_uint = cpu_shares_read_uint,
.write_uint = cpu_shares_write_uint,
},
{
.name = "usage",
.read_uint = cpu_usage_read,
},
};

static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont)
Expand All @@ -7272,3 +7252,126 @@ struct cgroup_subsys cpu_cgroup_subsys = {
};

#endif /* CONFIG_FAIR_CGROUP_SCHED */

#ifdef CONFIG_CGROUP_CPUACCT

/*
* CPU accounting code for task groups.
*
* Based on the work by Paul Menage (menage@google.com) and Balbir Singh
* (balbir@in.ibm.com).
*/

/* track cpu usage of a group of tasks */
struct cpuacct {
struct cgroup_subsys_state css;
/* cpuusage holds pointer to a u64-type object on every cpu */
u64 *cpuusage;
};

struct cgroup_subsys cpuacct_subsys;

/* return cpu accounting group corresponding to this container */
static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
{
return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
struct cpuacct, css);
}

/* return cpu accounting group to which this task belongs */
static inline struct cpuacct *task_ca(struct task_struct *tsk)
{
return container_of(task_subsys_state(tsk, cpuacct_subsys_id),
struct cpuacct, css);
}

/* create a new cpu accounting group */
static struct cgroup_subsys_state *cpuacct_create(
struct cgroup_subsys *ss, struct cgroup *cont)
{
struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);

if (!ca)
return ERR_PTR(-ENOMEM);

ca->cpuusage = alloc_percpu(u64);
if (!ca->cpuusage) {
kfree(ca);
return ERR_PTR(-ENOMEM);
}

return &ca->css;
}

/* destroy an existing cpu accounting group */
static void cpuacct_destroy(struct cgroup_subsys *ss,
struct cgroup *cont)
{
struct cpuacct *ca = cgroup_ca(cont);

free_percpu(ca->cpuusage);
kfree(ca);
}

/* return total cpu usage (in nanoseconds) of a group */
static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
{
struct cpuacct *ca = cgroup_ca(cont);
u64 totalcpuusage = 0;
int i;

for_each_possible_cpu(i) {
u64 *cpuusage = percpu_ptr(ca->cpuusage, i);

/*
* Take rq->lock to make 64-bit addition safe on 32-bit
* platforms.
*/
spin_lock_irq(&cpu_rq(i)->lock);
totalcpuusage += *cpuusage;
spin_unlock_irq(&cpu_rq(i)->lock);
}

return totalcpuusage;
}

static struct cftype files[] = {
{
.name = "usage",
.read_uint = cpuusage_read,
},
};

static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
{
return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
}

/*
* charge this task's execution time to its accounting group.
*
* called with rq->lock held.
*/
static void cpuacct_charge(struct task_struct *tsk, u64 cputime)
{
struct cpuacct *ca;

if (!cpuacct_subsys.active)
return;

ca = task_ca(tsk);
if (ca) {
u64 *cpuusage = percpu_ptr(ca->cpuusage, task_cpu(tsk));

*cpuusage += cputime;
}
}

struct cgroup_subsys cpuacct_subsys = {
.name = "cpuacct",
.create = cpuacct_create,
.destroy = cpuacct_destroy,
.populate = cpuacct_populate,
.subsys_id = cpuacct_subsys_id,
};
#endif /* CONFIG_CGROUP_CPUACCT */
6 changes: 6 additions & 0 deletions kernel/sched_fair.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ static void update_curr(struct cfs_rq *cfs_rq)

__update_curr(cfs_rq, curr, delta_exec);
curr->exec_start = now;

if (entity_is_task(curr)) {
struct task_struct *curtask = task_of(curr);

cpuacct_charge(curtask, delta_exec);
}
}

static inline void
Expand Down
1 change: 1 addition & 0 deletions kernel/sched_rt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ static void update_curr_rt(struct rq *rq)

curr->se.sum_exec_runtime += delta_exec;
curr->se.exec_start = rq->clock;
cpuacct_charge(curr, delta_exec);
}

static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
Expand Down

0 comments on commit ca6435f

Please sign in to comment.