02/12 - ckrm_core_class_support Provides functions to alloc and free a user defined class. Provides utility macro to walk through the class hierarchy --
Signed-Off-By: Chandra Seetharaman <[EMAIL PROTECTED]> Signed-Off-By: Hubertus Franke <[EMAIL PROTECTED]> Signed-Off-By: Shailabh Nagar <[EMAIL PROTECTED]> Signed-Off-By: Gerrit Huizenga <[EMAIL PROTECTED]> Signed-Off-By: Vivek Kashyap <[EMAIL PROTECTED]> Signed-Off-By: Matt Helsley <[EMAIL PROTECTED]> include/linux/ckrm.h | 22 ++++++ kernel/ckrm/ckrm.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 172 insertions(+), 11 deletions(-) Index: linux-2.6.16/include/linux/ckrm.h =================================================================== --- linux-2.6.16.orig/include/linux/ckrm.h +++ linux-2.6.16/include/linux/ckrm.h @@ -61,6 +61,8 @@ struct ckrm_shares { * registered a resource controller (see include/linux/ckrm_rc.h). */ struct ckrm_class { + const char *name; + struct kref ref; int depth; /* depth of this class. root == 0 */ spinlock_t class_lock; /* protects task_list, shares and children * When grabbing class_lock in a hierarchy, @@ -70,10 +72,30 @@ struct ckrm_class { * grabbing resource specific lock */ struct ckrm_shares *shares[CKRM_MAX_RES_CTLRS];/* resource shares */ struct list_head class_list; /* entry in list of all classes */ + + struct list_head task_list; /* this class's tasks */ + + struct ckrm_class *parent; + struct list_head siblings; /* entry in list of siblings */ + struct list_head children; /* head of children */ }; extern struct ckrm_controller *ckrm_get_controller_by_name(const char *); extern struct ckrm_controller *ckrm_get_controller_by_id(unsigned int); extern void ckrm_put_controller(struct ckrm_controller *); + +extern struct ckrm_class ckrm_default_class; +static inline int ckrm_is_class_root(const struct ckrm_class* class) +{ + return (class == &ckrm_default_class); +} + +extern struct ckrm_class *ckrm_alloc_class(struct ckrm_class *, const char *); +extern int ckrm_free_class(struct ckrm_class *); +extern void ckrm_release_class(struct kref *); + +#define for_each_child(child, parent) \ + list_for_each_entry(child, &parent->children, siblings) + #endif /* CONFIG_CKRM */ #endif /* _LINUX_CKRM_H */ Index: linux-2.6.16/kernel/ckrm/ckrm.c =================================================================== --- linux-2.6.16.orig/kernel/ckrm/ckrm.c +++ linux-2.6.16/kernel/ckrm/ckrm.c @@ -27,7 +27,25 @@ static atomic_t ckrm_ctlr_refcount[CKRM_ static spinlock_t res_ctlrs_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(ckrm_classes);/* link all classes */ -static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; /* protects ckrm_classes */ +static int ckrm_num_classes; /* Number of user defined classes */ +static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; + /* protects ckrm_classes list and ckrm_num_classes */ + +struct ckrm_class ckrm_default_class = { + .task_list = LIST_HEAD_INIT(ckrm_default_class.task_list), + .class_lock = SPIN_LOCK_UNLOCKED, + .name = "task", + .class_list = LIST_HEAD_INIT(ckrm_default_class.class_list), + .siblings = LIST_HEAD_INIT(ckrm_default_class.siblings), + .children = LIST_HEAD_INIT(ckrm_default_class.children), +}; + +/* Must be called with parent's class_lock held */ +static inline void ckrm_remove_child(struct ckrm_class *child) +{ + list_del(&child->siblings); + child->parent = CKRM_NO_CLASS; +} static inline int is_ctlr_id_valid(unsigned int ctlr_id) { @@ -98,6 +116,55 @@ static void do_alloc_shares_struct(struc ckrm_get_controller(ctlr); } +static void ckrm_class_init(struct ckrm_class *class) +{ + class->class_lock = SPIN_LOCK_UNLOCKED; + kref_init(&class->ref); + INIT_LIST_HEAD(&class->task_list); + INIT_LIST_HEAD(&class->children); + INIT_LIST_HEAD(&class->siblings); +} + +struct ckrm_class *ckrm_alloc_class(struct ckrm_class *parent, + const char *name) +{ + int i; + struct ckrm_class *class; + + BUG_ON(parent == NULL); + + kref_get(&parent->ref); + class = kzalloc(sizeof(struct ckrm_class), GFP_KERNEL); + if (!class) { + kref_put(&parent->ref, ckrm_release_class); + return NULL; + } + ckrm_class_init(class); + class->name = name; + class->depth = parent->depth + 1; + + /* Add to parent */ + spin_lock(&parent->class_lock); + class->parent = parent; + list_add(&class->siblings, &parent->children); + spin_unlock(&parent->class_lock); + + write_lock(&ckrm_class_lock); + list_add_tail(&class->class_list, &ckrm_classes); + ckrm_num_classes++; + write_unlock(&ckrm_class_lock); + + for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) { + struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i); + if (!ctlr) + continue; + do_alloc_shares_struct(class, ctlr); + ckrm_put_controller(ctlr); + } + + return class; +} + /* Free up the given resource specific information in a class */ static void do_free_shares_struct(struct ckrm_class *class, struct ckrm_controller *ctlr) @@ -115,6 +182,58 @@ static void do_free_shares_struct(struct ckrm_put_controller(ctlr); /* Drop reference acquired in do_alloc */ } + /* + * Release a class + * requires that all tasks were previously reassigned to another class + * + * Returns 0 on success -errno on failure. + */ +void ckrm_release_class(struct kref *kref) +{ + int i; + struct ckrm_class *class = container_of(kref, + struct ckrm_class, ref); + struct ckrm_class *parent = class->parent; + + BUG_ON(ckrm_is_class_root(class)); + + for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) { + struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i); + if (!ctlr) + continue; + do_free_shares_struct(class, ctlr); + ckrm_put_controller(ctlr); + } + + /* Remove this class from the list of all classes */ + write_lock(&ckrm_class_lock); + list_del(&class->class_list); + ckrm_num_classes--; + write_unlock(&ckrm_class_lock); + + /* remove from parent */ + spin_lock(&parent->class_lock); + list_del(&class->siblings); + class->parent = CKRM_NO_CLASS; + spin_unlock(&parent->class_lock); + + kref_put(&parent->ref, ckrm_release_class); + kfree(class); +} + +int ckrm_free_class(struct ckrm_class *class) +{ + BUG_ON(ckrm_is_class_root(class)); + spin_lock(&class->class_lock); + if (!list_empty(&class->children)) { + spin_unlock(&class->class_lock); + return -EBUSY; + } + spin_unlock(&class->class_lock); + kref_put(&class->ref, ckrm_release_class); + return 0; +} + /* * Interfaces for resource controllers */ @@ -142,7 +261,7 @@ static int ckrm_register_controller_inte int ckrm_register_controller(struct ckrm_controller *ctlr) { int ret; - struct ckrm_class *class; + struct ckrm_class *class, *prev_class; if (!ctlr) return -EINVAL; @@ -162,10 +281,20 @@ int ckrm_register_controller(struct ckrm * Run through all classes and create the controller specific data * structures. */ - read_lock(&ckrm_class_lock); - list_for_each_entry(class, &ckrm_classes, class_list) - do_alloc_shares_struct(class, ctlr); - read_unlock(&ckrm_class_lock); + prev_class = NULL; + read_lock(&ckrm_class_lock); + list_for_each_entry(class, &ckrm_classes, class_list) { + kref_get(&class->ref); + read_unlock(&ckrm_class_lock); + do_alloc_shares_struct(class, ctlr); + if (prev_class) + kref_put(&prev_class->ref, ckrm_release_class); + prev_class = class; + read_lock(&ckrm_class_lock); + } + read_unlock(&ckrm_class_lock); + if (prev_class) + kref_put(&prev_class->ref, ckrm_release_class); return 0; } @@ -176,7 +305,7 @@ int ckrm_register_controller(struct ckrm */ int ckrm_unregister_controller(struct ckrm_controller *ctlr) { - struct ckrm_class *class; + struct ckrm_class *class, *prev_class; unsigned int ctlr_id; if (!ctlr) @@ -187,10 +316,20 @@ int ckrm_unregister_controller(struct ck return -EINVAL; /* free shares structs for this resource from all the classes */ - read_lock(&ckrm_class_lock); - list_for_each_entry_reverse(class, &ckrm_classes, class_list) - do_free_shares_struct(class, ctlr); - read_unlock(&ckrm_class_lock); + prev_class = NULL; + read_lock(&ckrm_class_lock); + list_for_each_entry_reverse(class, &ckrm_classes, class_list) { + kref_get(&class->ref); + read_unlock(&ckrm_class_lock); + do_free_shares_struct(class, ctlr); + if (prev_class) + kref_put(&prev_class->ref, ckrm_release_class); + prev_class = class; + read_lock(&ckrm_class_lock); + } + read_unlock(&ckrm_class_lock); + if (prev_class) + kref_put(&prev_class->ref, ckrm_release_class); spin_lock(&res_ctlrs_lock); if (atomic_read(&ckrm_ctlr_refcount[ctlr_id]) > 0) { -- ---------------------------------------------------------------------- Chandra Seetharaman | Be careful what you choose.... - [EMAIL PROTECTED] | .......you may get it. ---------------------------------------------------------------------- ------------------------------------------------------- This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 _______________________________________________ ckrm-tech mailing list https://lists.sourceforge.net/lists/listinfo/ckrm-tech