aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-01-23 11:16:40 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-01-23 11:16:40 -0500
commitd56b86e42b72abb68ba74bf540ddc259f6b20f84 (patch)
treea9d78e760bcf4254d883c6242d384f9d1261098f /src
parent23701920e39a903883f19c2749383bba2a746405 (diff)
reorganize liblitmus to be more modular
Diffstat (limited to 'src')
-rw-r--r--src/adaptive.c3
-rw-r--r--src/kernel_iface.c61
-rw-r--r--src/litmus.c230
-rw-r--r--src/syscalls.c62
-rw-r--r--src/task.c72
5 files changed, 212 insertions, 216 deletions
diff --git a/src/adaptive.c b/src/adaptive.c
index ebf662d..6a7d7a2 100644
--- a/src/adaptive.c
+++ b/src/adaptive.c
@@ -2,6 +2,9 @@
2#include <unistd.h> 2#include <unistd.h>
3 3
4#include "litmus.h" 4#include "litmus.h"
5#include "internal.h"
6#include "syscalls.h"
7
5#include "adaptive.h" 8#include "adaptive.h"
6 9
7#define __NR_set_service_levels 346 10#define __NR_set_service_levels 346
diff --git a/src/kernel_iface.c b/src/kernel_iface.c
new file mode 100644
index 0000000..5751ca6
--- /dev/null
+++ b/src/kernel_iface.c
@@ -0,0 +1,61 @@
1#include <stdio.h>
2
3#include "litmus.h"
4#include "internal.h"
5
6struct np_flag {
7 #define RT_PREEMPTIVE 0x2050 /* = NP */
8 #define RT_NON_PREEMPTIVE 0x4e50 /* = P */
9 unsigned short preemptivity;
10
11 #define RT_EXIT_NP_REQUESTED 0x5251 /* = RQ */
12 unsigned short request;
13
14 unsigned int ctr;
15};
16
17int register_np_flag(struct np_flag* flag);
18int signal_exit_np(void);
19
20
21
22static struct np_flag np_flag;
23
24
25int init_kernel_iface(void)
26{
27 int ret;
28 np_flag.preemptivity = RT_PREEMPTIVE;
29 np_flag.ctr = 0;
30 ret = register_np_flag(&np_flag);
31 check("register_np_flag()");
32 return ret;
33}
34
35static inline void barrier(void)
36{
37 __asm__ __volatile__("sfence": : :"memory");
38}
39
40void enter_np(void)
41{
42 if (++np_flag.ctr == 1)
43 {
44 np_flag.request = 0;
45 barrier();
46 np_flag.preemptivity = RT_NON_PREEMPTIVE;
47 }
48}
49
50
51void exit_np(void)
52{
53 if (--np_flag.ctr == 0)
54 {
55 np_flag.preemptivity = RT_PREEMPTIVE;
56 barrier();
57 if (np_flag.request == RT_EXIT_NP_REQUESTED)
58 signal_exit_np();
59 }
60}
61
diff --git a/src/litmus.c b/src/litmus.c
index 531f501..4005345 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -1,53 +1,12 @@
1/* To get syscall() we need to define _GNU_SOURCE
2 * in modern glibc versions.
3 */
4#define _GNU_SOURCE
5#include <unistd.h> 1#include <unistd.h>
6#include <stdlib.h> 2#include <stdlib.h>
7#include <stdio.h> 3#include <stdio.h>
8#include <string.h> 4#include <string.h>
9#include <sys/types.h>
10#include <errno.h>
11#include <signal.h> 5#include <signal.h>
12#include <sys/mman.h> 6#include <sys/mman.h>
13 7
14
15
16#include "litmus.h" 8#include "litmus.h"
17 9#include "internal.h"
18
19/* this is missing in newer linux/unistd.h versions */
20
21#define _syscall0(type,name) \
22type name(void) \
23{\
24 return syscall(__NR_##name);\
25}
26
27#define _syscall1(type,name,type1,arg1) \
28type name(type1 arg1) \
29{\
30 return syscall(__NR_##name, arg1);\
31}
32
33
34#define _syscall2(type,name,type1,arg1,type2,arg2) \
35type name(type1 arg1,type2 arg2) \
36{\
37 return syscall(__NR_##name, arg1, arg2);\
38}
39
40#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
41type name(type1 arg1,type2 arg2, type3 arg3) \
42{\
43 return syscall(__NR_##name, arg1, arg2, arg3); \
44}
45
46#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
47type name(type1 arg1,type2 arg2, type3 arg3, type4 arg4) \
48{\
49 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
50}
51 10
52const char* get_scheduler_name(spolicy scheduler) 11const char* get_scheduler_name(spolicy scheduler)
53{ 12{
@@ -85,71 +44,6 @@ const char* get_scheduler_name(spolicy scheduler)
85 return name; 44 return name;
86} 45}
87 46
88static void tperrorx(char* msg)
89{
90 fprintf(stderr,
91 "Task %d: %s: %m",
92 getpid(), msg);
93 exit(-1);
94}
95
96/* common launch routine */
97int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
98 void* setup_arg)
99{
100 int ret;
101 int rt_task = fork();
102
103 if (rt_task == 0) {
104 /* we are the real-time task
105 * launch task and die when it is done
106 */
107 rt_task = getpid();
108 ret = setup(rt_task, setup_arg);
109 if (ret < 0)
110 tperrorx("could not setup task parameters");
111 ret = task_mode(LITMUS_RT_TASK);
112 if (ret < 0)
113 tperrorx("could not become real-time task");
114 exit(rt_prog(rt_arg));
115 }
116
117 return rt_task;
118}
119
120struct create_rt_param {
121 int cpu;
122 int wcet;
123 int period;
124 task_class_t class;
125};
126
127int setup_create_rt(int pid, struct create_rt_param* arg)
128{
129 rt_param_t params;
130 params.period = arg->period;
131 params.exec_cost = arg->wcet;
132 params.cpu = arg->cpu;
133 params.cls = arg->class;
134 return set_rt_task_param(pid, &params);
135}
136
137int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
138 task_class_t class)
139{
140 struct create_rt_param params;
141 params.cpu = cpu;
142 params.period = period;
143 params.wcet = wcet;
144 params.class = class;
145 return __launch_rt_task(rt_prog, arg,
146 (rt_setup_fn_t) setup_create_rt, &params);
147}
148
149int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
150 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
151}
152
153 47
154void show_rt_param(rt_param_t* tp) 48void show_rt_param(rt_param_t* tp)
155{ 49{
@@ -181,49 +75,6 @@ int sporadic_task(unsigned long e, unsigned long p,
181 return set_rt_task_param(getpid(), &param); 75 return set_rt_task_param(getpid(), &param);
182} 76}
183 77
184struct np_flag {
185 #define RT_PREEMPTIVE 0x2050 /* = NP */
186 #define RT_NON_PREEMPTIVE 0x4e50 /* = P */
187 unsigned short preemptivity;
188
189 #define RT_EXIT_NP_REQUESTED 0x5251 /* = RQ */
190 unsigned short request;
191
192 unsigned int ctr;
193};
194
195static struct np_flag np_flag;
196
197int register_np_flag(struct np_flag* flag);
198int signal_exit_np(void);
199
200
201static inline void barrier(void)
202{
203 __asm__ __volatile__("sfence": : :"memory");
204}
205
206void enter_np(void)
207{
208 if (++np_flag.ctr == 1)
209 {
210 np_flag.request = 0;
211 barrier();
212 np_flag.preemptivity = RT_NON_PREEMPTIVE;
213 }
214}
215
216
217void exit_np(void)
218{
219 if (--np_flag.ctr == 0)
220 {
221 np_flag.preemptivity = RT_PREEMPTIVE;
222 barrier();
223 if (np_flag.request == RT_EXIT_NP_REQUESTED)
224 signal_exit_np();
225 }
226}
227 78
228static int exit_requested = 0; 79static int exit_requested = 0;
229 80
@@ -237,79 +88,26 @@ int litmus_task_active(void)
237 return !exit_requested; 88 return !exit_requested;
238} 89}
239 90
240#define check(str) \
241 if (ret == -1) { \
242 perror(str); \
243 fprintf(stderr, \
244 "Warning: Could not initialize LITMUS^RT, " \
245 "%s failed.\n", str \
246 ); \
247 }
248 91
249void init_litmus(void) 92int init_kernel_iface(void);
93
94int init_litmus(void)
250{ 95{
251 int ret; 96 int ret, ret1, ret2;
252 np_flag.preemptivity = RT_PREEMPTIVE;
253 np_flag.ctr = 0;
254 97
255 ret = mlockall(MCL_CURRENT | MCL_FUTURE); 98 ret1 = ret = mlockall(MCL_CURRENT | MCL_FUTURE);
256 check("mlockall()"); 99 check("mlockall()");
257 ret = register_np_flag(&np_flag); 100 ret2 = ret = init_kernel_iface();
258 check("register_np_flag()"); 101 check("kernel <-> user space interface initialization");
102
259 signal(SIGINT, sig_handler); 103 signal(SIGINT, sig_handler);
260 signal(SIGTERM, sig_handler); 104 signal(SIGTERM, sig_handler);
261 signal(SIGHUP, sig_handler); 105 signal(SIGHUP, sig_handler);
262 signal(SIGUSR1, SIG_IGN); 106 signal(SIGUSR1, SIG_IGN);
107 return ret1 == 0 && ret2 == 0;
263} 108}
264 109
265 110void exit_litmus(void)
266/* Litmus syscalls definitions */ 111{
267#define __NR_sched_setpolicy 320 112 /* nothing to do in current version */
268#define __NR_sched_getpolicy 321 113}
269#define __NR_set_rt_mode 322
270#define __NR_set_rt_task_param 323
271#define __NR_get_rt_task_param 324
272#define __NR_sleep_next_period 326
273#define __NR_scheduler_setup 327
274#define __NR_register_np_flag 328
275#define __NR_signal_exit_np 329
276#define __NR_od_openx 330
277#define __NR_od_close 331
278#define __NR_pi_down 332
279#define __NR_pi_up 333
280#define __NR_srp_down 334
281#define __NR_srp_up 335
282#define __NR_reg_task_srp_sem 336
283#define __NR_get_job_no 337
284#define __NR_wait_for_job_release 338
285#define __NR_set_service_levels 339
286#define __NR_get_cur_service_level 340
287#define __NR_reg_ics_cb 341
288#define __NR_start_wcs 342
289#define __NR_task_mode 343
290
291/* Syscall stub for setting RT mode and scheduling options */
292_syscall0(spolicy, sched_getpolicy);
293_syscall1(int, set_rt_mode, int, arg1);
294_syscall2(int, set_rt_task_param, pid_t, pid, rt_param_t*, arg1);
295_syscall2(int, get_rt_task_param, pid_t, pid, rt_param_t*, arg1);
296_syscall0(int, sleep_next_period);
297_syscall2(int, scheduler_setup, int, cmd, void*, param);
298_syscall1(int, register_np_flag, struct np_flag*, flag);
299_syscall0(int, signal_exit_np);
300
301_syscall4(int, od_openx, int, fd, obj_type_t, type, int, obj_id,
302 void*, config);
303_syscall1(int, od_close, int, od);
304_syscall1(int, pi_down, int, od);
305_syscall1(int, pi_up, int, od);
306_syscall1(int, srp_down, int, od);
307_syscall1(int, srp_up, int, od);
308_syscall1(int, reg_task_srp_sem, int, od);
309
310_syscall1(int, get_job_no, unsigned int*, job_no);
311_syscall1(int, wait_for_job_release, unsigned int, job_no);
312
313_syscall1(int, start_wcs, int, od);
314_syscall1(int, reg_ics_cb, struct ics_cb*, ics_cb);
315_syscall1(int, task_mode, int, target_mode);
diff --git a/src/syscalls.c b/src/syscalls.c
new file mode 100644
index 0000000..a42fc62
--- /dev/null
+++ b/src/syscalls.c
@@ -0,0 +1,62 @@
1/* To get syscall() we need to define _GNU_SOURCE
2 * in modern glibc versions.
3 */
4#define _GNU_SOURCE
5#include <unistd.h>
6
7#include "litmus.h"
8
9#include "syscalls.h"
10
11struct np_flag;
12
13/* Litmus syscalls definitions */
14#define __NR_sched_setpolicy 320
15#define __NR_sched_getpolicy 321
16#define __NR_set_rt_mode 322
17#define __NR_set_rt_task_param 323
18#define __NR_get_rt_task_param 324
19#define __NR_sleep_next_period 326
20#define __NR_scheduler_setup 327
21#define __NR_register_np_flag 328
22#define __NR_signal_exit_np 329
23#define __NR_od_openx 330
24#define __NR_od_close 331
25#define __NR_pi_down 332
26#define __NR_pi_up 333
27#define __NR_srp_down 334
28#define __NR_srp_up 335
29#define __NR_reg_task_srp_sem 336
30#define __NR_get_job_no 337
31#define __NR_wait_for_job_release 338
32#define __NR_set_service_levels 339
33#define __NR_get_cur_service_level 340
34#define __NR_reg_ics_cb 341
35#define __NR_start_wcs 342
36#define __NR_task_mode 343
37
38/* Syscall stub for setting RT mode and scheduling options */
39_syscall0(spolicy, sched_getpolicy);
40_syscall1(int, set_rt_mode, int, arg1);
41_syscall2(int, set_rt_task_param, pid_t, pid, rt_param_t*, arg1);
42_syscall2(int, get_rt_task_param, pid_t, pid, rt_param_t*, arg1);
43_syscall0(int, sleep_next_period);
44_syscall2(int, scheduler_setup, int, cmd, void*, param);
45_syscall1(int, register_np_flag, struct np_flag*, flag);
46_syscall0(int, signal_exit_np);
47
48_syscall4(int, od_openx, int, fd, obj_type_t, type, int, obj_id,
49 void*, config);
50_syscall1(int, od_close, int, od);
51_syscall1(int, pi_down, int, od);
52_syscall1(int, pi_up, int, od);
53_syscall1(int, srp_down, int, od);
54_syscall1(int, srp_up, int, od);
55_syscall1(int, reg_task_srp_sem, int, od);
56
57_syscall1(int, get_job_no, unsigned int*, job_no);
58_syscall1(int, wait_for_job_release, unsigned int, job_no);
59
60_syscall1(int, start_wcs, int, od);
61_syscall1(int, reg_ics_cb, struct ics_cb*, ics_cb);
62_syscall1(int, task_mode, int, target_mode);
diff --git a/src/task.c b/src/task.c
new file mode 100644
index 0000000..47d68e1
--- /dev/null
+++ b/src/task.c
@@ -0,0 +1,72 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4
5#include "litmus.h"
6#include "internal.h"
7
8static void tperrorx(char* msg)
9{
10 fprintf(stderr,
11 "Task %d: %s: %m",
12 getpid(), msg);
13 exit(-1);
14}
15
16/* common launch routine */
17int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
18 void* setup_arg)
19{
20 int ret;
21 int rt_task = fork();
22
23 if (rt_task == 0) {
24 /* we are the real-time task
25 * launch task and die when it is done
26 */
27 rt_task = getpid();
28 ret = setup(rt_task, setup_arg);
29 if (ret < 0)
30 tperrorx("could not setup task parameters");
31 ret = task_mode(LITMUS_RT_TASK);
32 if (ret < 0)
33 tperrorx("could not become real-time task");
34 exit(rt_prog(rt_arg));
35 }
36
37 return rt_task;
38}
39
40struct create_rt_param {
41 int cpu;
42 int wcet;
43 int period;
44 task_class_t class;
45};
46
47int setup_create_rt(int pid, struct create_rt_param* arg)
48{
49 rt_param_t params;
50 params.period = arg->period;
51 params.exec_cost = arg->wcet;
52 params.cpu = arg->cpu;
53 params.cls = arg->class;
54 return set_rt_task_param(pid, &params);
55}
56
57int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
58 task_class_t class)
59{
60 struct create_rt_param params;
61 params.cpu = cpu;
62 params.period = period;
63 params.wcet = wcet;
64 params.class = class;
65 return __launch_rt_task(rt_prog, arg,
66 (rt_setup_fn_t) setup_create_rt, &params);
67}
68
69int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
70 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
71}
72