From 4ce37704ec0bedb28b5708d32964fca471e793d0 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Wed, 26 Jan 2011 20:42:49 -0500 Subject: Litmus core: extract userspace interface from C-EDF Make the cluster size configuration in C-EDF generic so that it can be used by other clustered schedulers. --- include/litmus/clustered.h | 22 ++++++++++++ litmus/litmus_proc.c | 78 ++++++++++++++++++++++++++++++++++++++++ litmus/sched_cedf.c | 88 ++++------------------------------------------ 3 files changed, 106 insertions(+), 82 deletions(-) create mode 100644 include/litmus/clustered.h diff --git a/include/litmus/clustered.h b/include/litmus/clustered.h new file mode 100644 index 000000000000..cad12467b4ee --- /dev/null +++ b/include/litmus/clustered.h @@ -0,0 +1,22 @@ +#ifndef CLUSTERED_H +#define CLUSTERED_H + +/* Which cache level should be used to group CPUs into clusters? + * GLOBAL_CLUSTER means that all CPUs form a single cluster (just like under + * global scheduling). + */ +enum cache_level { + GLOBAL_CLUSTER = 0, + L1_CLUSTER = 1, + L2_CLUSTER = 2, + L3_CLUSTER = 3 +}; + +int parse_cache_level(const char *str, enum cache_level *level); +const char* cache_level_name(enum cache_level level); + +/* expose a cache level in a /proc dir */ +struct proc_dir_entry* create_cluster_file(struct proc_dir_entry* parent, + enum cache_level* level); + +#endif diff --git a/litmus/litmus_proc.c b/litmus/litmus_proc.c index e3f3f11f80e1..4bf725a36c9c 100644 --- a/litmus/litmus_proc.c +++ b/litmus/litmus_proc.c @@ -8,6 +8,8 @@ #include #include +#include + /* in litmus/litmus.c */ extern atomic_t rt_task_count; @@ -267,3 +269,79 @@ int copy_and_chomp(char *kbuf, unsigned long ksize, return ksize; } + +/* helper functions for clustered plugins */ +static const char* cache_level_names[] = { + "ALL", + "L1", + "L2", + "L3", +}; + +int parse_cache_level(const char *cache_name, enum cache_level *level) +{ + int err = -EINVAL; + int i; + /* do a quick and dirty comparison to find the cluster size */ + for (i = GLOBAL_CLUSTER; i <= L3_CLUSTER; i++) + if (!strcmp(cache_name, cache_level_names[i])) { + *level = (enum cache_level) i; + err = 0; + break; + } + return err; +} + +const char* cache_level_name(enum cache_level level) +{ + int idx = level; + + if (idx >= GLOBAL_CLUSTER && idx <= L3_CLUSTER) + return cache_level_names[idx]; + else + return "INVALID"; +} + + +/* proc file interface to configure the cluster size */ +static int proc_read_cluster_size(char *page, char **start, + off_t off, int count, + int *eof, void *data) +{ + return snprintf(page, PAGE_SIZE, "%s\n", + cache_level_name(*((enum cache_level*) data)));; +} + +static int proc_write_cluster_size(struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int len; + char cache_name[8]; + + len = copy_and_chomp(cache_name, sizeof(cache_name), buffer, count); + + if (len > 0 && parse_cache_level(cache_name, (enum cache_level*) data)) + printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name); + + return len; +} + +struct proc_dir_entry* create_cluster_file(struct proc_dir_entry* parent, + enum cache_level* level) +{ + struct proc_dir_entry* cluster_file; + + cluster_file = create_proc_entry("cluster", 0644, parent); + if (!cluster_file) { + printk(KERN_ERR "Could not allocate %s/cluster " + "procfs entry.\n", parent->name); + } else { + cluster_file->read_proc = proc_read_cluster_size; + cluster_file->write_proc = proc_write_cluster_size; + cluster_file->data = level; + } + return cluster_file; +} + diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c index 098a449c2490..73fe1c442a0d 100644 --- a/litmus/sched_cedf.c +++ b/litmus/sched_cedf.c @@ -39,6 +39,8 @@ #include #include +#include + #include /* to configure the cluster size */ @@ -49,12 +51,7 @@ * group CPUs into clusters. GLOBAL_CLUSTER, which is the default, means that * all CPUs form a single cluster (just like GSN-EDF). */ -static enum { - GLOBAL_CLUSTER = 0, - L1_CLUSTER = 1, - L2_CLUSTER = 2, - L3_CLUSTER = 3 -} cluster_config = GLOBAL_CLUSTER; +static enum cache_level cluster_config = GLOBAL_CLUSTER; struct clusterdomain; @@ -770,73 +767,8 @@ static struct sched_plugin cedf_plugin __cacheline_aligned_in_smp = { .activate_plugin = cedf_activate_plugin, }; - -/* proc file interface to configure the cluster size */ - -static int proc_read_cluster_size(char *page, char **start, - off_t off, int count, - int *eof, void *data) -{ - int len; - switch (cluster_config) { - case GLOBAL_CLUSTER: - len = snprintf(page, PAGE_SIZE, "ALL\n"); - break; - case L1_CLUSTER: - case L2_CLUSTER: - case L3_CLUSTER: - len = snprintf(page, PAGE_SIZE, "L%d\n", cluster_config); - break; - default: - /* This should be impossible, but let's be paranoid. */ - len = snprintf(page, PAGE_SIZE, "INVALID (%d)\n", - cluster_config); - break; - } - return len; -} - -static int proc_write_cluster_size(struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int len; - /* L2, L3 */ - char cache_name[33]; - - if(count > 32) - len = 32; - else - len = count; - - if(copy_from_user(cache_name, buffer, len)) - return -EFAULT; - - cache_name[len] = '\0'; - /* chomp name */ - if (len > 1 && cache_name[len - 1] == '\n') - cache_name[len - 1] = '\0'; - - /* do a quick and dirty comparison to find the cluster size */ - if (!strcmp(cache_name, "L2")) - cluster_config = L2_CLUSTER; - else if (!strcmp(cache_name, "L3")) - cluster_config = L3_CLUSTER; - else if (!strcmp(cache_name, "L1")) - cluster_config = L1_CLUSTER; - else if (!strcmp(cache_name, "ALL")) - cluster_config = GLOBAL_CLUSTER; - else - printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name); - - return len; -} - - static struct proc_dir_entry *cluster_file = NULL, *cedf_dir = NULL; - static int __init init_cedf(void) { int err, fs; @@ -844,18 +776,10 @@ static int __init init_cedf(void) err = register_sched_plugin(&cedf_plugin); if (!err) { fs = make_plugin_proc_dir(&cedf_plugin, &cedf_dir); - if (!fs) { - cluster_file = create_proc_entry("cluster", 0644, cedf_dir); - if (!cluster_file) { - printk(KERN_ERR "Could not allocate C-EDF/cluster " - "procfs entry.\n"); - } else { - cluster_file->read_proc = proc_read_cluster_size; - cluster_file->write_proc = proc_write_cluster_size; - } - } else { + if (!fs) + cluster_file = create_cluster_file(cedf_dir, &cluster_config); + else printk(KERN_ERR "Could not allocate C-EDF procfs dir.\n"); - } } return err; } -- cgit v1.2.2