aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-03-17 17:23:36 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2013-03-17 17:23:36 -0400
commit469aaad39c956446b8a31d351ee36bedd87ac18a (patch)
tree3e2864a01df8a04ab7a406342627d3dc850760af /include
parent9374a7c30b6906d01c548833fb8a7b65ba4b5ccc (diff)
Per-task budget high-resolution timers (hrtimers).
As a step towards implementing more complex budget tracking method (ex. BWI, VXR, etc.), we need per-task budget trackers because we may be required to drain budget from a task, even while it is suspended or blocked. This patch does: 1) Replaces the per-CPU hrtimers with per-task hrtimers. 2) Plugin architecture for different budget policies. This patch creates three budget draining policies: SIMPLE, SAWARE (suspension-aware), and SOBLIV (suspension-oblivious). However, only SIMPLE is supported by this patch. SIMPLE (default): Budget drains while the task is scheduled. Budget is preserved across self-suspensions (but not job completions, of course). Only SIMPLE is supported in this patch. (Maintaining current Litmus functionality.) SAWARE: Draining according to suspension-aware analysis. Budget should drain whenever a task is among the top-m tasks in its cluster, where m is the number of processors in said cluster. This draining should happen whether or not the task is actually scheduled. SOBLIV: Draining according to suspension-oblivious analysis. Budget should drain whenever the task is scheduled or suspended (but not due to preemption). Exception: Draining should halt when we can prove that the task is not among the top-m tasks blocked on the same lock (i.e., on the PQ in the OMLP-family locking protocols).
Diffstat (limited to 'include')
-rw-r--r--include/litmus/budget.h106
-rw-r--r--include/litmus/fdso.h2
-rw-r--r--include/litmus/gpu_affinity.h8
-rw-r--r--include/litmus/litmus.h2
-rw-r--r--include/litmus/rt_param.h26
-rw-r--r--include/litmus/sched_plugin.h1
6 files changed, 106 insertions, 39 deletions
diff --git a/include/litmus/budget.h b/include/litmus/budget.h
index 763b31c0e9f6..2a3511245f7a 100644
--- a/include/litmus/budget.h
+++ b/include/litmus/budget.h
@@ -1,26 +1,14 @@
1#ifndef _LITMUS_BUDGET_H_ 1#ifndef _LITMUS_BUDGET_H_
2#define _LITMUS_BUDGET_H_ 2#define _LITMUS_BUDGET_H_
3 3
4/* Update the per-processor enforcement timer (arm/reproram/cancel) for 4#include <linux/hrtimer.h>
5 * the next task. */ 5#include <linux/semaphore.h>
6void update_enforcement_timer(struct task_struct* t);
7 6
8/* Send SIG_BUDGET to a real-time task. */ 7#define budget_exhausted(t) \
9void send_sigbudget(struct task_struct* t); 8 (get_exec_time(t) >= get_exec_cost(t))
10 9
11inline static int budget_exhausted(struct task_struct* t) 10#define budget_remaining(t) \
12{ 11 ((!budget_exhausted(t)) ? (get_exec_cost(t) - get_exec_time(t)) : 0)
13 return get_exec_time(t) >= get_exec_cost(t);
14}
15
16inline static lt_t budget_remaining(struct task_struct* t)
17{
18 if (!budget_exhausted(t))
19 return get_exec_cost(t) - get_exec_time(t);
20 else
21 /* avoid overflow */
22 return 0;
23}
24 12
25#define budget_enforced(t) (\ 13#define budget_enforced(t) (\
26 tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT) 14 tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT)
@@ -29,21 +17,87 @@ inline static lt_t budget_remaining(struct task_struct* t)
29 tsk_rt(t)->task_params.budget_policy == PRECISE_ENFORCEMENT || \ 17 tsk_rt(t)->task_params.budget_policy == PRECISE_ENFORCEMENT || \
30 tsk_rt(t)->task_params.budget_signal_policy == PRECISE_SIGNALS) 18 tsk_rt(t)->task_params.budget_signal_policy == PRECISE_SIGNALS)
31 19
20#define budget_quantum_tracked(t) (\
21 tsk_rt(t)->task_params.budget_policy == QUANTUM_ENFORCEMENT || \
22 tsk_rt(t)->task_params.budget_signal_policy == QUANTUM_SIGNALS)
23
32#define budget_signalled(t) (\ 24#define budget_signalled(t) (\
33 tsk_rt(t)->task_params.budget_signal_policy != NO_SIGNALS) 25 tsk_rt(t)->task_params.budget_signal_policy != NO_SIGNALS)
34 26
35#define budget_precisely_signalled(t) (\ 27#define budget_precisely_signalled(t) (\
36 tsk_rt(t)->task_params.budget_policy == PRECISE_SIGNALS) 28 tsk_rt(t)->task_params.budget_policy == PRECISE_SIGNALS)
37 29
38#define sigbudget_sent(t) (\ 30#define bt_flag_is_set(t, flag_nr) (\
39 test_bit(RT_JOB_SIG_BUDGET_SENT, &tsk_rt(t)->job_params.flags)) 31 test_bit(flag_nr, &tsk_rt(t)->budget.flags))
32
33#define bt_flag_test_and_set(t, flag_nr) (\
34 test_and_set_bit(flag_nr, &tsk_rt(t)->budget.flags))
35
36#define bt_flag_set(t, flag_nr) (\
37 set_bit(flag_nr, &tsk_rt(t)->budget.flags))
38
39#define bt_flag_clear(t, flag_nr) (\
40 clear_bit(flag_nr, &tsk_rt(t)->budget.flags))
41
42#define bt_flags_reset(t) (\
43 tsk_rt(t)->budget.flags = 0)
44
45#define requeue_preempted_job(t) \
46 (t && (!budget_exhausted(t) || !budget_enforced(t)))
47
48struct enforcement_timer
49{
50 raw_spinlock_t lock;
51 struct hrtimer timer;
52 int armed:1;
53};
54
55typedef void (*scheduled_t)(struct task_struct* t);
56typedef void (*blocked_t)(struct task_struct* t);
57typedef void (*preempt_or_sleep_t)(struct task_struct* t);
58typedef void (*exhausted_t)(struct task_struct* t);
59typedef void (*exit_t)(struct task_struct* t);
40 60
41static inline int requeue_preempted_job(struct task_struct* t) 61struct budget_tracker_ops
42{ 62{
43 /* Add task to ready queue only if not subject to budget enforcement or 63 scheduled_t on_scheduled; /* called from litmus_schedule(). */
44 * if the job has budget remaining. t may be NULL. 64 blocked_t on_blocked; /* called from plugin::schedule() */
45 */ 65 preempt_or_sleep_t on_preempt_or_sleep; /* called from plugin::schedule() */
46 return t && (!budget_exhausted(t) || !budget_enforced(t)); 66
47} 67 exit_t on_exit; /* task exiting rt mode */
68
69 exhausted_t on_exhausted; /* called by plugin::tick() or timer interrupt */
70};
71
72struct budget_tracker
73{
74 struct enforcement_timer timer;
75 const struct budget_tracker_ops* ops;
76 unsigned long flags;
77};
78
79/* budget tracker flags */
80enum BT_FLAGS
81{
82 BTF_BUDGET_EXHAUSTED = 0,
83 BTF_SIG_BUDGET_SENT = 1,
84};
85
86/* Functions for simple DRAIN_SIMPLE policy common
87 * to every scheduler. Scheduler must provided
88 * implementation for simple_on_exhausted().
89 */
90void simple_on_scheduled(struct task_struct* t);
91void simple_on_blocked(struct task_struct* t);
92void simple_on_preempt_or_sleep(struct task_struct* t);
93void simple_on_exit(struct task_struct* t);
94
95
96void init_budget_tracker(struct budget_tracker* bt,
97 const struct budget_tracker_ops* ops);
98
99
100/* Send SIG_BUDGET to a real-time task. */
101void send_sigbudget(struct task_struct* t);
48 102
49#endif 103#endif
diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h
index f7887288d8f5..2d8e6c43d908 100644
--- a/include/litmus/fdso.h
+++ b/include/litmus/fdso.h
@@ -36,7 +36,7 @@ typedef enum {
36 KFMLP_GPU_AFF_OBS = 12, 36 KFMLP_GPU_AFF_OBS = 12,
37 37
38 PRIOQ_MUTEX = 13, 38 PRIOQ_MUTEX = 13,
39 39
40 MAX_OBJ_TYPE = 13 40 MAX_OBJ_TYPE = 13
41} obj_type_t; 41} obj_type_t;
42 42
diff --git a/include/litmus/gpu_affinity.h b/include/litmus/gpu_affinity.h
index 47da725717b0..f610f58b1f3b 100644
--- a/include/litmus/gpu_affinity.h
+++ b/include/litmus/gpu_affinity.h
@@ -11,6 +11,7 @@ gpu_migration_dist_t gpu_migration_distance(int a, int b);
11static inline void reset_gpu_tracker(struct task_struct* t) 11static inline void reset_gpu_tracker(struct task_struct* t)
12{ 12{
13 t->rt_param.accum_gpu_time = 0; 13 t->rt_param.accum_gpu_time = 0;
14 t->rt_param.gpu_time_stamp = 0;
14} 15}
15 16
16static inline void start_gpu_tracker(struct task_struct* t) 17static inline void start_gpu_tracker(struct task_struct* t)
@@ -22,11 +23,16 @@ static inline void stop_gpu_tracker(struct task_struct* t)
22{ 23{
23 lt_t now = litmus_clock(); 24 lt_t now = litmus_clock();
24 t->rt_param.accum_gpu_time += (now - t->rt_param.gpu_time_stamp); 25 t->rt_param.accum_gpu_time += (now - t->rt_param.gpu_time_stamp);
26 t->rt_param.gpu_time_stamp = 0;
25} 27}
26 28
27static inline lt_t get_gpu_time(struct task_struct* t) 29static inline lt_t get_gpu_time(struct task_struct* t)
28{ 30{
29 return t->rt_param.accum_gpu_time; 31 lt_t accum = t->rt_param.accum_gpu_time;
32 if (t->rt_param.gpu_time_stamp != 0) {
33 accum += (litmus_clock() - t->rt_param.gpu_time_stamp);
34 }
35 return accum;
30} 36}
31 37
32static inline lt_t get_gpu_estimate(struct task_struct* t, gpu_migration_dist_t dist) 38static inline lt_t get_gpu_estimate(struct task_struct* t, gpu_migration_dist_t dist)
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index 70b421d59d34..f6ea5f6e80ee 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -62,6 +62,7 @@ void litmus_exit_task(struct task_struct *tsk);
62#define get_priority(t) (tsk_rt(t)->task_params.priority) 62#define get_priority(t) (tsk_rt(t)->task_params.priority)
63#define get_class(t) (tsk_rt(t)->task_params.cls) 63#define get_class(t) (tsk_rt(t)->task_params.cls)
64#define get_release_policy(t) (tsk_rt(t)->task_params.release_policy) 64#define get_release_policy(t) (tsk_rt(t)->task_params.release_policy)
65#define get_drain_policy(t) (tsk_rt(t)->task_params.drain_policy)
65 66
66/* job_param macros */ 67/* job_param macros */
67#define get_exec_time(t) (tsk_rt(t)->job_params.exec_time) 68#define get_exec_time(t) (tsk_rt(t)->job_params.exec_time)
@@ -69,6 +70,7 @@ void litmus_exit_task(struct task_struct *tsk);
69#define get_period(t) (tsk_rt(t)->task_params.period) 70#define get_period(t) (tsk_rt(t)->task_params.period)
70#define get_release(t) (tsk_rt(t)->job_params.release) 71#define get_release(t) (tsk_rt(t)->job_params.release)
71#define get_lateness(t) (tsk_rt(t)->job_params.lateness) 72#define get_lateness(t) (tsk_rt(t)->job_params.lateness)
73#define get_budget_timer(t) (tsk_rt(t)->job_params.budget_timer)
72 74
73#define effective_priority(t) ((!(tsk_rt(t)->inh_task)) ? t : tsk_rt(t)->inh_task) 75#define effective_priority(t) ((!(tsk_rt(t)->inh_task)) ? t : tsk_rt(t)->inh_task)
74#define base_priority(t) (t) 76#define base_priority(t) (t)
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index bf0ee8dbae6e..887075b908ca 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -36,6 +36,14 @@ typedef enum {
36} budget_policy_t; 36} budget_policy_t;
37 37
38typedef enum { 38typedef enum {
39 /* all drain mechanisms are ignored if budget enforcement or signalling
40 is not in use. */
41 DRAIN_SIMPLE, /* drains while task is linked */
42 DRAIN_SAWARE, /* drains according to suspension-aware analysis */
43 DRAIN_SOBLIV, /* drains according to suspension-obliv analysis */
44} budget_drain_policy_t;
45
46typedef enum {
39 NO_SIGNALS, /* job receives no signals when it exhausts its budget */ 47 NO_SIGNALS, /* job receives no signals when it exhausts its budget */
40 QUANTUM_SIGNALS, /* budget signals are only sent on quantum boundaries */ 48 QUANTUM_SIGNALS, /* budget signals are only sent on quantum boundaries */
41 PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */ 49 PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */
@@ -132,6 +140,7 @@ struct rt_task {
132 unsigned int priority; 140 unsigned int priority;
133 task_class_t cls; 141 task_class_t cls;
134 budget_policy_t budget_policy; /* ignored by pfair */ 142 budget_policy_t budget_policy; /* ignored by pfair */
143 budget_drain_policy_t drain_policy;
135 budget_signal_policy_t budget_signal_policy; /* currently ignored by pfair */ 144 budget_signal_policy_t budget_signal_policy; /* currently ignored by pfair */
136 release_policy_t release_policy; 145 release_policy_t release_policy;
137}; 146};
@@ -213,8 +222,9 @@ struct control_page {
213/* don't export internal data structures to user space (liblitmus) */ 222/* don't export internal data structures to user space (liblitmus) */
214#ifdef __KERNEL__ 223#ifdef __KERNEL__
215 224
216#include <litmus/binheap.h>
217#include <linux/semaphore.h> 225#include <linux/semaphore.h>
226#include <litmus/budget.h>
227#include <litmus/binheap.h>
218 228
219#ifdef CONFIG_LITMUS_SOFTIRQD 229#ifdef CONFIG_LITMUS_SOFTIRQD
220#include <linux/interrupt.h> 230#include <linux/interrupt.h>
@@ -247,15 +257,8 @@ struct rt_job {
247 * Increase this sequence number when a job is released. 257 * Increase this sequence number when a job is released.
248 */ 258 */
249 unsigned int job_no; 259 unsigned int job_no;
250
251 /* bits:
252 * 0th: Set if a budget exhaustion signal has already been sent for
253 * the current job. */
254 unsigned long flags;
255}; 260};
256 261
257#define RT_JOB_SIG_BUDGET_SENT 0
258
259struct pfair_param; 262struct pfair_param;
260 263
261enum klmirqd_sem_status 264enum klmirqd_sem_status
@@ -278,12 +281,12 @@ typedef enum gpu_migration_dist
278 MIG_LAST = MIG_NONE 281 MIG_LAST = MIG_NONE
279} gpu_migration_dist_t; 282} gpu_migration_dist_t;
280 283
281typedef struct feedback_est{ 284typedef struct feedback_est
285{
282 fp_t est; 286 fp_t est;
283 fp_t accum_err; 287 fp_t accum_err;
284} feedback_est_t; 288} feedback_est_t;
285 289
286
287#define AVG_EST_WINDOW_SIZE 20 290#define AVG_EST_WINDOW_SIZE 20
288 291
289typedef int (*notify_rsrc_exit_t)(struct task_struct* tsk); 292typedef int (*notify_rsrc_exit_t)(struct task_struct* tsk);
@@ -417,7 +420,6 @@ struct rt_param {
417 struct binheap_node aux_task_owner_node; 420 struct binheap_node aux_task_owner_node;
418#endif 421#endif
419 422
420
421#ifdef CONFIG_NP_SECTION 423#ifdef CONFIG_NP_SECTION
422 /* For the FMLP under PSN-EDF, it is required to make the task 424 /* For the FMLP under PSN-EDF, it is required to make the task
423 * non-preemptive from kernel space. In order not to interfere with 425 * non-preemptive from kernel space. In order not to interfere with
@@ -427,6 +429,8 @@ struct rt_param {
427 unsigned int kernel_np; 429 unsigned int kernel_np;
428#endif 430#endif
429 431
432 struct budget_tracker budget;
433
430 /* This field can be used by plugins to store where the task 434 /* This field can be used by plugins to store where the task
431 * is currently scheduled. It is the responsibility of the 435 * is currently scheduled. It is the responsibility of the
432 * plugin to avoid race conditions. 436 * plugin to avoid race conditions.
diff --git a/include/litmus/sched_plugin.h b/include/litmus/sched_plugin.h
index 78cec30866ac..6e7d6df2fb78 100644
--- a/include/litmus/sched_plugin.h
+++ b/include/litmus/sched_plugin.h
@@ -130,6 +130,7 @@ struct sched_plugin {
130 schedule_t schedule; 130 schedule_t schedule;
131 finish_switch_t finish_switch; 131 finish_switch_t finish_switch;
132 132
133
133 /* syscall backend */ 134 /* syscall backend */
134 complete_job_t complete_job; 135 complete_job_t complete_job;
135 release_at_t release_at; 136 release_at_t release_at;