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