aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2011-01-26 20:42:49 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2011-02-01 17:00:26 -0500
commit4ce37704ec0bedb28b5708d32964fca471e793d0 (patch)
tree4e622b0d2d6793e944455ba108ae6dd5bf05ee80
parent963fd846e36b48d5338ef2a134d3ee8d208abc07 (diff)
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.
-rw-r--r--include/litmus/clustered.h22
-rw-r--r--litmus/litmus_proc.c78
-rw-r--r--litmus/sched_cedf.c88
3 files changed, 106 insertions, 82 deletions
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 @@
1#ifndef CLUSTERED_H
2#define CLUSTERED_H
3
4/* Which cache level should be used to group CPUs into clusters?
5 * GLOBAL_CLUSTER means that all CPUs form a single cluster (just like under
6 * global scheduling).
7 */
8enum cache_level {
9 GLOBAL_CLUSTER = 0,
10 L1_CLUSTER = 1,
11 L2_CLUSTER = 2,
12 L3_CLUSTER = 3
13};
14
15int parse_cache_level(const char *str, enum cache_level *level);
16const char* cache_level_name(enum cache_level level);
17
18/* expose a cache level in a /proc dir */
19struct proc_dir_entry* create_cluster_file(struct proc_dir_entry* parent,
20 enum cache_level* level);
21
22#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 @@
8#include <litmus/litmus.h> 8#include <litmus/litmus.h>
9#include <litmus/litmus_proc.h> 9#include <litmus/litmus_proc.h>
10 10
11#include <litmus/clustered.h>
12
11/* in litmus/litmus.c */ 13/* in litmus/litmus.c */
12extern atomic_t rt_task_count; 14extern atomic_t rt_task_count;
13 15
@@ -267,3 +269,79 @@ int copy_and_chomp(char *kbuf, unsigned long ksize,
267 269
268 return ksize; 270 return ksize;
269} 271}
272
273/* helper functions for clustered plugins */
274static const char* cache_level_names[] = {
275 "ALL",
276 "L1",
277 "L2",
278 "L3",
279};
280
281int parse_cache_level(const char *cache_name, enum cache_level *level)
282{
283 int err = -EINVAL;
284 int i;
285 /* do a quick and dirty comparison to find the cluster size */
286 for (i = GLOBAL_CLUSTER; i <= L3_CLUSTER; i++)
287 if (!strcmp(cache_name, cache_level_names[i])) {
288 *level = (enum cache_level) i;
289 err = 0;
290 break;
291 }
292 return err;
293}
294
295const char* cache_level_name(enum cache_level level)
296{
297 int idx = level;
298
299 if (idx >= GLOBAL_CLUSTER && idx <= L3_CLUSTER)
300 return cache_level_names[idx];
301 else
302 return "INVALID";
303}
304
305
306/* proc file interface to configure the cluster size */
307static int proc_read_cluster_size(char *page, char **start,
308 off_t off, int count,
309 int *eof, void *data)
310{
311 return snprintf(page, PAGE_SIZE, "%s\n",
312 cache_level_name(*((enum cache_level*) data)));;
313}
314
315static int proc_write_cluster_size(struct file *file,
316 const char *buffer,
317 unsigned long count,
318 void *data)
319{
320 int len;
321 char cache_name[8];
322
323 len = copy_and_chomp(cache_name, sizeof(cache_name), buffer, count);
324
325 if (len > 0 && parse_cache_level(cache_name, (enum cache_level*) data))
326 printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name);
327
328 return len;
329}
330
331struct proc_dir_entry* create_cluster_file(struct proc_dir_entry* parent,
332 enum cache_level* level)
333{
334 struct proc_dir_entry* cluster_file;
335
336 cluster_file = create_proc_entry("cluster", 0644, parent);
337 if (!cluster_file) {
338 printk(KERN_ERR "Could not allocate %s/cluster "
339 "procfs entry.\n", parent->name);
340 } else {
341 cluster_file->read_proc = proc_read_cluster_size;
342 cluster_file->write_proc = proc_write_cluster_size;
343 cluster_file->data = level;
344 }
345 return cluster_file;
346}
347
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 @@
39#include <litmus/edf_common.h> 39#include <litmus/edf_common.h>
40#include <litmus/sched_trace.h> 40#include <litmus/sched_trace.h>
41 41
42#include <litmus/clustered.h>
43
42#include <litmus/bheap.h> 44#include <litmus/bheap.h>
43 45
44/* to configure the cluster size */ 46/* to configure the cluster size */
@@ -49,12 +51,7 @@
49 * group CPUs into clusters. GLOBAL_CLUSTER, which is the default, means that 51 * group CPUs into clusters. GLOBAL_CLUSTER, which is the default, means that
50 * all CPUs form a single cluster (just like GSN-EDF). 52 * all CPUs form a single cluster (just like GSN-EDF).
51 */ 53 */
52static enum { 54static enum cache_level cluster_config = GLOBAL_CLUSTER;
53 GLOBAL_CLUSTER = 0,
54 L1_CLUSTER = 1,
55 L2_CLUSTER = 2,
56 L3_CLUSTER = 3
57} cluster_config = GLOBAL_CLUSTER;
58 55
59struct clusterdomain; 56struct clusterdomain;
60 57
@@ -770,73 +767,8 @@ static struct sched_plugin cedf_plugin __cacheline_aligned_in_smp = {
770 .activate_plugin = cedf_activate_plugin, 767 .activate_plugin = cedf_activate_plugin,
771}; 768};
772 769
773
774/* proc file interface to configure the cluster size */
775
776static int proc_read_cluster_size(char *page, char **start,
777 off_t off, int count,
778 int *eof, void *data)
779{
780 int len;
781 switch (cluster_config) {
782 case GLOBAL_CLUSTER:
783 len = snprintf(page, PAGE_SIZE, "ALL\n");
784 break;
785 case L1_CLUSTER:
786 case L2_CLUSTER:
787 case L3_CLUSTER:
788 len = snprintf(page, PAGE_SIZE, "L%d\n", cluster_config);
789 break;
790 default:
791 /* This should be impossible, but let's be paranoid. */
792 len = snprintf(page, PAGE_SIZE, "INVALID (%d)\n",
793 cluster_config);
794 break;
795 }
796 return len;
797}
798
799static int proc_write_cluster_size(struct file *file,
800 const char *buffer,
801 unsigned long count,
802 void *data)
803{
804 int len;
805 /* L2, L3 */
806 char cache_name[33];
807
808 if(count > 32)
809 len = 32;
810 else
811 len = count;
812
813 if(copy_from_user(cache_name, buffer, len))
814 return -EFAULT;
815
816 cache_name[len] = '\0';
817 /* chomp name */
818 if (len > 1 && cache_name[len - 1] == '\n')
819 cache_name[len - 1] = '\0';
820
821 /* do a quick and dirty comparison to find the cluster size */
822 if (!strcmp(cache_name, "L2"))
823 cluster_config = L2_CLUSTER;
824 else if (!strcmp(cache_name, "L3"))
825 cluster_config = L3_CLUSTER;
826 else if (!strcmp(cache_name, "L1"))
827 cluster_config = L1_CLUSTER;
828 else if (!strcmp(cache_name, "ALL"))
829 cluster_config = GLOBAL_CLUSTER;
830 else
831 printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name);
832
833 return len;
834}
835
836
837static struct proc_dir_entry *cluster_file = NULL, *cedf_dir = NULL; 770static struct proc_dir_entry *cluster_file = NULL, *cedf_dir = NULL;
838 771
839
840static int __init init_cedf(void) 772static int __init init_cedf(void)
841{ 773{
842 int err, fs; 774 int err, fs;
@@ -844,18 +776,10 @@ static int __init init_cedf(void)
844 err = register_sched_plugin(&cedf_plugin); 776 err = register_sched_plugin(&cedf_plugin);
845 if (!err) { 777 if (!err) {
846 fs = make_plugin_proc_dir(&cedf_plugin, &cedf_dir); 778 fs = make_plugin_proc_dir(&cedf_plugin, &cedf_dir);
847 if (!fs) { 779 if (!fs)
848 cluster_file = create_proc_entry("cluster", 0644, cedf_dir); 780 cluster_file = create_cluster_file(cedf_dir, &cluster_config);
849 if (!cluster_file) { 781 else
850 printk(KERN_ERR "Could not allocate C-EDF/cluster "
851 "procfs entry.\n");
852 } else {
853 cluster_file->read_proc = proc_read_cluster_size;
854 cluster_file->write_proc = proc_write_cluster_size;
855 }
856 } else {
857 printk(KERN_ERR "Could not allocate C-EDF procfs dir.\n"); 782 printk(KERN_ERR "Could not allocate C-EDF procfs dir.\n");
858 }
859 } 783 }
860 return err; 784 return err;
861} 785}