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

Reply via email to