1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include "litmus.h"
#include "internal.h"
static void tperrorx(char* msg)
{
fprintf(stderr,
"Task %d: %s: %m",
gettid(), msg);
exit(-1);
}
/* common launch routine */
int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
void* setup_arg)
{
int ret;
int rt_task = fork();
if (rt_task == 0) {
/* we are the real-time task
* launch task and die when it is done
*/
rt_task = gettid();
ret = setup(rt_task, setup_arg);
if (ret < 0)
tperrorx("could not setup task parameters");
ret = task_mode(LITMUS_RT_TASK);
if (ret < 0)
tperrorx("could not become real-time task");
exit(rt_prog(rt_arg));
}
return rt_task;
}
int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
int period, lt_t *frac1, lt_t *frac2,
int cpu1, int cpu2, task_class_t class)
{
struct rt_task params;
params.cpu = cpu;
params.period = period;
params.exec_cost = wcet;
params.cls = class;
params.phase = 0;
/* enforce budget for tasks that might not use sleep_next_period() */
params.budget_policy = QUANTUM_ENFORCEMENT;
/* edf-fm check on denominators for migratory tasks */
if (frac1[1] != 0 && frac2[1] != 0) {
/* edf-fm migrat task */
params.nr_cpus = 1;
params.cpus[0] = cpu1;
params.cpus[1] = cpu2;
params.fraction[0][0] = frac1[0];
params.fraction[1][0] = frac1[1];
params.fraction[0][1] = frac2[0];
params.fraction[1][1] = frac2[1];
}
return __launch_rt_task(rt_prog, arg,
(rt_setup_fn_t) set_rt_task_param, ¶ms);
}
int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
int period, int npsf_id, task_class_t class)
{
struct rt_task params;
params.cpu = cpu;
params.period = period;
params.exec_cost = wcet;
params.cls = class;
params.phase = 0;
/* enforce budget for tasks that might not use sleep_next_period() */
params.budget_policy = QUANTUM_ENFORCEMENT;
params.npsf_id = npsf_id;
return __launch_rt_task(rt_prog, arg,
(rt_setup_fn_t) set_rt_task_param, ¶ms);
}
int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
task_class_t class)
{
struct rt_task params;
params.cpu = cpu;
params.period = period;
params.exec_cost = wcet;
params.cls = class;
params.phase = 0;
/* enforce budget for tasks that might not use sleep_next_period() */
params.budget_policy = QUANTUM_ENFORCEMENT;
return __launch_rt_task(rt_prog, arg,
(rt_setup_fn_t) set_rt_task_param, ¶ms);
}
int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
}
#define SCHED_NORMAL 0
#define SCHED_LITMUS 6
int task_mode(int mode)
{
struct sched_param param;
int me = gettid();
int policy = sched_getscheduler(gettid());
int old_mode = policy == SCHED_LITMUS ? LITMUS_RT_TASK : BACKGROUND_TASK;
param.sched_priority = 0;
if (old_mode == LITMUS_RT_TASK && mode == BACKGROUND_TASK) {
/* transition to normal task */
return sched_setscheduler(me, SCHED_NORMAL, ¶m);
} else if (old_mode == BACKGROUND_TASK && mode == LITMUS_RT_TASK) {
/* transition to RT task */
return sched_setscheduler(me, SCHED_LITMUS, ¶m);
} else {
errno = -EINVAL;
return -1;
}
}
|