1 /* kernel/ckrm/ckrm_null_class.c - NULL TaskClass controller for CKRM
3 * Copyright (C) Haoqiang Zheng, IBM Corp. 2004
4 * (C) Hubertus Franke, IBM Corp. 2004
6 * Copyright (C) Marc E. Fiuczynski, Princeton University 2005
7 * Adapted from ckrm_cpu_class.c.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <asm/errno.h>
19 #include <linux/ckrm_events.h>
20 #include <linux/ckrm_rc.h>
21 #include <linux/ckrm_tc.h>
22 #include <linux/ckrm_classqueue.h>
23 #include <linux/seq_file.h>
25 #define CKRM_NULL_CLASS_MAGIC 0xdeadbeef
27 static struct ckrm_res_ctlr null_rcbs;
30 * manages the class status
31 * there should be only one instance of this object for each class in the whole system
33 struct ckrm_null_class {
34 struct ckrm_core_class *core;
35 struct ckrm_core_class *parent;
36 struct ckrm_shares shares;
37 spinlock_t cnt_lock; // always grab parent's lock first and then child's
38 unsigned long magic; //for debugging
42 * initialize a class object and its local queues
44 static void init_null_class(struct ckrm_null_class *cls,ckrm_shares_t* shares)
46 cls->shares = *shares;
47 cls->cnt_lock = SPIN_LOCK_UNLOCKED;
48 cls->magic = CKRM_NULL_CLASS_MAGIC;
51 static inline void set_default_share(ckrm_shares_t *shares)
53 shares->my_guarantee = 0;
54 shares->total_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE;
55 shares->unused_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE;
56 shares->my_limit = CKRM_SHARE_DFLT_MAX_LIMIT;
57 shares->max_limit = CKRM_SHARE_DFLT_MAX_LIMIT;
58 shares->cur_max_limit = 0;
61 static inline int valid_null_class(struct ckrm_null_class * cls)
63 return (cls && cls->magic == CKRM_NULL_CLASS_MAGIC);
67 static struct ckrm_null_class * ckrm_get_null_class(struct ckrm_core_class *core)
69 struct ckrm_null_class * cls;
70 cls = ckrm_get_res_class(core, null_rcbs.resid, struct ckrm_null_class);
71 if (valid_null_class(cls))
78 static struct ckrm_null_class default_null_class_obj;
80 static struct ckrm_null_class * get_default_null_class(void) {
81 return (&default_null_class_obj);
85 static void* ckrm_alloc_null_class(struct ckrm_core_class *core, struct ckrm_core_class *parent)
87 struct ckrm_null_class *cls;
89 if (! parent) /*root class*/
90 cls = get_default_null_class();
92 cls = (struct ckrm_null_class *) kmalloc(sizeof(struct ckrm_null_class),GFP_ATOMIC);
96 if ((! parent) && (core)) {
98 * the default class is already initialized
99 * so only update the core structure
103 set_default_share(&shares);
104 init_null_class(cls,&shares);
106 cls->parent = parent;
109 printk(KERN_ERR"alloc_null_class failed\n");
115 * hzheng: this is not a stable implementation
116 * need to check race condition issue here
118 static void ckrm_free_null_class(void *my_res)
120 struct ckrm_null_class *cls = my_res, *parres, *childres;
121 ckrm_core_class_t *child = NULL;
127 /*the default class can't be freed*/
128 if (cls == get_default_null_class())
131 // Assuming there will be no children when this function is called
132 parres = ckrm_get_null_class(cls->parent);
134 // return child's limit/guarantee to parent node
135 spin_lock(&parres->cnt_lock);
136 child_guarantee_changed(&parres->shares, cls->shares.my_guarantee, 0);
138 // run thru parent's children and get the new max_limit of the parent
139 ckrm_lock_hier(parres->core);
141 while ((child = ckrm_get_next_child(parres->core, child)) != NULL) {
142 childres = ckrm_get_null_class(child);
143 if (maxlimit < childres->shares.my_limit) {
144 maxlimit = childres->shares.my_limit;
147 ckrm_unlock_hier(parres->core);
148 if (parres->shares.cur_max_limit < maxlimit) {
149 parres->shares.cur_max_limit = maxlimit;
152 spin_unlock(&parres->cnt_lock);
157 * the system will adjust to the new share automatically
159 static int ckrm_null_set_share(void *my_res, struct ckrm_shares *new_share)
161 struct ckrm_null_class *parres, *cls = my_res;
162 struct ckrm_shares *cur = &cls->shares, *par;
169 parres = ckrm_get_null_class(cls->parent);
170 spin_lock(&parres->cnt_lock);
171 spin_lock(&cls->cnt_lock);
172 par = &parres->shares;
174 spin_lock(&cls->cnt_lock);
180 * hzheng: CKRM_SHARE_DONTCARE should be handled
182 if (new_share->my_guarantee == CKRM_SHARE_DONTCARE)
183 new_share->my_guarantee = 0;
185 rc = set_shares(new_share, cur, par);
186 if (cur->my_limit == CKRM_SHARE_DONTCARE)
187 cur->my_limit = cur->max_limit;
190 spin_unlock(&cls->cnt_lock);
192 spin_unlock(&parres->cnt_lock);
198 static int ckrm_null_get_share(void *my_res,
199 struct ckrm_shares *shares)
201 struct ckrm_null_class *cls = my_res;
205 *shares = cls->shares;
209 static int ckrm_null_get_stats(void *my_res, struct seq_file * sfile)
211 struct ckrm_null_class *cls = my_res;
216 seq_printf(sfile, "-------- Null Class Status Start---------\n");
217 seq_printf(sfile, "Share:\n\tgrt= %d limit= %d total_grt= %d max_limit= %d\n",
218 cls->shares.my_guarantee,
219 cls->shares.my_limit,
220 cls->shares.total_guarantee,
221 cls->shares.max_limit);
222 seq_printf(sfile, "\tunused_grt= %d cur_max_limit= %d\n",
223 cls->shares.unused_guarantee,
224 cls->shares.cur_max_limit);
226 seq_printf(sfile, "-------- Null Class Status END ---------\n");
232 * task will remain in the same null but on a different local runqueue
234 static void ckrm_null_change_class(void *task, void *old, void *new)
237 if (!task || ! old || !new)
240 /* hook to controller */
243 /*dummy function, not used*/
244 static int ckrm_null_show_config(void *my_res, struct seq_file *sfile)
246 struct ckrm_null_class *cls = my_res;
251 seq_printf(sfile, "cls=%s,parameter=somevalue\n","ckrm_null class");
255 /*dummy function, not used*/
256 static int ckrm_null_set_config(void *my_res, const char *cfgstr)
258 struct ckrm_nullclass *cls = my_res;
262 printk(KERN_DEBUG "ckrm_null config='%s'\n",cfgstr);
266 static struct ckrm_res_ctlr null_rcbs = {
270 .res_alloc = ckrm_alloc_null_class,
271 .res_free = ckrm_free_null_class,
272 .set_share_values = ckrm_null_set_share,
273 .get_share_values = ckrm_null_get_share,
274 .get_stats = ckrm_null_get_stats,
275 .show_config = ckrm_null_show_config,
276 .set_config = ckrm_null_set_config,
277 .change_resclass = ckrm_null_change_class,
280 int __init init_ckrm_null_res(void)
282 struct ckrm_classtype *clstype;
283 int resid = null_rcbs.resid;
285 clstype = ckrm_find_classtype_by_name("taskclass");
286 if (clstype == NULL) {
287 printk(KERN_INFO" Unknown ckrm classtype<taskclass>");
291 /* Initialize default class obj before registering with core */
292 ckrm_alloc_null_class(NULL,NULL);
294 if (resid == -1) { /*not registered */
295 resid = ckrm_register_res_ctlr(clstype,&null_rcbs);
296 printk(KERN_DEBUG "........init_ckrm_null_res , resid= %d\n",resid);
301 void __exit exit_ckrm_null_res(void)
303 ckrm_unregister_res_ctlr(&null_rcbs);
304 null_rcbs.resid = -1;
307 module_init(init_ckrm_null_res)
308 module_exit(exit_ckrm_null_res)