1 /* ckrm.c - Class-based Kernel Resource Management (CKRM)
3 * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004
4 * (C) Shailabh Nagar, IBM Corp. 2003, 2004
5 * (C) Chandra Seetharaman, IBM Corp. 2003
6 * (C) Vivek Kashyap, IBM Corp. 2004
9 * Provides kernel API of CKRM for in-kernel,per-resource controllers
10 * (one each for cpu, memory, io, network) and callbacks for
11 * classification modules.
13 * Latest version, more details at http://ckrm.sf.net
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
27 * Made modifications to suit the new RBCE module.
29 * Fixed a bug in fork and exit callbacks. Added callbacks_active and
30 * surrounding logic. Added task paramter for all CE callbacks.
32 * moved to referenced counted class objects and correct locking
34 * Integrated ckrm hooks, classtypes, ...
38 #include <linux/config.h>
39 #include <linux/init.h>
40 #include <linux/linkage.h>
41 #include <linux/kernel.h>
42 #include <linux/errno.h>
43 #include <asm/uaccess.h>
45 #include <asm/errno.h>
46 #include <linux/string.h>
47 #include <linux/list.h>
48 #include <linux/spinlock.h>
49 #include <linux/module.h>
50 #include <linux/ckrm_rc.h>
51 #include <linux/rcfs.h>
55 rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; // protect classlists
57 struct rcfs_functions rcfs_fn;
58 EXPORT_SYMBOL(rcfs_fn);
60 // rcfs state needed by another module
62 EXPORT_SYMBOL(rcfs_engine_regd);
65 EXPORT_SYMBOL(rcfs_mounted);
67 /**************************************************************************
69 **************************************************************************/
72 * Return TRUE if the given core class pointer is valid.
76 * Return TRUE if the given resource is registered.
78 inline unsigned int is_res_regd(struct ckrm_classtype *clstype, int resid)
80 return ((resid >= 0) && (resid < clstype->max_resid) &&
81 test_bit(resid, &clstype->bit_res_ctlrs)
85 struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *clstype,
90 if (!clstype || !resname) {
93 for (resid = 0; resid < clstype->max_resid; resid++) {
94 if (test_bit(resid, &clstype->bit_res_ctlrs)) {
95 struct ckrm_res_ctlr *rctrl = clstype->res_ctlrs[resid];
96 if (!strncmp(resname, rctrl->res_name,
104 EXPORT_SYMBOL(ckrm_resctlr_lookup);
106 /* given a classname return the class handle and its classtype*/
107 void *ckrm_classobj(char *classname, int *classTypeID)
112 if (!classname || !*classname) {
116 read_lock(&ckrm_class_lock);
117 for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
118 struct ckrm_classtype *ctype = ckrm_classtypes[i];
119 struct ckrm_core_class *core;
123 list_for_each_entry(core, &ctype->classes, clslist) {
124 if (core->name && !strcmp(core->name, classname)) {
125 // FIXME: should grep reference..
126 read_unlock(&ckrm_class_lock);
127 *classTypeID = ctype->typeID;
132 read_unlock(&ckrm_class_lock);
136 EXPORT_SYMBOL(is_res_regd);
137 EXPORT_SYMBOL(ckrm_classobj);
139 /**************************************************************************
140 * Internal Functions/macros *
141 **************************************************************************/
143 static inline void set_callbacks_active(struct ckrm_classtype *ctype)
145 ctype->ce_cb_active = ((atomic_read(&ctype->ce_regd) > 0) &&
146 (ctype->ce_callbacks.always_callback
147 || (ctype->num_classes > 1)));
150 int ckrm_validate_and_grab_core(struct ckrm_core_class *core)
153 read_lock(&ckrm_class_lock);
154 if (likely(ckrm_is_core_valid(core))) {
155 ckrm_core_grab(core);
158 read_unlock(&ckrm_class_lock);
162 /****************************************************************************
163 * Interfaces for classification engine *
164 ****************************************************************************/
167 * Registering a callback structure by the classification engine.
169 * Returns typeId of class on success -errno for failure.
171 int ckrm_register_engine(const char *typename, ckrm_eng_callback_t * ecbs)
173 struct ckrm_classtype *ctype;
175 ctype = ckrm_find_classtype_by_name(typename);
179 atomic_inc(&ctype->ce_regd);
181 /* another engine registered or trying to register ? */
182 if (atomic_read(&ctype->ce_regd) != 1) {
183 atomic_dec(&ctype->ce_regd);
187 /* One of the following must be set:
188 classify, class_delete (due to object reference) or
189 notify (case where notification supported but not classification)
190 The function pointer must be set the momement the mask is non-null
193 if (!(((ecbs->classify) && (ecbs->class_delete)) || (ecbs->notify)) ||
194 (ecbs->c_interest && ecbs->classify == NULL) ||
195 (ecbs->n_interest && ecbs->notify == NULL)) {
196 atomic_dec(&ctype->ce_regd);
200 ctype->ce_callbacks = *ecbs;
201 set_callbacks_active(ctype);
203 if (ctype->ce_callbacks.class_add) {
204 struct ckrm_core_class *core;
206 read_lock(&ckrm_class_lock);
208 list_for_each_entry(core, &ctype->classes, clslist) {
209 (*ctype->ce_callbacks.class_add) (core->name, core,
212 read_unlock(&ckrm_class_lock);
214 return ctype->typeID;
218 * Unregistering a callback structure by the classification engine.
220 * Returns 0 on success -errno for failure.
222 int ckrm_unregister_engine(const char *typename)
224 struct ckrm_classtype *ctype;
226 ctype = ckrm_find_classtype_by_name(typename);
230 ctype->ce_cb_active = 0;
232 if (atomic_read(&ctype->ce_nr_users) > 1) {
233 // Somebody is currently using the engine, cannot deregister.
237 atomic_set(&ctype->ce_regd, 0);
238 memset(&ctype->ce_callbacks, 0, sizeof(ckrm_eng_callback_t));
242 /****************************************************************************
243 * Interfaces to manipulate class (core or resource) hierarchies
244 ****************************************************************************/
249 ckrm_add_child(struct ckrm_core_class *parent, struct ckrm_core_class *child)
251 struct ckrm_hnode *cnode = &child->hnode;
253 if (!ckrm_is_core_valid(child)) {
254 printk(KERN_ERR "Invalid child %p given in ckrm_add_child\n",
260 INIT_LIST_HEAD(&cnode->children);
261 INIT_LIST_HEAD(&cnode->siblings);
264 struct ckrm_hnode *pnode;
266 if (!ckrm_is_core_valid(parent)) {
268 "Invalid parent %p given in ckrm_add_child\n",
272 pnode = &parent->hnode;
273 write_lock(&parent->hnode_rwlock);
274 list_add(&cnode->siblings, &pnode->children);
275 write_unlock(&parent->hnode_rwlock);
278 cnode->parent = parent;
285 static int ckrm_remove_child(struct ckrm_core_class *child)
287 struct ckrm_hnode *cnode, *pnode;
288 struct ckrm_core_class *parent;
290 if (!ckrm_is_core_valid(child)) {
291 printk(KERN_ERR "Invalid child %p given"
292 " in ckrm_remove_child\n",
297 cnode = &child->hnode;
298 parent = cnode->parent;
299 if (!ckrm_is_core_valid(parent)) {
300 printk(KERN_ERR "Invalid parent %p in ckrm_remove_child\n",
305 pnode = &parent->hnode;
308 /* ensure that the node does not have children */
309 if (!list_empty(&cnode->children)) {
313 write_lock(&parent->hnode_rwlock);
314 list_del(&cnode->siblings);
315 write_unlock(&parent->hnode_rwlock);
316 cnode->parent = NULL;
321 void ckrm_lock_hier(struct ckrm_core_class *parent)
323 if (ckrm_is_core_valid(parent)) {
324 read_lock(&parent->hnode_rwlock);
328 void ckrm_unlock_hier(struct ckrm_core_class *parent)
330 if (ckrm_is_core_valid(parent)) {
331 read_unlock(&parent->hnode_rwlock);
336 * hnode_rwlock of the parent core class must held in read mode.
337 * external callers should 've called ckrm_lock_hier before calling this
340 #define hnode_2_core(ptr) \
341 ((ptr)? container_of(ptr, struct ckrm_core_class, hnode) : NULL)
343 struct ckrm_core_class *ckrm_get_next_child(struct ckrm_core_class *parent,
344 struct ckrm_core_class *child)
346 struct list_head *cnode;
347 struct ckrm_hnode *next_cnode;
348 struct ckrm_core_class *next_childcore;
350 if (!ckrm_is_core_valid(parent)) {
351 printk(KERN_ERR "Invalid parent %p in ckrm_get_next_child\n",
355 if (list_empty(&parent->hnode.children)) {
360 if (!ckrm_is_core_valid(child)) {
362 "Invalid child %p in ckrm_get_next_child\n",
366 cnode = child->hnode.siblings.next;
368 cnode = parent->hnode.children.next;
371 if (cnode == &parent->hnode.children) { // back at the anchor
375 next_cnode = container_of(cnode, struct ckrm_hnode, siblings);
376 next_childcore = hnode_2_core(next_cnode);
378 if (!ckrm_is_core_valid(next_childcore)) {
380 "Invalid next child %p in ckrm_get_next_child\n",
384 return next_childcore;
387 EXPORT_SYMBOL(ckrm_lock_hier);
388 EXPORT_SYMBOL(ckrm_unlock_hier);
389 EXPORT_SYMBOL(ckrm_get_next_child);
392 ckrm_alloc_res_class(struct ckrm_core_class *core,
393 struct ckrm_core_class *parent, int resid)
396 struct ckrm_classtype *clstype;
399 * Allocate a resource class only if the resource controller has
400 * registered with core and the engine requests for the class.
403 if (!ckrm_is_core_valid(core))
406 clstype = core->classtype;
407 core->res_class[resid] = NULL;
409 if (test_bit(resid, &clstype->bit_res_ctlrs)) {
410 ckrm_res_ctlr_t *rcbs;
412 atomic_inc(&clstype->nr_resusers[resid]);
413 rcbs = clstype->res_ctlrs[resid];
415 if (rcbs && rcbs->res_alloc) {
416 core->res_class[resid] =
417 (*rcbs->res_alloc) (core, parent);
418 if (core->res_class[resid])
420 printk(KERN_ERR "Error creating res class\n");
422 atomic_dec(&clstype->nr_resusers[resid]);
427 * Initialize a core class
431 #define CLS_DEBUG(fmt, args...) \
432 do { /* printk("%s: " fmt, __FUNCTION__ , ## args); */ } while (0)
435 ckrm_init_core_class(struct ckrm_classtype *clstype,
436 struct ckrm_core_class *dcore,
437 struct ckrm_core_class *parent, const char *name)
439 // Hubertus ... should replace name with dentry or add dentry ?
442 // Hubertus .. how is this used in initialization
444 CLS_DEBUG("name %s => %p\n", name ? name : "default", dcore);
446 if ((dcore != clstype->default_class) && (!ckrm_is_core_valid(parent))){
447 printk("error not a valid parent %p\n", parent);
451 // Hubertus .. dynamic allocation still breaks when RCs registers.
452 // See def in ckrm_rc.h
453 dcore->res_class = NULL;
454 if (clstype->max_resid > 0) {
456 (void **)kmalloc(clstype->max_resid * sizeof(void *),
458 if (dcore->res_class == NULL) {
459 printk("error no mem\n");
465 dcore->classtype = clstype;
466 dcore->magic = CKRM_CORE_MAGIC;
468 dcore->class_lock = SPIN_LOCK_UNLOCKED;
469 dcore->hnode_rwlock = RW_LOCK_UNLOCKED;
472 atomic_set(&dcore->refcnt, 0);
473 write_lock(&ckrm_class_lock);
475 INIT_LIST_HEAD(&dcore->objlist);
476 list_add_tail(&dcore->clslist, &clstype->classes);
478 clstype->num_classes++;
479 set_callbacks_active(clstype);
481 write_unlock(&ckrm_class_lock);
482 ckrm_add_child(parent, dcore);
484 for (i = 0; i < clstype->max_resid; i++)
485 ckrm_alloc_res_class(dcore, parent, i);
487 // fix for race condition seen in stress with numtasks
489 ckrm_core_grab(parent);
491 ckrm_core_grab(dcore);
495 static void ckrm_free_res_class(struct ckrm_core_class *core, int resid)
498 * Free a resource class only if the resource controller has
499 * registered with core
501 if (core->res_class[resid]) {
502 ckrm_res_ctlr_t *rcbs;
503 struct ckrm_classtype *clstype = core->classtype;
505 atomic_inc(&clstype->nr_resusers[resid]);
506 rcbs = clstype->res_ctlrs[resid];
508 if (rcbs->res_free) {
509 (*rcbs->res_free) (core->res_class[resid]);
510 // compensate inc in alloc
511 atomic_dec(&clstype->nr_resusers[resid]);
513 atomic_dec(&clstype->nr_resusers[resid]);
515 core->res_class[resid] = NULL;
520 * requires that all tasks were previously reassigned to another class
522 * Returns 0 on success -errno on failure.
525 void ckrm_free_core_class(struct ckrm_core_class *core)
528 struct ckrm_classtype *clstype = core->classtype;
529 struct ckrm_core_class *parent = core->hnode.parent;
531 CLS_DEBUG("core=%p:%s parent=%p:%s\n", core, core->name, parent,
534 /* this core was marked as late */
535 printk("class <%s> finally deleted %lu\n", core->name, jiffies);
537 if (ckrm_remove_child(core) == 0) {
538 printk("Core class removal failed. Chilren present\n");
541 for (i = 0; i < clstype->max_resid; i++) {
542 ckrm_free_res_class(core, i);
545 write_lock(&ckrm_class_lock);
547 // Clear the magic, so we would know if this core is reused.
549 #if 0 // Dynamic not yet enabled
550 core->res_class = NULL;
552 // Remove this core class from its linked list.
553 list_del(&core->clslist);
554 clstype->num_classes--;
555 set_callbacks_active(clstype);
556 write_unlock(&ckrm_class_lock);
558 // fix for race condition seen in stress with numtasks
560 ckrm_core_drop(parent);
565 int ckrm_release_core_class(struct ckrm_core_class *core)
567 if (!ckrm_is_core_valid(core)) {
572 if (core == core->classtype->default_class)
575 /* need to make sure that the classgot really dropped */
576 if (atomic_read(&core->refcnt) != 1) {
577 CLS_DEBUG("class <%s> deletion delayed refcnt=%d jif=%ld\n",
578 core->name, atomic_read(&core->refcnt), jiffies);
579 core->delayed = 1; /* just so we have a ref point */
581 ckrm_core_drop(core);
585 /****************************************************************************
586 * Interfaces for the resource controller *
587 ****************************************************************************/
589 * Registering a callback structure by the resource controller.
591 * Returns the resource id(0 or +ve) on success, -errno for failure.
594 ckrm_register_res_ctlr_intern(struct ckrm_classtype *clstype,
595 ckrm_res_ctlr_t * rcbs)
604 spin_lock(&clstype->res_ctlrs_lock);
606 printk(KERN_WARNING "resid is %d name is %s %s\n",
607 resid, rcbs->res_name, clstype->res_ctlrs[resid]->res_name);
610 if ((resid < CKRM_MAX_RES_CTLRS)
611 && (clstype->res_ctlrs[resid] == NULL)) {
612 clstype->res_ctlrs[resid] = rcbs;
613 atomic_set(&clstype->nr_resusers[resid], 0);
614 set_bit(resid, &clstype->bit_res_ctlrs);
616 if (resid >= clstype->max_resid) {
617 clstype->max_resid = resid + 1;
622 spin_unlock(&clstype->res_ctlrs_lock);
626 for (i = clstype->resid_reserved; i < clstype->max_res_ctlrs; i++) {
627 if (clstype->res_ctlrs[i] == NULL) {
628 clstype->res_ctlrs[i] = rcbs;
630 atomic_set(&clstype->nr_resusers[i], 0);
631 set_bit(i, &clstype->bit_res_ctlrs);
632 if (i >= clstype->max_resid) {
633 clstype->max_resid = i + 1;
635 spin_unlock(&clstype->res_ctlrs_lock);
640 spin_unlock(&clstype->res_ctlrs_lock);
645 ckrm_register_res_ctlr(struct ckrm_classtype *clstype, ckrm_res_ctlr_t * rcbs)
647 struct ckrm_core_class *core;
650 resid = ckrm_register_res_ctlr_intern(clstype, rcbs);
653 /* run through all classes and create the resource class
654 * object and if necessary "initialize" class in context
657 read_lock(&ckrm_class_lock);
658 list_for_each_entry(core, &clstype->classes, clslist) {
659 printk("CKRM .. create res clsobj for resouce <%s>"
660 "class <%s> par=%p\n", rcbs->res_name,
661 core->name, core->hnode.parent);
662 ckrm_alloc_res_class(core, core->hnode.parent, resid);
664 if (clstype->add_resctrl) {
665 // FIXME: this should be mandatory
666 (*clstype->add_resctrl) (core, resid);
669 read_unlock(&ckrm_class_lock);
675 * Unregistering a callback structure by the resource controller.
677 * Returns 0 on success -errno for failure.
679 int ckrm_unregister_res_ctlr(struct ckrm_res_ctlr *rcbs)
681 struct ckrm_classtype *clstype = rcbs->classtype;
682 struct ckrm_core_class *core = NULL;
683 int resid = rcbs->resid;
685 if ((clstype == NULL) || (resid < 0)) {
688 // FIXME: probably need to also call deregistration function
690 read_lock(&ckrm_class_lock);
691 // free up this resource from all the classes
692 list_for_each_entry(core, &clstype->classes, clslist) {
693 ckrm_free_res_class(core, resid);
695 read_unlock(&ckrm_class_lock);
697 if (atomic_read(&clstype->nr_resusers[resid])) {
701 spin_lock(&clstype->res_ctlrs_lock);
702 clstype->res_ctlrs[resid] = NULL;
703 clear_bit(resid, &clstype->bit_res_ctlrs);
704 clstype->max_resid = fls(clstype->bit_res_ctlrs);
706 spin_unlock(&clstype->res_ctlrs_lock);
711 /*******************************************************************
712 * Class Type Registration
713 *******************************************************************/
715 /* Hubertus ... we got to do some locking here */
718 struct ckrm_classtype *ckrm_classtypes[CKRM_MAX_CLASSTYPES];
719 // really should build a better interface for this
720 EXPORT_SYMBOL(ckrm_classtypes);
722 int ckrm_register_classtype(struct ckrm_classtype *clstype)
724 int tid = clstype->typeID;
727 if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
728 || (ckrm_classtypes[tid]))
732 for (i = CKRM_RESV_CLASSTYPES; i < CKRM_MAX_CLASSTYPES; i++) {
733 if (ckrm_classtypes[i] == NULL) {
741 clstype->typeID = tid;
742 ckrm_classtypes[tid] = clstype;
744 /* Hubertus .. we need to call the callbacks of the RCFS client */
745 if (rcfs_fn.register_classtype) {
746 (*rcfs_fn.register_classtype) (clstype);
747 // No error return for now ;
753 int ckrm_unregister_classtype(struct ckrm_classtype *clstype)
755 int tid = clstype->typeID;
757 if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
758 || (ckrm_classtypes[tid] != clstype))
761 if (rcfs_fn.deregister_classtype) {
762 (*rcfs_fn.deregister_classtype) (clstype);
763 // No error return for now
766 ckrm_classtypes[tid] = NULL;
767 clstype->typeID = -1;
771 struct ckrm_classtype *ckrm_find_classtype_by_name(const char *name)
774 for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
775 struct ckrm_classtype *ctype = ckrm_classtypes[i];
776 if (ctype && !strncmp(ctype->name, name, CKRM_MAX_TYPENAME_LEN))
782 /*******************************************************************
783 * Event callback invocation
784 *******************************************************************/
786 struct ckrm_hook_cb *ckrm_event_callbacks[CKRM_NONLATCHABLE_EVENTS];
788 /* Registration / Deregistration / Invocation functions */
790 int ckrm_register_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb)
792 struct ckrm_hook_cb **cbptr;
794 if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS))
796 cbptr = &ckrm_event_callbacks[ev];
797 while (*cbptr != NULL)
798 cbptr = &((*cbptr)->next);
803 int ckrm_unregister_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb)
805 struct ckrm_hook_cb **cbptr;
807 if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS))
809 cbptr = &ckrm_event_callbacks[ev];
810 while ((*cbptr != NULL) && (*cbptr != cb))
811 cbptr = &((*cbptr)->next);
813 (*cbptr)->next = cb->next;
814 return (*cbptr == NULL);
817 int ckrm_register_event_set(struct ckrm_event_spec especs[])
819 struct ckrm_event_spec *espec = especs;
821 for (espec = especs; espec->ev != -1; espec++)
822 ckrm_register_event_cb(espec->ev, &espec->cb);
826 int ckrm_unregister_event_set(struct ckrm_event_spec especs[])
828 struct ckrm_event_spec *espec = especs;
830 for (espec = especs; espec->ev != -1; espec++)
831 ckrm_unregister_event_cb(espec->ev, &espec->cb);
835 #define ECC_PRINTK(fmt, args...) \
836 // printk("%s: " fmt, __FUNCTION__ , ## args)
838 void ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg)
840 struct ckrm_hook_cb *cb, *anchor;
842 ECC_PRINTK("%d %x\n", current, ev, arg);
843 if ((anchor = ckrm_event_callbacks[ev]) != NULL) {
844 for (cb = anchor; cb; cb = cb->next)
849 /*******************************************************************
850 * Generic Functions that can be used as default functions
851 * in almost all classtypes
852 * (a) function iterator over all resource classes of a class
853 * (b) function invoker on a named resource
854 *******************************************************************/
856 int ckrm_class_show_shares(struct ckrm_core_class *core, struct seq_file *seq)
859 struct ckrm_res_ctlr *rcbs;
860 struct ckrm_classtype *clstype = core->classtype;
861 struct ckrm_shares shares;
863 for (i = 0; i < clstype->max_resid; i++) {
864 atomic_inc(&clstype->nr_resusers[i]);
865 rcbs = clstype->res_ctlrs[i];
866 if (rcbs && rcbs->get_share_values) {
867 (*rcbs->get_share_values) (core->res_class[i], &shares);
868 seq_printf(seq,"res=%s,guarantee=%d,limit=%d,"
869 "total_guarantee=%d,max_limit=%d\n",
870 rcbs->res_name, shares.my_guarantee,
871 shares.my_limit, shares.total_guarantee,
874 atomic_dec(&clstype->nr_resusers[i]);
879 int ckrm_class_show_stats(struct ckrm_core_class *core, struct seq_file *seq)
882 struct ckrm_res_ctlr *rcbs;
883 struct ckrm_classtype *clstype = core->classtype;
885 for (i = 0; i < clstype->max_resid; i++) {
886 atomic_inc(&clstype->nr_resusers[i]);
887 rcbs = clstype->res_ctlrs[i];
888 if (rcbs && rcbs->get_stats)
889 (*rcbs->get_stats) (core->res_class[i], seq);
890 atomic_dec(&clstype->nr_resusers[i]);
895 int ckrm_class_show_config(struct ckrm_core_class *core, struct seq_file *seq)
898 struct ckrm_res_ctlr *rcbs;
899 struct ckrm_classtype *clstype = core->classtype;
901 for (i = 0; i < clstype->max_resid; i++) {
902 atomic_inc(&clstype->nr_resusers[i]);
903 rcbs = clstype->res_ctlrs[i];
904 if (rcbs && rcbs->show_config)
905 (*rcbs->show_config) (core->res_class[i], seq);
906 atomic_dec(&clstype->nr_resusers[i]);
911 int ckrm_class_set_config(struct ckrm_core_class *core, const char *resname,
914 struct ckrm_classtype *clstype = core->classtype;
915 struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
918 if (rcbs == NULL || rcbs->set_config == NULL)
920 rc = (*rcbs->set_config) (core->res_class[rcbs->resid], cfgstr);
924 #define legalshare(a) \
926 || ((a) == CKRM_SHARE_UNCHANGED) \
927 || ((a) == CKRM_SHARE_DONTCARE) )
929 int ckrm_class_set_shares(struct ckrm_core_class *core, const char *resname,
930 struct ckrm_shares *shares)
932 struct ckrm_classtype *clstype = core->classtype;
933 struct ckrm_res_ctlr *rcbs;
936 // Check for legal values
937 if (!legalshare(shares->my_guarantee) || !legalshare(shares->my_limit)
938 || !legalshare(shares->total_guarantee)
939 || !legalshare(shares->max_limit))
942 rcbs = ckrm_resctlr_lookup(clstype, resname);
943 if (rcbs == NULL || rcbs->set_share_values == NULL)
945 rc = (*rcbs->set_share_values) (core->res_class[rcbs->resid], shares);
949 int ckrm_class_reset_stats(struct ckrm_core_class *core, const char *resname,
952 struct ckrm_classtype *clstype = core->classtype;
953 struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
956 if (rcbs == NULL || rcbs->reset_stats == NULL)
958 rc = (*rcbs->reset_stats) (core->res_class[rcbs->resid]);
962 /*******************************************************************
964 *******************************************************************/
966 void ckrm_cb_newtask(struct task_struct *tsk)
969 spin_lock_init(&tsk->ckrm_tsklock);
970 ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK, tsk);
973 void ckrm_cb_exit(struct task_struct *tsk)
975 ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT, tsk);
979 void __init ckrm_init(void)
981 printk("CKRM Initialization\n");
983 // register/initialize the Metatypes
985 #ifdef CONFIG_CKRM_TYPE_TASKCLASS
987 extern void ckrm_meta_init_taskclass(void);
988 ckrm_meta_init_taskclass();
991 #ifdef CONFIG_CKRM_TYPE_SOCKETCLASS
993 extern void ckrm_meta_init_sockclass(void);
994 ckrm_meta_init_sockclass();
997 // prepare init_task and then rely on inheritance of properties
998 ckrm_cb_newtask(&init_task);
999 printk("CKRM Initialization done\n");
1002 EXPORT_SYMBOL(ckrm_register_engine);
1003 EXPORT_SYMBOL(ckrm_unregister_engine);
1005 EXPORT_SYMBOL(ckrm_register_res_ctlr);
1006 EXPORT_SYMBOL(ckrm_unregister_res_ctlr);
1008 EXPORT_SYMBOL(ckrm_init_core_class);
1009 EXPORT_SYMBOL(ckrm_free_core_class);
1010 EXPORT_SYMBOL(ckrm_release_core_class);
1012 EXPORT_SYMBOL(ckrm_register_classtype);
1013 EXPORT_SYMBOL(ckrm_unregister_classtype);
1014 EXPORT_SYMBOL(ckrm_find_classtype_by_name);
1016 EXPORT_SYMBOL(ckrm_core_grab);
1017 EXPORT_SYMBOL(ckrm_core_drop);
1018 EXPORT_SYMBOL(ckrm_is_core_valid);
1019 EXPORT_SYMBOL(ckrm_validate_and_grab_core);
1021 EXPORT_SYMBOL(ckrm_register_event_set);
1022 EXPORT_SYMBOL(ckrm_unregister_event_set);
1023 EXPORT_SYMBOL(ckrm_register_event_cb);
1024 EXPORT_SYMBOL(ckrm_unregister_event_cb);
1026 EXPORT_SYMBOL(ckrm_class_show_stats);
1027 EXPORT_SYMBOL(ckrm_class_show_config);
1028 EXPORT_SYMBOL(ckrm_class_show_shares);
1030 EXPORT_SYMBOL(ckrm_class_set_config);
1031 EXPORT_SYMBOL(ckrm_class_set_shares);
1033 EXPORT_SYMBOL(ckrm_class_reset_stats);