One of the arguments presented against merging the Resource Groups core is the lack of resource controllers that are in a state where they're ready to be merged.
Here's a very simple resource "controller" that simply accounts the CPU time consumed by the tasks in a resource group, and reports it via the stats interface. It has no shares or other configuration, but also has nothing intrusive in the kernel apart from a couple of calls to an accounting function in the existing time accounting in sched.c It's something that could be useful for any job control system. Obviously a proper CPU scheduler with QoS isolation is better, but (in the absence of such a scheduler that's ready for merging), right now tracking the CPU cycles consumed by a group of processes involves lots of expensive /proc scraping. (It's certainly something that we'd find useful). How about adding this alongside the numtasks controller as an example of a simple but useful controller? Paul diff -Naur -X /home/menage/dontdiff linux-2.6.17.7-clean/include/linux/cpu_acct.h linux-2.6.17.7/include/linux/cpu_acct.h --- linux-2.6.17.7-clean/include/linux/cpu_acct.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.17.7/include/linux/cpu_acct.h 2006-08-03 21:59:04.000000000 -0700 @@ -0,0 +1,10 @@ + +#ifndef _LINUX_CPU_ACCT_H +#define _LINUX_CPU_ACCT_H + +#include <linux/res_group_rc.h> +#include <asm/cputime.h> + +extern void cpuacct_charge(struct resource_group *, cputime_t cputime); + +#endif diff -Naur -X /home/menage/dontdiff linux-2.6.17.7-clean/kernel/sched.c linux-2.6.17.7/kernel/sched.c --- linux-2.6.17.7-clean/kernel/sched.c 2006-07-24 20:36:01.000000000 -0700 +++ linux-2.6.17.7/kernel/sched.c 2006-08-03 23:26:03.000000000 -0700 @@ -50,6 +50,7 @@ #include <linux/times.h> #include <linux/acct.h> #include <linux/kprobes.h> +#include <linux/cpu_acct.h> #include <asm/tlb.h> #include <asm/unistd.h> @@ -2518,6 +2519,8 @@ p->utime = cputime_add(p->utime, cputime); + cpuacct_charge(p->res_group, cputime); + /* Add user time to cpustat. */ tmp = cputime_to_cputime64(cputime); if (TASK_NICE(p) > 0) @@ -2541,6 +2544,8 @@ p->stime = cputime_add(p->stime, cputime); + cpuacct_charge(p->res_group, cputime); + /* Add system time to cpustat. */ tmp = cputime_to_cputime64(cputime); if (hardirq_count() - hardirq_offset) --- linux-2.6.17.7-clean/kernel/res_group/Makefile 2006-08-04 17:35:52.000000000 -0700 +++ linux-2.6.17.7/kernel/res_group/Makefile 2006-08-04 17:46:21.000000000 -0700 @@ -1,3 +1,4 @@ obj-y = res_group.o shares.o task.o obj-$(CONFIG_RES_GROUPS_NUMTASKS) += numtasks.o +obj-$(CONFIG_RES_GROUPS_CPUACCT) += cpu_acct.o obj-$(CONFIG_RGCS) += rgcs.o --- linux-2.6.17.7-clean/init/Kconfig 2006-08-04 17:35:52.000000000 -0700 +++ linux-2.6.17.7/init/Kconfig 2006-08-04 17:45:50.000000000 -0700 @@ -185,6 +185,14 @@ Say N if unsure, Y to use the feature. +config RES_GROUPS_CPUACCT + bool "Simple CPU accounting Resource Controller" + depends on RES_GROUPS + default y + help + Provides a simple Resource Controller for monitoring the + total CPU consumed by the tasks in a resource group + endmenu config SYSCTL bool "Sysctl support" --- linux-2.6.17.7-clean/kernel/res_group/cpu_acct.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.17.7/kernel/res_group/cpu_acct.c 2006-08-04 18:07:28.000000000 -0700 @@ -0,0 +1,121 @@ +/* cpu_acct.c - CPU accounting resource controller for Resource Groups + * + * Copyright (C) Google Inc, 2006 + * + */ + +/* + * Resource controller for reporting total CPU usage of tasks in a + * resource group. + */ +#include <linux/module.h> +#include <linux/res_group_rc.h> +#include <asm/div64.h> + +static const char res_ctlr_name[] = "cpuacct"; + +struct cpuacct { + struct res_shares shares; // Not really used + spinlock_t lock; + cputime64_t time; // total time used by this class +}; + +struct res_controller cpuacct_ctlr; + +static struct cpuacct *get_shares_cpuacct(struct res_shares *shares) { + if (shares) + return container_of(shares, struct cpuacct, shares); + return NULL; +} + +static struct cpuacct *get_cpuacct(struct resource_group *rgroup) { + return get_shares_cpuacct(get_controller_shares(rgroup, + &cpuacct_ctlr)); +} + +static struct res_shares *cpuacct_alloc_shares_struct( + struct resource_group *rgroup) { + struct cpuacct *res; + + res = kzalloc(sizeof(struct cpuacct), GFP_KERNEL); + if (!res) { + return NULL; + } + res->shares.min_shares = SHARE_UNSUPPORTED; + res->shares.max_shares = SHARE_UNSUPPORTED; + res->shares.child_shares_divisor = SHARE_DEFAULT_DIVISOR; + res->shares.unused_min_shares = SHARE_DEFAULT_DIVISOR; + spin_lock_init(&res->lock); + return &res->shares; +} + +static void cpuacct_free_shares_struct(struct res_shares *shares) { + struct cpuacct *res; + + res = get_shares_cpuacct(shares); + kfree(res); +} + +static ssize_t cpuacct_show_stats(struct res_shares *shares, + char *buf, size_t buf_size) { + struct cpuacct *res; + cputime64_t time; + + res = get_shares_cpuacct(shares); + if (!res) + return -EINVAL; + + spin_lock_irq(&res->lock); + time = res->time; + spin_unlock_irq(&res->lock); + + time *= 1000; + do_div(time, HZ); + return snprintf(buf, buf_size, "%s: total_msecs: %llu\n", + res_ctlr_name, time); + +} + +void cpuacct_charge(struct resource_group * rgroup, cputime_t cputime) { + struct cpuacct *res; + unsigned long flags; + + if ((cpuacct_ctlr.ctlr_id == NO_RES_ID) || (rgroup == NULL)) + return; + + res = get_cpuacct(rgroup); + + /* cpuacct not available for this resource group */ + if (!res) + return; + + spin_lock_irqsave(&res->lock, flags); + res->time = cputime64_add(res->time, cputime); + spin_unlock_irqrestore(&res->lock, flags); + +} + +struct res_controller cpuacct_ctlr = { + .name = res_ctlr_name, + .depth_supported = 3, + .ctlr_id = NO_RES_ID, + .alloc_shares_struct = cpuacct_alloc_shares_struct, + .free_shares_struct = cpuacct_free_shares_struct, + .show_stats = cpuacct_show_stats, +}; + +int __init init_cpuacct_res(void) { + if (cpuacct_ctlr.ctlr_id != NO_RES_ID) + return -EBUSY; /* already registered */ + return register_controller(&cpuacct_ctlr); +} + +void __exit exit_cpuacct_res(void) { + int rc; + do { + rc = unregister_controller(&cpuacct_ctlr); + } while (rc == -EBUSY); + BUG_ON(rc != 0); +} +module_init(init_cpuacct_res) +module_exit(exit_cpuacct_res) ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ ckrm-tech mailing list https://lists.sourceforge.net/lists/listinfo/ckrm-tech