aboutsummaryrefslogtreecommitdiffstats
path: root/litmus.c
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@jupiter-cs.cs.unc.edu>2007-02-05 18:31:20 -0500
committerBjoern B. Brandenburg <bbb@jupiter-cs.cs.unc.edu>2007-02-05 18:31:20 -0500
commitb32b21bd57b21b249447e2944c4473e0d196bb4f (patch)
treefea9e8712fbc97f30003065074a1ff180f3e1de4 /litmus.c
liblitmus essential tools
liblitmus should consist only of the litmus library and the essential tools.
Diffstat (limited to 'litmus.c')
-rw-r--r--litmus.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/litmus.c b/litmus.c
new file mode 100644
index 0000000..6f4aa18
--- /dev/null
+++ b/litmus.c
@@ -0,0 +1,188 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <sys/types.h>
5#include <unistd.h>
6#include <errno.h>
7#include <signal.h>
8
9#include "litmus.h"
10
11/* this is missing in newer linux/unistd.h versions */
12
13#define _syscall0(type,name) \
14type name(void) \
15{\
16 return syscall(__NR_##name);\
17}
18
19#define _syscall1(type,name,type1,arg1) \
20type name(type1 arg1) \
21{\
22 return syscall(__NR_##name, arg1);\
23}
24
25
26#define _syscall2(type,name,type1,arg1,type2,arg2) \
27type name(type1 arg1,type2 arg2) \
28{\
29 return syscall(__NR_##name, arg1, arg2);\
30}
31
32
33/* clear the TID in the child */
34#define CLONE_CHILD_CLEARTID 0x00200000
35/* set the TID in the child */
36#define CLONE_CHILD_SETTID 0x01000000
37/* don't let the child run before we have completed setup */
38#define CLONE_STOPPED 0x02000000
39/* litmus clone flag */
40#define CLONE_REALTIME 0x10000000
41
42/* CLONE_REALTIME is necessary because CLONE_STOPPED will put a SIGSTOP in
43 * the pending signal queue. Thus the first thing a newly created task will
44 * do after it is released is to stop, which is not what we want
45 *
46 * CLONE_REALTIME just sets the status to TASK_STOPPED without queueing a
47 * signal.
48 */
49
50
51/* this is essentially a fork with CLONE_STOPPED */
52/* #define CLONE_LITMUS CLONE_STOPPED | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID */
53#define CLONE_LITMUS CLONE_REALTIME | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID
54
55/* we need to override libc because it wants to be clever
56 * and rejects our call without presenting it even to the kernel
57 */
58#define __NR_raw_clone 120
59
60
61_syscall2(int, raw_clone, unsigned long, flags, unsigned long, child_stack)
62
63
64const char* get_scheduler_name(spolicy scheduler)
65{
66 const char* name;
67
68 switch (scheduler){
69 case SCHED_LINUX :
70 name = "Linux";
71 break;
72 case SCHED_PFAIR:
73 name = "Pfair";
74 break;
75 case SCHED_PFAIR_STAGGER:
76 name = "Pfair (staggered)";
77 break;
78 case SCHED_PART_EDF:
79 name = "Partioned EDF";
80 break;
81 case SCHED_PART_EEVDF:
82 name = "Partioned EEVDF";
83 break;
84 case SCHED_GLOBAL_EDF:
85 name = "Global EDF";
86 break;
87 case SCHED_EDF_HSB:
88 name = "EDF-HSB";
89 break;
90 default:
91 name = "Unkown";
92 break;
93 }
94 return name;
95}
96
97int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
98 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
99}
100
101int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
102 task_class_t class)
103{
104 int ret;
105 rt_param_t params;
106 int rt_task = raw_clone(CLONE_LITMUS, 0);
107
108 if (rt_task < 0)
109 return rt_task;
110
111 if (rt_task > 0) {
112 /* we are the controller task */
113 params.period = period;
114 params.exec_cost = wcet;
115 params.cpu = cpu;
116 params.cls = class;
117 ret = set_rt_task_param(rt_task, &params);
118 if (ret < 0) {
119 /* we have a problem: we created the task but
120 * for some stupid reason we cannot set the real-time
121 * parameters. We must clean up the stopped task.
122 */
123 kill(rt_task, SIGKILL);
124 /* syscall will have set errno, we don't have to do
125 * anything
126 */
127 return -1;
128 }
129 ret = prepare_rt_task(rt_task);
130 if (ret < 0) {
131 /* same problem as above*/
132 //kill(rt_task, SIGKILL);
133 rt_task = -1;
134 }
135 return rt_task;
136 }
137 else {
138 /* we are the real-time task
139 * launch task and die when it is done
140 */
141
142 exit(rt_prog(arg));
143 }
144}
145
146
147void show_rt_param(rt_param_t* tp)
148{
149 printf("rt params:\n\t"
150 "exec_cost:\t%ld\n\tperiod:\t\t%ld\n\tcpu:\t%d\n",
151 tp->exec_cost, tp->period, tp->cpu);
152}
153
154task_class_t str2class(const char* str)
155{
156 if (!strcmp(str, "hrt"))
157 return RT_CLASS_HARD;
158 else if (!strcmp(str, "srt"))
159 return RT_CLASS_SOFT;
160 else if (!strcmp(str, "be"))
161 return RT_CLASS_BEST_EFFORT;
162 else
163 return -1;
164}
165
166
167/* Litmus syscalls definitions */
168#define __NR_sched_setpolicy 320
169#define __NR_sched_getpolicy 321
170#define __NR_set_rt_mode 322
171#define __NR_set_rt_task_param 323
172#define __NR_get_rt_task_param 324
173#define __NR_prepare_rt_task 325
174#define __NR_reset_stat 326
175#define __NR_sleep_next_period 327
176#define __NR_scheduler_setup 328
177
178
179/* Syscall stub for setting RT mode and scheduling options */
180_syscall1(spolicy, sched_setpolicy, spolicy, arg1);
181_syscall0(spolicy, sched_getpolicy);
182_syscall1(int, set_rt_mode, int, arg1);
183_syscall2(int, set_rt_task_param, pid_t, pid, rt_param_t*, arg1);
184_syscall2(int, get_rt_task_param, pid_t, pid, rt_param_t*, arg1);
185_syscall1(int, prepare_rt_task, pid_t, pid);
186_syscall0(int, reset_stat);
187_syscall0(int, sleep_next_period);
188_syscall2(int, scheduler_setup, int, cmd, void*, param);