* [PATCH 3/6] CKRM task_class classtype
@ 2004-04-29 8:25 Shailabh Nagar
0 siblings, 0 replies; only message in thread
From: Shailabh Nagar @ 2004-04-29 8:25 UTC (permalink / raw)
To: linux-kernel, ckrm-tech
[-- Attachment #1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2: 02-taskclass.ckrm-E12.patch --]
[-- Type: text/plain, Size: 25401 bytes --]
diff -Nru a/include/linux/ckrm_tc.h b/include/linux/ckrm_tc.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/ckrm_tc.h Wed Apr 28 22:41:05 2004
@@ -0,0 +1,18 @@
+#include <linux/ckrm_rc.h>
+
+
+
+#define TASK_CLASS_TYPE_NAME "taskclass"
+
+typedef struct ckrm_task_class {
+ struct ckrm_core_class core;
+} ckrm_task_class_t;
+
+
+// Index into genmfdesc array, defined in rcfs/dir_modules.c,
+// which has the mfdesc entry that taskclass wants to use
+#define TC_MF_IDX 0
+
+
+extern int ckrm_forced_reclassify_pid(int pid, struct ckrm_task_class *cls);
+
diff -Nru a/kernel/ckrm/ckrm_tc.c b/kernel/ckrm/ckrm_tc.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/kernel/ckrm/ckrm_tc.c Wed Apr 28 22:41:05 2004
@@ -0,0 +1,770 @@
+/* ckrm_tc.c - Class-based Kernel Resource Management (CKRM)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004
+ * (C) Shailabh Nagar, IBM Corp. 2003
+ * (C) Chandra Seetharaman, IBM Corp. 2003
+ * (C) Vivek Kashyap, IBM Corp. 2004
+ *
+ *
+ * Provides kernel API of CKRM for in-kernel,per-resource controllers
+ * (one each for cpu, memory, io, network) and callbacks for
+ * classification modules.
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/* Changes
+ *
+ * 28 Aug 2003
+ * Created.
+ * 06 Nov 2003
+ * Made modifications to suit the new RBCE module.
+ * 10 Nov 2003
+ * Fixed a bug in fork and exit callbacks. Added callbacks_active and
+ * surrounding logic. Added task paramter for all CE callbacks.
+ * 23 Mar 2004
+ * moved to referenced counted class objects and correct locking
+ * 12 Apr 2004
+ * introduced adopted to emerging classtype interface
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <asm/errno.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ckrm_rc.h>
+
+#include <linux/ckrm_tc.h>
+
+static struct ckrm_task_class taskclass_dflt_class = {
+};
+
+const char *dflt_taskclass_name = TASK_CLASS_TYPE_NAME;
+
+static struct ckrm_core_class *ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name);
+static int ckrm_free_task_class(struct ckrm_core_class *core);
+
+static int tc_forced_reclassify(ckrm_core_class_t *target, const char *resname);
+static int tc_show_members(struct ckrm_core_class *core, struct seq_file *seq);
+static void tc_add_resctrl(struct ckrm_core_class *core, int resid);
+
+struct ckrm_classtype CT_taskclass = {
+ .mfidx = TC_MF_IDX,
+ .name = TASK_CLASS_TYPE_NAME,
+ .typeID = CKRM_CLASSTYPE_TASK_CLASS,
+ .maxdepth = 3, // Hubertus .. just to start
+ .resid_reserved = 4, // Hubertus .. reservation
+ .max_res_ctlrs = CKRM_MAX_RES_CTLRS,
+ .max_resid = 0,
+ .bit_res_ctlrs = 0L,
+ .res_ctlrs_lock = SPIN_LOCK_UNLOCKED,
+ .classes = LIST_HEAD_INIT(CT_taskclass.classes),
+
+ .default_class = &taskclass_dflt_class.core,
+
+ // private version of functions
+ .alloc = &ckrm_alloc_task_class,
+ .free = &ckrm_free_task_class,
+ .show_members = &tc_show_members,
+ .forced_reclassify = &tc_forced_reclassify,
+
+ // use of default functions
+ .show_shares = &ckrm_class_show_shares,
+ .show_stats = &ckrm_class_show_stats,
+ .show_config = &ckrm_class_show_config,
+ .set_config = &ckrm_class_set_config,
+ .set_shares = &ckrm_class_set_shares,
+ .reset_stats = &ckrm_class_reset_stats,
+
+ // mandatory private version .. no dflt available
+ .add_resctrl = &tc_add_resctrl,
+};
+
+/**************************************************************************
+ * Helper Functions *
+ **************************************************************************/
+
+static inline void
+ckrm_init_task_lock(struct task_struct *tsk)
+{
+ tsk->ckrm_tsklock = SPIN_LOCK_UNLOCKED;
+}
+
+// Hubertus .. following functions should move to ckrm_rc.h
+
+static inline void
+ckrm_task_lock(struct task_struct *tsk)
+{
+ spin_lock(&tsk->ckrm_tsklock);
+}
+
+static inline void
+ckrm_task_unlock(struct task_struct *tsk)
+{
+ spin_unlock(&tsk->ckrm_tsklock);
+}
+
+/*
+ * Change the task class of the given task.
+ *
+ * Change the task's task class to "newcls" if the task's current
+ * class (task->taskclass) is same as given "oldcls", if it is non-NULL.
+ *
+ * Caller is responsible to make sure the task structure stays put through
+ * this function.
+ *
+ * This function should be called with the following locks NOT held
+ * - tsk->ckrm_task_lock
+ * - core->ckrm_lock, if core is NULL then ckrm_dflt_class.ckrm_lock
+ * - tsk->taskclass->ckrm_lock
+ *
+ * Function is also called with a ckrm_core_grab on the new core, hence
+ * it needs to be dropped if no assignment takes place.
+ */
+
+static void
+ckrm_set_taskclass(struct task_struct *tsk, ckrm_task_class_t *newcls,
+ ckrm_task_class_t *oldcls, enum ckrm_event event)
+{
+ int i;
+ ckrm_classtype_t *clstype;
+ ckrm_res_ctlr_t *rcbs;
+ ckrm_task_class_t *curcls;
+ void *old_res_class, *new_res_class;
+ int drop_old_cls;
+
+ ckrm_task_lock(tsk);
+ curcls = tsk->taskclass;
+
+ // check whether compare_and_exchange should
+ if (oldcls && (oldcls != curcls)) {
+ ckrm_task_unlock(tsk);
+ if (newcls) {
+ /* compensate for previous grab */
+ printk("ckrm_set_taskclass(%s:%d): Race-condition caught <%s> %d\n",
+ tsk->comm,tsk->pid,class_core(newcls)->name,event);
+ ckrm_core_drop(class_core(newcls));
+ }
+ return;
+ }
+
+ // make sure we have a real destination core
+ if (!newcls) {
+ newcls = &taskclass_dflt_class;
+ ckrm_core_grab(class_core(newcls));
+ }
+
+ // take out of old class
+ // remember that we need to drop the oldcore
+ if ((drop_old_cls = (curcls != NULL))) {
+ class_lock(class_core(curcls));
+ if (newcls == curcls) {
+ // we are already in the destination class.
+ // we still need to drop oldcore
+ class_unlock(class_core(curcls));
+ ckrm_task_unlock(tsk);
+ goto out;
+ }
+ list_del(&tsk->taskclass_link);
+ INIT_LIST_HEAD(&tsk->taskclass_link);
+ tsk->taskclass = NULL;
+ class_unlock(class_core(curcls));
+ }
+
+ // put into new class
+ class_lock(class_core(newcls));
+ tsk->taskclass = newcls;
+ list_add(&tsk->taskclass_link, &class_core(newcls)->objlist);
+ class_unlock(class_core(newcls));
+
+ if (newcls == curcls) {
+ ckrm_task_unlock(tsk);
+ goto out;
+ }
+
+ CE_NOTIFY(&CT_taskclass,event,newcls,tsk);
+
+ ckrm_task_unlock(tsk);
+
+ clstype = class_isa(newcls); // Hubertus .. can hardcode ckrm_CT_taskclass
+ for (i = 0; i < clstype->max_resid; i++) {
+ atomic_inc(&clstype->nr_resusers[i]);
+ old_res_class = curcls ? class_core(curcls)->res_class[i] : NULL;
+ new_res_class = newcls ? class_core(newcls)->res_class[i] : NULL;
+ rcbs = clstype->res_ctlrs[i];
+ if (rcbs && rcbs->change_resclass && (old_res_class != new_res_class))
+ (*rcbs->change_resclass)(tsk, old_res_class, new_res_class);
+ atomic_dec(&clstype->nr_resusers[i]);
+ }
+
+ out:
+ if (drop_old_cls)
+ ckrm_core_drop(class_core(curcls));
+ return;
+}
+
+// HF SUGGEST: we could macro-tize this for other types DEF_FUNC_ADD_RESCTRL(funcname,link)
+// would DEF_FUNC_ADD_RESCTRL(tc_add_resctrl,taskclass_link)
+
+static void
+tc_add_resctrl(struct ckrm_core_class *core, int resid)
+{
+ struct task_struct *tsk;
+ struct ckrm_res_ctlr *rcbs;
+
+ if ((resid < 0) || (resid >= CKRM_MAX_RES_CTLRS) || ((rcbs = core->classtype->res_ctlrs[resid]) == NULL))
+ return;
+
+ spin_lock(&core->ckrm_lock);
+ list_for_each_entry(tsk, &core->objlist, taskclass_link) {
+ if (rcbs->change_resclass)
+ (*rcbs->change_resclass)(tsk, (void *) -1, core->res_class[resid]);
+ }
+ spin_unlock(&core->ckrm_lock);
+}
+
+
+/**************************************************************************
+ * Functions called from classification points *
+ **************************************************************************/
+
+#define ECB_PRINTK(fmt, args...) // do { if (CT_taskclass.ce_regd) printk("%s: " fmt, __FUNCTION__ , ## args); } while (0)
+
+#define CE_CLASSIFY_TASK(event, tsk) \
+do { \
+ struct ckrm_task_class *newcls = NULL, *oldcls = tsk->taskclass; \
+ \
+ CE_CLASSIFY_RET(newcls,&CT_taskclass,event,tsk); \
+ if (newcls) { \
+ /* called synchrously. no need to get task struct */ \
+ ckrm_set_taskclass(tsk, newcls, oldcls, event); \
+ } \
+} while (0)
+
+#define CE_CLASSIFY_TASK_PROTECT(event, tsk) \
+do { \
+ ce_protect(&CT_taskclass); \
+ CE_CLASSIFY_TASK(event,tsk); \
+ ce_release(&CT_taskclass); \
+} while (0)
+
+
+
+
+static void
+cb_taskclass_newtask(struct task_struct *tsk)
+{
+ tsk->taskclass = NULL;
+ INIT_LIST_HEAD(&tsk->taskclass_link);
+}
+
+
+static void
+cb_taskclass_fork(struct task_struct *tsk)
+{
+ struct ckrm_task_class *cls = NULL;
+
+ ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm);
+
+ ce_protect(&CT_taskclass);
+ CE_CLASSIFY_RET(cls,&CT_taskclass,CKRM_EVENT_FORK,tsk);
+ if (cls == NULL) {
+ ckrm_task_lock(tsk->parent);
+ cls = tsk->parent->taskclass;
+ ckrm_core_grab(class_core(cls));
+ ckrm_task_unlock(tsk->parent);
+ }
+ if (!list_empty(&tsk->taskclass_link))
+ printk("BUG in cb_fork.. tsk (%s:%d> already linked\n",
+ tsk->comm,tsk->pid);
+
+ ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_FORK);
+ ce_release(&CT_taskclass);
+}
+
+static void
+cb_taskclass_exit(struct task_struct *tsk)
+{
+ ckrm_task_class_t *cls;
+
+ // Remove the task from the current core class
+
+ ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm);
+ ckrm_task_lock(tsk);
+
+ CE_CLASSIFY_NORET( &CT_taskclass, CKRM_EVENT_EXIT, tsk);
+
+ if ((cls = tsk->taskclass) != NULL) {
+ class_lock(class_core(cls));
+ tsk->taskclass = NULL;
+ list_del(&tsk->taskclass_link);
+ class_unlock(class_core(cls));
+ ckrm_core_drop(class_core(cls));
+ } else {
+ INIT_LIST_HEAD(&tsk->taskclass_link);
+ }
+ ckrm_task_unlock(tsk);
+}
+
+static void
+cb_taskclass_exec(const char *filename)
+{
+ ECB_PRINTK("%p:%d:%s <%s>\n",current,current->pid,current->comm,filename);
+ CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_EXEC, current);
+}
+
+static void
+cb_taskclass_uid(void)
+{
+ ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm);
+ CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_UID, current);
+}
+
+static void
+cb_taskclass_gid(void)
+{
+ ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm);
+ CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_GID, current);
+}
+
+static struct ckrm_event_spec taskclass_events_callbacks[] = {
+ CKRM_EVENT_SPEC( NEWTASK, cb_taskclass_newtask ),
+ CKRM_EVENT_SPEC( EXEC , cb_taskclass_exec ),
+ CKRM_EVENT_SPEC( FORK , cb_taskclass_fork ),
+ CKRM_EVENT_SPEC( EXIT , cb_taskclass_exit ),
+ CKRM_EVENT_SPEC( UID , cb_taskclass_uid ),
+ CKRM_EVENT_SPEC( GID , cb_taskclass_gid ),
+ { -1 }
+};
+
+/***********************************************************************
+ *
+ * Asynchronous callback functions (driven by RCFS)
+ *
+ * Async functions force a setting of the task structure
+ * synchronous callbacks are protected against race conditions
+ * by using a cmpxchg on the core before setting it.
+ * Async calls need to be serialized to ensure they can't
+ * race against each other
+ *
+ ***********************************************************************/
+
+DECLARE_MUTEX(async_serializer); // serialize all async functions
+
+
+/*
+ * Go through the task list and reclassify all tasks according to the current
+ * classification rules.
+ *
+ * We have the problem that we can not hold any lock (including the
+ * tasklist_lock) while classifying. Two methods possible
+ *
+ * (a) go through entire pidrange (0..pidmax) and if a task exists at
+ * that pid then reclassify it
+ * (b) go several time through task list and build a bitmap for a particular
+ * subrange of pid otherwise the memory requirements ight be too much.
+ *
+ * We use a hybrid by comparing ratio nr_threads/pidmax
+ */
+
+static void
+ckrm_reclassify_all_tasks(void)
+{
+ extern int pid_max;
+
+ struct task_struct *proc, *thread;
+ int i;
+ int curpidmax = pid_max;
+ int ratio;
+ int use_bitmap;
+
+
+ ratio = curpidmax / nr_threads;
+ if (curpidmax <= PID_MAX_DEFAULT) {
+ use_bitmap = 1;
+ } else {
+ use_bitmap = (ratio >= 2);
+ }
+
+ ce_protect(&CT_taskclass);
+
+ retry:
+ if (use_bitmap == 0) {
+ // go through it in one walk
+ read_lock(&tasklist_lock);
+ for ( i=0 ; i<curpidmax ; i++ ) {
+ if ((thread = find_task_by_pid(i)) == NULL)
+ continue;
+ get_task_struct(thread);
+ read_unlock(&tasklist_lock);
+ CE_CLASSIFY_TASK(CKRM_EVENT_RECLASSIFY, thread);
+ put_task_struct(thread);
+ read_lock(&tasklist_lock);
+ }
+ read_unlock(&tasklist_lock);
+ } else {
+ unsigned long *bitmap;
+ int bitmapsize;
+ int order = 0;
+ int num_loops;
+ int pid, do_next;
+
+
+ bitmap = (unsigned long*) __get_free_pages(GFP_KERNEL,order);
+ if (bitmap == NULL) {
+ use_bitmap = 0;
+ goto retry;
+ }
+
+ bitmapsize = 8 * (1 << (order + PAGE_SHIFT));
+ num_loops = (curpidmax + bitmapsize - 1) / bitmapsize;
+
+ do_next = 1;
+ for ( i=0 ; i < num_loops && do_next; i++) {
+ int pid_start = i*bitmapsize;
+ int pid_end = pid_start + bitmapsize;
+ int num_found = 0;
+ int pos;
+
+ memset(bitmap, 0, bitmapsize/8); // start afresh
+ do_next = 0;
+
+ read_lock(&tasklist_lock);
+ do_each_thread(proc, thread) {
+ pid = thread->pid;
+ if ((pid < pid_start) || (pid >= pid_end)) {
+ if (pid >= pid_end) {
+ do_next = 1;
+ }
+ continue;
+ }
+ pid -= pid_start;
+ set_bit(pid, bitmap);
+ num_found++;
+ } while_each_thread(proc, thread);
+ read_unlock(&tasklist_lock);
+
+ if (num_found == 0)
+ continue;
+
+ pos = 0;
+ for ( ; num_found-- ; ) {
+ pos = find_next_bit(bitmap, bitmapsize, pos);
+ pid = pos + pid_start;
+
+ read_lock(&tasklist_lock);
+ if ((thread = find_task_by_pid(pid)) != NULL) {
+ get_task_struct(thread);
+ read_unlock(&tasklist_lock);
+ CE_CLASSIFY_TASK(CKRM_EVENT_RECLASSIFY, thread);
+ put_task_struct(thread);
+ } else {
+ read_unlock(&tasklist_lock);
+ }
+ }
+ }
+
+ }
+ ce_release(&CT_taskclass);
+}
+
+int
+ckrm_reclassify(int pid)
+{
+ struct task_struct *tsk;
+ int rc = 0;
+
+ down(&async_serializer); // protect again race condition
+ if (pid < 0) {
+ // do we want to treat this as process group .. should YES ToDo
+ rc = -EINVAL;
+ } else if (pid == 0) {
+ // reclassify all tasks in the system
+ ckrm_reclassify_all_tasks();
+ } else {
+ // reclassify particular pid
+ read_lock(&tasklist_lock);
+ if ((tsk = find_task_by_pid(pid)) != NULL) {
+ get_task_struct(tsk);
+ read_unlock(&tasklist_lock);
+ CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_RECLASSIFY, tsk);
+ put_task_struct(tsk);
+ } else {
+ read_unlock(&tasklist_lock);
+ rc = -EINVAL;
+ }
+ }
+ up(&async_serializer);
+ return rc;
+}
+
+/*
+ * Reclassify all tasks in the given core class.
+ */
+
+static void
+ckrm_reclassify_class_tasks(struct ckrm_task_class *cls)
+{
+ int ce_regd;
+ struct ckrm_hnode *cnode;
+ struct ckrm_task_class *parcls;
+
+ if (!ckrm_validate_and_grab_core(&cls->core))
+ return;
+
+ down(&async_serializer); // protect again race condition
+
+
+ printk("\t%s: start %p:%s:%d\n",__FUNCTION__,cls,cls->core.name, cls->core.refcnt);
+ // If no CE registered for this classtype, following will be needed repeatedly;
+ ce_regd = class_core(cls)->classtype->ce_regd;
+ cnode = &(class_core(cls)->hnode);
+ parcls = class_type(ckrm_task_class_t, cnode->parent);
+
+next_task:
+ class_lock(class_core(cls));
+ if (!list_empty(&class_core(cls)->objlist)) {
+ struct ckrm_task_class *newcls = NULL;
+ struct task_struct *tsk =
+ list_entry(class_core(cls)->objlist.next,
+ struct task_struct, taskclass_link);
+
+ get_task_struct(tsk);
+ class_unlock(class_core(cls));
+
+ if (ce_regd) {
+ CE_CLASSIFY_RET(newcls,&CT_taskclass,CKRM_EVENT_RECLASSIFY,tsk);
+ } else {
+ newcls = parcls;
+ ckrm_core_grab(class_core(newcls));
+ }
+
+ if (cls == newcls) {
+ // don't allow reclassifying to the same class
+ // as we are in the process of cleaning up this class
+ ckrm_core_drop(class_core(newcls)); // to compensate CE's grab
+ newcls = NULL;
+ }
+ ckrm_set_taskclass(tsk, newcls, cls, CKRM_EVENT_RECLASSIFY);
+ put_task_struct(tsk);
+ goto next_task;
+ }
+ printk("\t%s: stop %p:%s:%d\n",__FUNCTION__,cls,cls->core.name, cls->core.refcnt);
+ ckrm_core_drop(class_core(cls));
+ class_unlock(class_core(cls));
+
+ up(&async_serializer);
+
+ return ;
+}
+
+/*
+ * Change the core class of the given task.
+ */
+
+int
+ckrm_forced_reclassify_pid(pid_t pid, struct ckrm_task_class *cls)
+{
+ struct task_struct *tsk;
+
+ if (!ckrm_validate_and_grab_core(class_core(cls)))
+ return - EINVAL;
+
+ read_lock(&tasklist_lock);
+ if ((tsk = find_task_by_pid(pid)) == NULL) {
+ read_unlock(&tasklist_lock);
+ return -EINVAL;
+ }
+ get_task_struct(tsk);
+ read_unlock(&tasklist_lock);
+
+ down(&async_serializer); // protect again race condition
+
+ ce_protect(&CT_taskclass);
+ ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_MANUAL);
+ ce_release(&CT_taskclass);
+ put_task_struct(tsk);
+
+ up(&async_serializer);
+ return 0;
+}
+
+static struct ckrm_core_class *
+ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name)
+{
+ struct ckrm_task_class *taskcls;
+ taskcls = kmalloc(sizeof(struct ckrm_task_class), GFP_KERNEL);
+ if (taskcls == NULL)
+ return NULL;
+
+ ckrm_init_core_class(&CT_taskclass,
+ class_core(taskcls),parent,name);
+
+ ce_protect(&CT_taskclass);
+ if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_add)
+ (*CT_taskclass.ce_callbacks.class_add)(name,taskcls);
+ ce_release(&CT_taskclass);
+
+ return class_core(taskcls);
+}
+
+static int
+ckrm_free_task_class(struct ckrm_core_class *core)
+{
+ struct ckrm_task_class *taskcls;
+
+ if (!ckrm_is_core_valid(core)) {
+ // Invalid core
+ return (-EINVAL);
+ }
+ if (core == core->classtype->default_class) {
+ // reset the name tag
+ core->name = dflt_taskclass_name;
+ return 0;
+ }
+
+ printk("%s: stop %p:%s:%d\n",__FUNCTION__,core,core->name, core->refcnt);
+ taskcls = class_type(struct ckrm_task_class, core);
+
+ ce_protect(&CT_taskclass);
+
+ if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_delete)
+ (*CT_taskclass.ce_callbacks.class_delete)(core->name,taskcls);
+ ckrm_reclassify_class_tasks( taskcls );
+
+ ce_release(&CT_taskclass);
+
+ ckrm_release_core_class(core); // Hubertus .... could just drop the class .. error message
+ return 0;
+}
+
+
+void __init
+ckrm_meta_init_taskclass(void)
+{
+ printk("...... Initializing ClassType<%s> ........\n",CT_taskclass.name);
+ // intialize the default class
+ ckrm_init_core_class(&CT_taskclass, class_core(&taskclass_dflt_class),
+ NULL,dflt_taskclass_name);
+
+ // register classtype and initialize default task class
+ ckrm_register_classtype(&CT_taskclass);
+ ckrm_register_event_set(taskclass_events_callbacks);
+
+ // note registeration of all resource controllers will be done later dynamically
+ // as these are specified as modules
+}
+
+
+
+static int
+tc_show_members(struct ckrm_core_class *core, struct seq_file *seq)
+{
+ struct list_head *lh;
+ struct task_struct *tsk;
+
+ spin_lock(&core->ckrm_lock);
+ list_for_each(lh, &core->objlist) {
+ tsk = container_of(lh, struct task_struct, taskclass_link);
+ seq_printf(seq,"%ld\n", (long)tsk->pid);
+ }
+ spin_unlock(&core->ckrm_lock);
+
+ return 0;
+}
+
+static int
+tc_forced_reclassify(struct ckrm_core_class *target,const char *obj)
+{
+ pid_t pid;
+ int rc = -EINVAL;
+
+ pid = (pid_t) simple_strtoul(obj,NULL,10);
+ if (pid > 0) {
+ rc = ckrm_forced_reclassify_pid(pid,
+ class_type(ckrm_task_class_t,target));
+ }
+ return rc;
+}
+
+#if 1
+
+/***************************************************************************************
+ * Debugging Task Classes: Utility functions
+ **************************************************************************************/
+
+void
+check_tasklist_sanity(struct ckrm_task_class *cls)
+{
+ struct ckrm_core_class *core = class_core(cls);
+ struct list_head *lh1, *lh2;
+ int count = 0;
+
+ if (core) {
+ class_lock(core);
+ if (list_empty(&core->objlist)) {
+ class_lock(core);
+ printk("check_tasklist_sanity: class %s empty list\n",
+ core->name);
+ return;
+ }
+ list_for_each_safe(lh1, lh2, &core->objlist) {
+ struct task_struct *tsk = container_of(lh1, struct task_struct, taskclass_link);
+ if (count++ > 20000) {
+ printk("list is CORRUPTED\n");
+ break;
+ }
+ if (tsk->taskclass != cls) {
+ const char *tclsname;
+ tclsname = (tsk->taskclass) ? class_core(tsk->taskclass)->name
+ : "NULL";
+ printk("sanity: task %s:%d has ckrm_core |%s| but in list |%s|\n",
+ tsk->comm,tsk->pid,tclsname,core->name);
+ }
+ }
+ class_unlock(core);
+ }
+}
+
+void
+ckrm_debug_free_task_class(struct ckrm_task_class *tskcls)
+{
+ struct task_struct *proc, *thread;
+ int count = 0;
+
+ printk("Analyze Error <%s> %d\n",
+ class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt)));
+
+ read_lock(&tasklist_lock);
+ class_lock(class_core(tskcls));
+ do_each_thread(proc, thread) {
+ count += (tskcls == thread->taskclass);
+ if ((thread->taskclass == tskcls) || (tskcls == NULL)) {
+ const char *tclsname;
+ tclsname = (thread->taskclass) ? class_core(thread->taskclass)->name : "NULL";
+ printk("%d thread=<%s:%d> -> <%s> <%lx>\n",
+ count,thread->comm,thread->pid,tclsname, thread->flags & PF_EXITING);
+ }
+ } while_each_thread(proc, thread);
+ class_unlock(class_core(tskcls));
+ read_unlock(&tasklist_lock);
+
+ printk("End Analyze Error <%s> %d\n",
+ class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt)));
+}
+
+#endif
diff -Nru a/fs/rcfs/tc_magic.c b/fs/rcfs/tc_magic.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/fs/rcfs/tc_magic.c Wed Apr 28 22:41:05 2004
@@ -0,0 +1,94 @@
+/*
+ * fs/rcfs/tc_magic.c
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2004
+ * (C) Vivek Kashyap, IBM Corp. 2004
+ * (C) Chandra Seetharaman, IBM Corp. 2004
+ * (C) Hubertus Franke, IBM Corp. 2004
+ *
+ *
+ * define magic fileops for taskclass classtype
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/* Changes
+ *
+ * 23 Apr 2004
+ * Created.
+ *
+ */
+
+#include <linux/rcfs.h>
+#include <linux/ckrm_tc.h>
+
+
+/*******************************************************************************
+ * Taskclass general
+ *
+ * Define structures for taskclass root directory and its magic files
+ * In taskclasses, there is one set of magic files, created automatically under
+ * the taskclass root (upon classtype registration) and each directory (class)
+ * created subsequently. However, classtypes can also choose to have different
+ * sets of magic files created under their root and other directories under root
+ * using their mkdir function. RCFS only provides helper functions for creating
+ * the root directory and its magic files
+ *
+ *******************************************************************************/
+
+#define TC_FILE_MODE (S_IFREG | S_IRUGO | S_IWUSR)
+
+#define NR_TCROOTMF 6
+struct rcfs_magf tc_rootdesc[NR_TCROOTMF] = {
+ /* First entry must be root */
+ {
+// .name = should not be set, copy from classtype name
+ .mode = RCFS_DEFAULT_DIR_MODE,
+ .i_op = &rcfs_dir_inode_operations,
+ .i_fop = &simple_dir_operations,
+ },
+ /* Rest are root's magic files */
+ {
+ .name = "target",
+ .mode = TC_FILE_MODE,
+ .i_fop = &target_fileops,
+ .i_op = &rcfs_file_inode_operations,
+ },
+ {
+ .name = "config",
+ .mode = TC_FILE_MODE,
+ .i_fop = &config_fileops,
+ .i_op = &rcfs_file_inode_operations,
+ },
+ {
+ .name = "members",
+ .mode = TC_FILE_MODE,
+ .i_fop = &members_fileops,
+ .i_op = &rcfs_file_inode_operations,
+ },
+ {
+ .name = "stats",
+ .mode = TC_FILE_MODE,
+ .i_fop = &stats_fileops,
+ .i_op = &rcfs_file_inode_operations,
+ },
+ {
+ .name = "shares",
+ .mode = TC_FILE_MODE,
+ .i_fop = &shares_fileops,
+ .i_op = &rcfs_file_inode_operations,
+ },
+};
+
+struct rcfs_mfdesc tc_mfdesc = {
+ .rootmf = tc_rootdesc,
+ .rootmflen = NR_TCROOTMF,
+};
+
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-04-29 8:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-29 8:25 [PATCH 3/6] CKRM task_class classtype Shailabh Nagar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.