aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/litmus.h16
-rw-r--r--include/litmus/litmus_proc.h19
-rw-r--r--litmus/Makefile1
-rw-r--r--litmus/litmus.c313
-rw-r--r--litmus/litmus_proc.c324
5 files changed, 346 insertions, 327 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index ccb6b137952b..5d20276e44f4 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -9,9 +9,6 @@
9#include <linux/jiffies.h> 9#include <linux/jiffies.h>
10#include <litmus/sched_trace.h> 10#include <litmus/sched_trace.h>
11 11
12#include <litmus/sched_plugin.h>
13#include <linux/proc_fs.h>
14
15#ifdef CONFIG_RELEASE_MASTER 12#ifdef CONFIG_RELEASE_MASTER
16extern atomic_t release_master_cpu; 13extern atomic_t release_master_cpu;
17#endif 14#endif
@@ -65,19 +62,6 @@ void exit_litmus(struct task_struct *dead_tsk);
65long litmus_admit_task(struct task_struct *tsk); 62long litmus_admit_task(struct task_struct *tsk);
66void litmus_exit_task(struct task_struct *tsk); 63void litmus_exit_task(struct task_struct *tsk);
67 64
68/*
69 * On success, returns 0 and sets the pointer to the location of the new
70 * proc dir entry, otherwise returns an error code and sets pde to NULL.
71 */
72long make_plugin_proc_dir(struct sched_plugin* plugin,
73 struct proc_dir_entry** pde);
74
75/*
76 * Plugins should deallocate all child proc directory entries before
77 * calling this, to avoid memory leaks.
78 */
79void remove_plugin_proc_dir(struct sched_plugin* plugin);
80
81#define is_realtime(t) ((t)->policy == SCHED_LITMUS) 65#define is_realtime(t) ((t)->policy == SCHED_LITMUS)
82#define rt_transition_pending(t) \ 66#define rt_transition_pending(t) \
83 ((t)->rt_param.transition_pending) 67 ((t)->rt_param.transition_pending)
diff --git a/include/litmus/litmus_proc.h b/include/litmus/litmus_proc.h
new file mode 100644
index 000000000000..fbc0082b2d21
--- /dev/null
+++ b/include/litmus/litmus_proc.h
@@ -0,0 +1,19 @@
1#include <litmus/sched_plugin.h>
2#include <linux/proc_fs.h>
3
4int __init init_litmus_proc(void);
5void exit_litmus_proc(void);
6
7/*
8 * On success, returns 0 and sets the pointer to the location of the new
9 * proc dir entry, otherwise returns an error code and sets pde to NULL.
10 */
11long make_plugin_proc_dir(struct sched_plugin* plugin,
12 struct proc_dir_entry** pde);
13
14/*
15 * Plugins should deallocate all child proc directory entries before
16 * calling this, to avoid memory leaks.
17 */
18void remove_plugin_proc_dir(struct sched_plugin* plugin);
19
diff --git a/litmus/Makefile b/litmus/Makefile
index f301d2842e43..7bd1abdcb84a 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-y = sched_plugin.o litmus.o \ 5obj-y = sched_plugin.o litmus.o \
6 litmus_proc.o \
6 budget.o \ 7 budget.o \
7 jobs.o \ 8 jobs.o \
8 sync.o \ 9 sync.o \
diff --git a/litmus/litmus.c b/litmus/litmus.c
index 3b73b39ffbbf..99c35ac99870 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -19,6 +19,8 @@
19 19
20#include <litmus/rt_domain.h> 20#include <litmus/rt_domain.h>
21 21
22#include <litmus/litmus_proc.h>
23
22/* Number of RT tasks that exist in the system */ 24/* Number of RT tasks that exist in the system */
23atomic_t rt_task_count = ATOMIC_INIT(0); 25atomic_t rt_task_count = ATOMIC_INIT(0);
24static DEFINE_RAW_SPINLOCK(task_transition_lock); 26static DEFINE_RAW_SPINLOCK(task_transition_lock);
@@ -505,317 +507,6 @@ static struct sysrq_key_op sysrq_kill_rt_tasks_op = {
505}; 507};
506#endif 508#endif
507 509
508/* in litmus/sync.c */
509int count_tasks_waiting_for_release(void);
510
511static int proc_read_stats(char *page, char **start,
512 off_t off, int count,
513 int *eof, void *data)
514{
515 int len;
516
517 len = snprintf(page, PAGE_SIZE,
518 "real-time tasks = %d\n"
519 "ready for release = %d\n",
520 atomic_read(&rt_task_count),
521 count_tasks_waiting_for_release());
522 return len;
523}
524
525static int proc_read_plugins(char *page, char **start,
526 off_t off, int count,
527 int *eof, void *data)
528{
529 int len;
530
531 len = print_sched_plugins(page, PAGE_SIZE);
532 return len;
533}
534
535static int proc_read_curr(char *page, char **start,
536 off_t off, int count,
537 int *eof, void *data)
538{
539 int len;
540
541 len = snprintf(page, PAGE_SIZE, "%s\n", litmus->plugin_name);
542 return len;
543}
544
545static int proc_write_curr(struct file *file,
546 const char *buffer,
547 unsigned long count,
548 void *data)
549{
550 int len, ret;
551 char name[65];
552 struct sched_plugin* found;
553
554 if(count > 64)
555 len = 64;
556 else
557 len = count;
558
559 if(copy_from_user(name, buffer, len))
560 return -EFAULT;
561
562 name[len] = '\0';
563 /* chomp name */
564 if (len > 1 && name[len - 1] == '\n')
565 name[len - 1] = '\0';
566
567 found = find_sched_plugin(name);
568
569 if (found) {
570 ret = switch_sched_plugin(found);
571 if (ret != 0)
572 printk(KERN_INFO "Could not switch plugin: %d\n", ret);
573 } else
574 printk(KERN_INFO "Plugin '%s' is unknown.\n", name);
575
576 return len;
577}
578
579static int proc_read_cluster_size(char *page, char **start,
580 off_t off, int count,
581 int *eof, void *data)
582{
583 int len;
584 if (cluster_cache_index == 2)
585 len = snprintf(page, PAGE_SIZE, "L2\n");
586 else if (cluster_cache_index == 3)
587 len = snprintf(page, PAGE_SIZE, "L3\n");
588 else if (cluster_cache_index == 1)
589 len = snprintf(page, PAGE_SIZE, "L1\n");
590 else
591 len = snprintf(page, PAGE_SIZE, "ALL\n");
592
593 return len;
594}
595
596static int proc_write_cluster_size(struct file *file,
597 const char *buffer,
598 unsigned long count,
599 void *data)
600{
601 int len;
602 /* L2, L3 */
603 char cache_name[33];
604
605 if(count > 32)
606 len = 32;
607 else
608 len = count;
609
610 if(copy_from_user(cache_name, buffer, len))
611 return -EFAULT;
612
613 cache_name[len] = '\0';
614 /* chomp name */
615 if (len > 1 && cache_name[len - 1] == '\n')
616 cache_name[len - 1] = '\0';
617
618 /* do a quick and dirty comparison to find the cluster size */
619 if (!strcmp(cache_name, "L2"))
620 cluster_cache_index = 2;
621 else if (!strcmp(cache_name, "L3"))
622 cluster_cache_index = 3;
623 else if (!strcmp(cache_name, "L1"))
624 cluster_cache_index = 1;
625 else if (!strcmp(cache_name, "ALL"))
626 cluster_cache_index = num_online_cpus();
627 else
628 printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name);
629
630 return len;
631}
632
633#ifdef CONFIG_RELEASE_MASTER
634static int proc_read_release_master(char *page, char **start,
635 off_t off, int count,
636 int *eof, void *data)
637{
638 int len, master;
639 master = atomic_read(&release_master_cpu);
640 if (master == NO_CPU)
641 len = snprintf(page, PAGE_SIZE, "NO_CPU\n");
642 else
643 len = snprintf(page, PAGE_SIZE, "%d\n", master);
644 return len;
645}
646
647static int proc_write_release_master(struct file *file,
648 const char *buffer,
649 unsigned long count,
650 void *data)
651{
652 int cpu, err, online = 0;
653 char msg[64];
654
655 if (count > 63)
656 return -EINVAL;
657
658 if (copy_from_user(msg, buffer, count))
659 return -EFAULT;
660
661 /* terminate */
662 msg[count] = '\0';
663 /* chomp */
664 if (count > 1 && msg[count - 1] == '\n')
665 msg[count - 1] = '\0';
666
667 if (strcmp(msg, "NO_CPU") == 0) {
668 atomic_set(&release_master_cpu, NO_CPU);
669 return count;
670 } else {
671 err = sscanf(msg, "%d", &cpu);
672 if (err == 1 && cpu >= 0 && (online = cpu_online(cpu))) {
673 atomic_set(&release_master_cpu, cpu);
674 return count;
675 } else {
676 TRACE("invalid release master: '%s' "
677 "(err:%d cpu:%d online:%d)\n",
678 msg, err, cpu, online);
679 return -EINVAL;
680 }
681 }
682}
683#endif
684
685static struct proc_dir_entry *litmus_dir = NULL,
686 *curr_file = NULL,
687 *stat_file = NULL,
688 *plugs_dir = NULL,
689 *plugs_file = NULL,
690#ifdef CONFIG_RELEASE_MASTER
691 *release_master_file = NULL,
692#endif
693 *clus_cache_idx_file = NULL;
694
695static int __init init_litmus_proc(void)
696{
697 litmus_dir = proc_mkdir("litmus", NULL);
698 if (!litmus_dir) {
699 printk(KERN_ERR "Could not allocate LITMUS^RT procfs entry.\n");
700 return -ENOMEM;
701 }
702
703 curr_file = create_proc_entry("active_plugin",
704 0644, litmus_dir);
705 if (!curr_file) {
706 printk(KERN_ERR "Could not allocate active_plugin "
707 "procfs entry.\n");
708 return -ENOMEM;
709 }
710 curr_file->read_proc = proc_read_curr;
711 curr_file->write_proc = proc_write_curr;
712
713#ifdef CONFIG_RELEASE_MASTER
714 release_master_file = create_proc_entry("release_master",
715 0644, litmus_dir);
716 if (!release_master_file) {
717 printk(KERN_ERR "Could not allocate release_master "
718 "procfs entry.\n");
719 return -ENOMEM;
720 }
721 release_master_file->read_proc = proc_read_release_master;
722 release_master_file->write_proc = proc_write_release_master;
723#endif
724
725 clus_cache_idx_file = create_proc_entry("cluster_cache",
726 0644, litmus_dir);
727 if (!clus_cache_idx_file) {
728 printk(KERN_ERR "Could not allocate cluster_cache "
729 "procfs entry.\n");
730 return -ENOMEM;
731 }
732 clus_cache_idx_file->read_proc = proc_read_cluster_size;
733 clus_cache_idx_file->write_proc = proc_write_cluster_size;
734
735 stat_file = create_proc_read_entry("stats", 0444, litmus_dir,
736 proc_read_stats, NULL);
737
738 plugs_dir = proc_mkdir("plugins", litmus_dir);
739 if (!plugs_dir){
740 printk(KERN_ERR "Could not allocate plugins directory "
741 "procfs entry.\n");
742 return -ENOMEM;
743 }
744
745 plugs_file = create_proc_read_entry("loaded", 0444, plugs_dir,
746 proc_read_plugins, NULL);
747
748 return 0;
749}
750
751static void exit_litmus_proc(void)
752{
753 if (plugs_file)
754 remove_proc_entry("loaded", plugs_dir);
755 if (plugs_dir)
756 remove_proc_entry("plugins", litmus_dir);
757 if (stat_file)
758 remove_proc_entry("stats", litmus_dir);
759 if (curr_file)
760 remove_proc_entry("active_plugin", litmus_dir);
761 if (clus_cache_idx_file)
762 remove_proc_entry("cluster_cache", litmus_dir);
763#ifdef CONFIG_RELEASE_MASTER
764 if (release_master_file)
765 remove_proc_entry("release_master", litmus_dir);
766#endif
767 if (litmus_dir)
768 remove_proc_entry("litmus", NULL);
769}
770
771long make_plugin_proc_dir(struct sched_plugin* plugin,
772 struct proc_dir_entry** pde_in)
773{
774 struct proc_dir_entry *pde_new = NULL;
775 long rv;
776
777 if (!plugin || !plugin->plugin_name){
778 printk(KERN_ERR "Invalid plugin struct passed to %s.\n",
779 __func__);
780 rv = -EINVAL;
781 goto out_no_pde;
782 }
783
784 if (!plugs_dir){
785 printk(KERN_ERR "Could not make plugin sub-directory, because "
786 "/proc/litmus/plugins does not exist.\n");
787 rv = -ENOENT;
788 goto out_no_pde;
789 }
790
791 pde_new = proc_mkdir(plugin->plugin_name, plugs_dir);
792 if (!pde_new){
793 printk(KERN_ERR "Could not make plugin sub-directory: "
794 "out of memory?.\n");
795 rv = -ENOMEM;
796 goto out_no_pde;
797 }
798
799 rv = 0;
800 *pde_in = pde_new;
801 goto out_ok;
802
803out_no_pde:
804 *pde_in = NULL;
805out_ok:
806 return rv;
807}
808
809void remove_plugin_proc_dir(struct sched_plugin* plugin)
810{
811 if (!plugin || !plugin->plugin_name){
812 printk(KERN_ERR "Invalid plugin struct passed to %s.\n",
813 __func__);
814 return;
815 }
816 remove_proc_entry(plugin->plugin_name, plugs_dir);
817}
818
819extern struct sched_plugin linux_sched_plugin; 510extern struct sched_plugin linux_sched_plugin;
820 511
821static int __init _init_litmus(void) 512static int __init _init_litmus(void)
diff --git a/litmus/litmus_proc.c b/litmus/litmus_proc.c
new file mode 100644
index 000000000000..ee0ad56d445c
--- /dev/null
+++ b/litmus/litmus_proc.c
@@ -0,0 +1,324 @@
1/*
2 * litmus_proc.c -- Implementation of the /proc/litmus directory tree.
3 */
4
5#include <linux/uaccess.h>
6
7#include <litmus/litmus_proc.h>
8
9/* in litmus/litmus.c */
10extern atomic_t rt_task_count;
11
12static struct proc_dir_entry *litmus_dir = NULL,
13 *curr_file = NULL,
14 *stat_file = NULL,
15 *plugs_dir = NULL,
16 *plugs_file = NULL,
17#ifdef CONFIG_RELEASE_MASTER
18 *release_master_file = NULL,
19#endif
20 *clus_cache_idx_file = NULL;
21
22/* in litmus/sync.c */
23int count_tasks_waiting_for_release(void);
24
25static int proc_read_stats(char *page, char **start,
26 off_t off, int count,
27 int *eof, void *data)
28{
29 int len;
30
31 len = snprintf(page, PAGE_SIZE,
32 "real-time tasks = %d\n"
33 "ready for release = %d\n",
34 atomic_read(&rt_task_count),
35 count_tasks_waiting_for_release());
36 return len;
37}
38
39static int proc_read_plugins(char *page, char **start,
40 off_t off, int count,
41 int *eof, void *data)
42{
43 int len;
44
45 len = print_sched_plugins(page, PAGE_SIZE);
46 return len;
47}
48
49static int proc_read_curr(char *page, char **start,
50 off_t off, int count,
51 int *eof, void *data)
52{
53 int len;
54
55 len = snprintf(page, PAGE_SIZE, "%s\n", litmus->plugin_name);
56 return len;
57}
58
59/* in litmus/litmus.c */
60int switch_sched_plugin(struct sched_plugin*);
61
62static int proc_write_curr(struct file *file,
63 const char *buffer,
64 unsigned long count,
65 void *data)
66{
67 int len, ret;
68 char name[65];
69 struct sched_plugin* found;
70
71 if(count > 64)
72 len = 64;
73 else
74 len = count;
75
76 if(copy_from_user(name, buffer, len))
77 return -EFAULT;
78
79 name[len] = '\0';
80 /* chomp name */
81 if (len > 1 && name[len - 1] == '\n')
82 name[len - 1] = '\0';
83
84 found = find_sched_plugin(name);
85
86 if (found) {
87 ret = switch_sched_plugin(found);
88 if (ret != 0)
89 printk(KERN_INFO "Could not switch plugin: %d\n", ret);
90 } else
91 printk(KERN_INFO "Plugin '%s' is unknown.\n", name);
92
93 return len;
94}
95
96static int proc_read_cluster_size(char *page, char **start,
97 off_t off, int count,
98 int *eof, void *data)
99{
100 int len;
101 if (cluster_cache_index == 2)
102 len = snprintf(page, PAGE_SIZE, "L2\n");
103 else if (cluster_cache_index == 3)
104 len = snprintf(page, PAGE_SIZE, "L3\n");
105 else if (cluster_cache_index == 1)
106 len = snprintf(page, PAGE_SIZE, "L1\n");
107 else
108 len = snprintf(page, PAGE_SIZE, "ALL\n");
109
110 return len;
111}
112
113static int proc_write_cluster_size(struct file *file,
114 const char *buffer,
115 unsigned long count,
116 void *data)
117{
118 int len;
119 /* L2, L3 */
120 char cache_name[33];
121
122 if(count > 32)
123 len = 32;
124 else
125 len = count;
126
127 if(copy_from_user(cache_name, buffer, len))
128 return -EFAULT;
129
130 cache_name[len] = '\0';
131 /* chomp name */
132 if (len > 1 && cache_name[len - 1] == '\n')
133 cache_name[len - 1] = '\0';
134
135 /* do a quick and dirty comparison to find the cluster size */
136 if (!strcmp(cache_name, "L2"))
137 cluster_cache_index = 2;
138 else if (!strcmp(cache_name, "L3"))
139 cluster_cache_index = 3;
140 else if (!strcmp(cache_name, "L1"))
141 cluster_cache_index = 1;
142 else if (!strcmp(cache_name, "ALL"))
143 cluster_cache_index = num_online_cpus();
144 else
145 printk(KERN_INFO "Cluster '%s' is unknown.\n", cache_name);
146
147 return len;
148}
149
150#ifdef CONFIG_RELEASE_MASTER
151static int proc_read_release_master(char *page, char **start,
152 off_t off, int count,
153 int *eof, void *data)
154{
155 int len, master;
156 master = atomic_read(&release_master_cpu);
157 if (master == NO_CPU)
158 len = snprintf(page, PAGE_SIZE, "NO_CPU\n");
159 else
160 len = snprintf(page, PAGE_SIZE, "%d\n", master);
161 return len;
162}
163
164static int proc_write_release_master(struct file *file,
165 const char *buffer,
166 unsigned long count,
167 void *data)
168{
169 int cpu, err, online = 0;
170 char msg[64];
171
172 if (count > 63)
173 return -EINVAL;
174
175 if (copy_from_user(msg, buffer, count))
176 return -EFAULT;
177
178 /* terminate */
179 msg[count] = '\0';
180 /* chomp */
181 if (count > 1 && msg[count - 1] == '\n')
182 msg[count - 1] = '\0';
183
184 if (strcmp(msg, "NO_CPU") == 0) {
185 atomic_set(&release_master_cpu, NO_CPU);
186 return count;
187 } else {
188 err = sscanf(msg, "%d", &cpu);
189 if (err == 1 && cpu >= 0 && (online = cpu_online(cpu))) {
190 atomic_set(&release_master_cpu, cpu);
191 return count;
192 } else {
193 TRACE("invalid release master: '%s' "
194 "(err:%d cpu:%d online:%d)\n",
195 msg, err, cpu, online);
196 return -EINVAL;
197 }
198 }
199}
200#endif
201
202int __init init_litmus_proc(void)
203{
204 litmus_dir = proc_mkdir("litmus", NULL);
205 if (!litmus_dir) {
206 printk(KERN_ERR "Could not allocate LITMUS^RT procfs entry.\n");
207 return -ENOMEM;
208 }
209
210 curr_file = create_proc_entry("active_plugin",
211 0644, litmus_dir);
212 if (!curr_file) {
213 printk(KERN_ERR "Could not allocate active_plugin "
214 "procfs entry.\n");
215 return -ENOMEM;
216 }
217 curr_file->read_proc = proc_read_curr;
218 curr_file->write_proc = proc_write_curr;
219
220#ifdef CONFIG_RELEASE_MASTER
221 release_master_file = create_proc_entry("release_master",
222 0644, litmus_dir);
223 if (!release_master_file) {
224 printk(KERN_ERR "Could not allocate release_master "
225 "procfs entry.\n");
226 return -ENOMEM;
227 }
228 release_master_file->read_proc = proc_read_release_master;
229 release_master_file->write_proc = proc_write_release_master;
230#endif
231
232 clus_cache_idx_file = create_proc_entry("cluster_cache",
233 0644, litmus_dir);
234 if (!clus_cache_idx_file) {
235 printk(KERN_ERR "Could not allocate cluster_cache "
236 "procfs entry.\n");
237 return -ENOMEM;
238 }
239 clus_cache_idx_file->read_proc = proc_read_cluster_size;
240 clus_cache_idx_file->write_proc = proc_write_cluster_size;
241
242 stat_file = create_proc_read_entry("stats", 0444, litmus_dir,
243 proc_read_stats, NULL);
244
245 plugs_dir = proc_mkdir("plugins", litmus_dir);
246 if (!plugs_dir){
247 printk(KERN_ERR "Could not allocate plugins directory "
248 "procfs entry.\n");
249 return -ENOMEM;
250 }
251
252 plugs_file = create_proc_read_entry("loaded", 0444, plugs_dir,
253 proc_read_plugins, NULL);
254
255 return 0;
256}
257
258void exit_litmus_proc(void)
259{
260 if (plugs_file)
261 remove_proc_entry("loaded", plugs_dir);
262 if (plugs_dir)
263 remove_proc_entry("plugins", litmus_dir);
264 if (stat_file)
265 remove_proc_entry("stats", litmus_dir);
266 if (curr_file)
267 remove_proc_entry("active_plugin", litmus_dir);
268 if (clus_cache_idx_file)
269 remove_proc_entry("cluster_cache", litmus_dir);
270#ifdef CONFIG_RELEASE_MASTER
271 if (release_master_file)
272 remove_proc_entry("release_master", litmus_dir);
273#endif
274 if (litmus_dir)
275 remove_proc_entry("litmus", NULL);
276}
277
278long make_plugin_proc_dir(struct sched_plugin* plugin,
279 struct proc_dir_entry** pde_in)
280{
281 struct proc_dir_entry *pde_new = NULL;
282 long rv;
283
284 if (!plugin || !plugin->plugin_name){
285 printk(KERN_ERR "Invalid plugin struct passed to %s.\n",
286 __func__);
287 rv = -EINVAL;
288 goto out_no_pde;
289 }
290
291 if (!plugs_dir){
292 printk(KERN_ERR "Could not make plugin sub-directory, because "
293 "/proc/litmus/plugins does not exist.\n");
294 rv = -ENOENT;
295 goto out_no_pde;
296 }
297
298 pde_new = proc_mkdir(plugin->plugin_name, plugs_dir);
299 if (!pde_new){
300 printk(KERN_ERR "Could not make plugin sub-directory: "
301 "out of memory?.\n");
302 rv = -ENOMEM;
303 goto out_no_pde;
304 }
305
306 rv = 0;
307 *pde_in = pde_new;
308 goto out_ok;
309
310out_no_pde:
311 *pde_in = NULL;
312out_ok:
313 return rv;
314}
315
316void remove_plugin_proc_dir(struct sched_plugin* plugin)
317{
318 if (!plugin || !plugin->plugin_name){
319 printk(KERN_ERR "Invalid plugin struct passed to %s.\n",
320 __func__);
321 return;
322 }
323 remove_proc_entry(plugin->plugin_name, plugs_dir);
324}