aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2015-08-09 07:18:46 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2017-05-26 17:12:24 -0400
commitff34630ceb91174ab0d6cec03e00e2c2fa6585b4 (patch)
treeda162979a0bd8d89628a316d13ab1c59a9761e66
parentf298dae81d90b00d47be0ccb94a47be1861b5bf1 (diff)
Extend task_struct with rt_param
This patch adds the PCB extensions required for LITMUS^RT.
-rw-r--r--include/linux/sched.h5
-rw-r--r--include/litmus/rt_param.h291
2 files changed, 296 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f425eb3318ab..b52aa2d1d3e8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -126,6 +126,8 @@ struct sched_attr {
126 u64 sched_period; 126 u64 sched_period;
127}; 127};
128 128
129#include <litmus/rt_param.h>
130
129struct futex_pi_state; 131struct futex_pi_state;
130struct robust_list_head; 132struct robust_list_head;
131struct bio_list; 133struct bio_list;
@@ -1886,6 +1888,9 @@ struct task_struct {
1886 int nr_dirtied_pause; 1888 int nr_dirtied_pause;
1887 unsigned long dirty_paused_when; /* start of a write-and-pause period */ 1889 unsigned long dirty_paused_when; /* start of a write-and-pause period */
1888 1890
1891 /* LITMUS RT parameters and state */
1892 struct rt_param rt_param;
1893
1889#ifdef CONFIG_LATENCYTOP 1894#ifdef CONFIG_LATENCYTOP
1890 int latency_record_count; 1895 int latency_record_count;
1891 struct latency_record latency_record[LT_SAVECOUNT]; 1896 struct latency_record latency_record[LT_SAVECOUNT];
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
new file mode 100644
index 000000000000..8c7869f46bfb
--- /dev/null
+++ b/include/litmus/rt_param.h
@@ -0,0 +1,291 @@
1/*
2 * Definition of the scheduler plugin interface.
3 *
4 */
5#ifndef _LINUX_RT_PARAM_H_
6#define _LINUX_RT_PARAM_H_
7
8/* Litmus time type. */
9typedef unsigned long long lt_t;
10
11static inline int lt_after(lt_t a, lt_t b)
12{
13 return ((long long) b) - ((long long) a) < 0;
14}
15#define lt_before(a, b) lt_after(b, a)
16
17static inline int lt_after_eq(lt_t a, lt_t b)
18{
19 return ((long long) a) - ((long long) b) >= 0;
20}
21#define lt_before_eq(a, b) lt_after_eq(b, a)
22
23/* different types of clients */
24typedef enum {
25 RT_CLASS_HARD,
26 RT_CLASS_SOFT,
27 RT_CLASS_BEST_EFFORT
28} task_class_t;
29
30typedef enum {
31 NO_ENFORCEMENT, /* job may overrun unhindered */
32 QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */
33 PRECISE_ENFORCEMENT /* budgets are enforced with hrtimers */
34} budget_policy_t;
35
36/* Release behaviors for jobs. PERIODIC and EARLY jobs
37 must end by calling sys_complete_job() (or equivalent)
38 to set up their next release and deadline. */
39typedef enum {
40 /* Jobs are released sporadically (provided job precedence
41 constraints are met). */
42 TASK_SPORADIC,
43
44 /* Jobs are released periodically (provided job precedence
45 constraints are met). */
46 TASK_PERIODIC,
47
48 /* Jobs are released immediately after meeting precedence
49 constraints. Beware this can peg your CPUs if used in
50 the wrong applications. Only supported by EDF schedulers. */
51 TASK_EARLY
52} release_policy_t;
53
54/* We use the common priority interpretation "lower index == higher priority",
55 * which is commonly used in fixed-priority schedulability analysis papers.
56 * So, a numerically lower priority value implies higher scheduling priority,
57 * with priority 1 being the highest priority. Priority 0 is reserved for
58 * priority boosting. LITMUS_MAX_PRIORITY denotes the maximum priority value
59 * range.
60 */
61
62#define LITMUS_MAX_PRIORITY 512
63#define LITMUS_HIGHEST_PRIORITY 1
64#define LITMUS_LOWEST_PRIORITY (LITMUS_MAX_PRIORITY - 1)
65
66/* Provide generic comparison macros for userspace,
67 * in case that we change this later. */
68#define litmus_higher_fixed_prio(a, b) (a < b)
69#define litmus_lower_fixed_prio(a, b) (a > b)
70#define litmus_is_valid_fixed_prio(p) \
71 ((p) >= LITMUS_HIGHEST_PRIORITY && \
72 (p) <= LITMUS_LOWEST_PRIORITY)
73
74struct rt_task {
75 lt_t exec_cost;
76 lt_t period;
77 lt_t relative_deadline;
78 lt_t phase;
79 unsigned int cpu;
80 unsigned int priority;
81 task_class_t cls;
82 budget_policy_t budget_policy; /* ignored by pfair */
83 release_policy_t release_policy;
84};
85
86union np_flag {
87 uint64_t raw;
88 struct {
89 /* Is the task currently in a non-preemptive section? */
90 uint64_t flag:31;
91 /* Should the task call into the scheduler? */
92 uint64_t preempt:1;
93 } np;
94};
95
96/* The definition of the data that is shared between the kernel and real-time
97 * tasks via a shared page (see litmus/ctrldev.c).
98 *
99 * WARNING: User space can write to this, so don't trust
100 * the correctness of the fields!
101 *
102 * This servees two purposes: to enable efficient signaling
103 * of non-preemptive sections (user->kernel) and
104 * delayed preemptions (kernel->user), and to export
105 * some real-time relevant statistics such as preemption and
106 * migration data to user space. We can't use a device to export
107 * statistics because we want to avoid system call overhead when
108 * determining preemption/migration overheads).
109 */
110struct control_page {
111 /* This flag is used by userspace to communicate non-preempive
112 * sections. */
113 volatile union np_flag sched;
114
115 volatile uint64_t irq_count; /* Incremented by the kernel each time an IRQ is
116 * handled. */
117
118 /* Locking overhead tracing: userspace records here the time stamp
119 * and IRQ counter prior to starting the system call. */
120 uint64_t ts_syscall_start; /* Feather-Trace cycles */
121 uint64_t irq_syscall_start; /* Snapshot of irq_count when the syscall
122 * started. */
123
124 /* to be extended */
125};
126
127/* Expected offsets within the control page. */
128
129#define LITMUS_CP_OFFSET_SCHED 0
130#define LITMUS_CP_OFFSET_IRQ_COUNT 8
131#define LITMUS_CP_OFFSET_TS_SC_START 16
132#define LITMUS_CP_OFFSET_IRQ_SC_START 24
133
134/* don't export internal data structures to user space (liblitmus) */
135#ifdef __KERNEL__
136
137struct _rt_domain;
138struct bheap_node;
139struct release_heap;
140
141struct rt_job {
142 /* Time instant the the job was or will be released. */
143 lt_t release;
144
145 /* What is the current deadline? */
146 lt_t deadline;
147
148 /* How much service has this job received so far? */
149 lt_t exec_time;
150
151 /* By how much did the prior job miss its deadline by?
152 * Value differs from tardiness in that lateness may
153 * be negative (when job finishes before its deadline).
154 */
155 long long lateness;
156
157 /* Which job is this. This is used to let user space
158 * specify which job to wait for, which is important if jobs
159 * overrun. If we just call sys_sleep_next_period() then we
160 * will unintentionally miss jobs after an overrun.
161 *
162 * Increase this sequence number when a job is released.
163 */
164 unsigned int job_no;
165
166#ifdef CONFIG_SCHED_TASK_TRACE
167 /* Keep track of the last time the job suspended.
168 * -> used for tracing sporadic tasks. */
169 lt_t last_suspension;
170#endif
171};
172
173struct pfair_param;
174
175/* RT task parameters for scheduling extensions
176 * These parameters are inherited during clone and therefore must
177 * be explicitly set up before the task set is launched.
178 */
179struct rt_param {
180 /* Generic flags available for plugin-internal use. */
181 unsigned int flags:8;
182
183 /* do we need to check for srp blocking? */
184 unsigned int srp_non_recurse:1;
185
186 /* is the task present? (true if it can be scheduled) */
187 unsigned int present:1;
188
189 /* has the task completed? */
190 unsigned int completed:1;
191
192#ifdef CONFIG_LITMUS_LOCKING
193 /* Is the task being priority-boosted by a locking protocol? */
194 unsigned int priority_boosted:1;
195 /* If so, when did this start? */
196 lt_t boost_start_time;
197
198 /* How many LITMUS^RT locks does the task currently hold/wait for? */
199 unsigned int num_locks_held;
200 /* How many PCP/SRP locks does the task currently hold/wait for? */
201 unsigned int num_local_locks_held;
202#endif
203
204 /* user controlled parameters */
205 struct rt_task task_params;
206
207 /* timing parameters */
208 struct rt_job job_params;
209
210 /* Should the next job be released at some time other than
211 * just period time units after the last release?
212 */
213 unsigned int sporadic_release:1;
214 lt_t sporadic_release_time;
215
216
217 /* task representing the current "inherited" task
218 * priority, assigned by inherit_priority and
219 * return priority in the scheduler plugins.
220 * could point to self if PI does not result in
221 * an increased task priority.
222 */
223 struct task_struct* inh_task;
224
225#ifdef CONFIG_NP_SECTION
226 /* For the FMLP under PSN-EDF, it is required to make the task
227 * non-preemptive from kernel space. In order not to interfere with
228 * user space, this counter indicates the kernel space np setting.
229 * kernel_np > 0 => task is non-preemptive
230 */
231 unsigned int kernel_np;
232#endif
233
234 /* This field can be used by plugins to store where the task
235 * is currently scheduled. It is the responsibility of the
236 * plugin to avoid race conditions.
237 *
238 * This used by GSN-EDF and PFAIR.
239 */
240 volatile int scheduled_on;
241
242 /* Is the stack of the task currently in use? This is updated by
243 * the LITMUS core.
244 *
245 * Be careful to avoid deadlocks!
246 */
247 volatile int stack_in_use;
248
249 /* This field can be used by plugins to store where the task
250 * is currently linked. It is the responsibility of the plugin
251 * to avoid race conditions.
252 *
253 * Used by GSN-EDF.
254 */
255 volatile int linked_on;
256
257 /* PFAIR/PD^2 state. Allocated on demand. */
258 struct pfair_param* pfair;
259
260 /* Fields saved before BE->RT transition.
261 */
262 int old_policy;
263 int old_prio;
264
265 /* ready queue for this task */
266 struct _rt_domain* domain;
267
268 /* heap element for this task
269 *
270 * Warning: Don't statically allocate this node. The heap
271 * implementation swaps these between tasks, thus after
272 * dequeuing from a heap you may end up with a different node
273 * then the one you had when enqueuing the task. For the same
274 * reason, don't obtain and store references to this node
275 * other than this pointer (which is updated by the heap
276 * implementation).
277 */
278 struct bheap_node* heap_node;
279 struct release_heap* rel_heap;
280
281 /* Used by rt_domain to queue task in release list.
282 */
283 struct list_head list;
284
285 /* Pointer to the page shared between userspace and kernel. */
286 struct control_page * ctrl_page;
287};
288
289#endif
290
291#endif