aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/rt_param.h14
-rw-r--r--litmus/Makefile9
-rwxr-xr-xlitmus/sched_pfair.c785
3 files changed, 799 insertions, 9 deletions
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index a7dd67a81a..7bb568432e 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -64,6 +64,8 @@ struct rt_job {
64}; 64};
65 65
66 66
67struct pfair_param;
68
67/* RT task parameters for scheduling extensions 69/* RT task parameters for scheduling extensions
68 * These parameters are inherited during clone and therefore must 70 * These parameters are inherited during clone and therefore must
69 * be explicitly set up before the task set is launched. 71 * be explicitly set up before the task set is launched.
@@ -108,15 +110,12 @@ struct rt_param {
108 * is currently scheduled. It is the responsibility of the 110 * is currently scheduled. It is the responsibility of the
109 * plugin to avoid race conditions. 111 * plugin to avoid race conditions.
110 * 112 *
111 * Used by GSN-EDF. 113 * This used by GSN-EDF and PFAIR.
112 */ 114 */
113 volatile int scheduled_on; 115 volatile int scheduled_on;
114 116
115 /* Is the stack of the task currently in use? Currently, this 117 /* Is the stack of the task currently in use? This is updated by
116 * is the responsibility of the plugin to update this field. 118 * the LITMUS core.
117 * Maybe become part of the LITMUS core some day.
118 *
119 * Used by GSN-EDF.
120 * 119 *
121 * Be careful to avoid deadlocks! 120 * Be careful to avoid deadlocks!
122 */ 121 */
@@ -130,6 +129,9 @@ struct rt_param {
130 */ 129 */
131 volatile int linked_on; 130 volatile int linked_on;
132 131
132 /* PFAIR/PD^2 state. Allocated on demand. */
133 struct pfair_param* pfair;
134
133 /* Fields saved before BE->RT transition. 135 /* Fields saved before BE->RT transition.
134 */ 136 */
135 int old_policy; 137 int old_policy;
diff --git a/litmus/Makefile b/litmus/Makefile
index bfe393eb56..545203876a 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -3,9 +3,12 @@
3# 3#
4 4
5obj-y = sched_plugin.o litmus.o sched_trace.o \ 5obj-y = sched_plugin.o litmus.o sched_trace.o \
6 edf_common.o jobs.o\ 6 edf_common.o jobs.o \
7 sched_gsn_edf.o sched_psn_edf.o sched_cedf.o \
8 rt_domain.o fdso.o sync.o \ 7 rt_domain.o fdso.o sync.o \
9 fmlp.o srp.o norqlock.o 8 fmlp.o srp.o norqlock.o \
9 sched_gsn_edf.o \
10 sched_psn_edf.o \
11 sched_cedf.o \
12 sched_pfair.o
10 13
11obj-$(CONFIG_FEATHER_TRACE) += trace.o ft_event.o 14obj-$(CONFIG_FEATHER_TRACE) += trace.o ft_event.o
diff --git a/litmus/sched_pfair.c b/litmus/sched_pfair.c
new file mode 100755
index 0000000000..6f95688508
--- /dev/null
+++ b/litmus/sched_pfair.c
@@ -0,0 +1,785 @@
1/*
2 * kernel/sched_pfair.c
3 *
4 * Implementation of the (global) Pfair scheduling algorithm.
5 *
6 */
7
8#include <asm/div64.h>
9#include <linux/delay.h>
10#include <linux/module.h>
11#include <linux/spinlock.h>
12#include <linux/percpu.h>
13#include <linux/sched.h>
14#include <linux/list.h>
15
16#include <litmus/litmus.h>
17#include <litmus/jobs.h>
18#include <litmus/rt_domain.h>
19#include <litmus/sched_plugin.h>
20#include <litmus/sched_trace.h>
21
22#include <litmus/heap.h>
23
24/* Tick period is used to convert ns-specified execution
25 * costs and periods into tick-based equivalents.
26 */
27extern ktime_t tick_period;
28
29/* make the unit explicit */
30typedef unsigned long quanta_t;
31
32struct subtask {
33 /* measured in quanta relative to job release */
34 quanta_t release;
35 quanta_t deadline;
36 quanta_t overlap; /* called "b bit" by PD^2 */
37 quanta_t group_deadline;
38};
39
40struct pfair_param {
41 quanta_t quanta; /* number of subtasks */
42 quanta_t cur; /* index of current subtask */
43
44 quanta_t release; /* in quanta */
45 quanta_t period; /* in quanta */
46
47 quanta_t last_quantum; /* when scheduled last */
48 int last_cpu; /* where scheduled last */
49
50 unsigned int present; /* Can the task be scheduled? */
51
52 struct subtask subtasks[0]; /* allocate together with pfair_param */
53};
54
55#define tsk_pfair(tsk) ((tsk)->rt_param.pfair)
56
57struct pfair_state {
58 int cpu;
59 volatile quanta_t cur_tick; /* updated by the CPU that is advancing
60 * the time */
61 volatile quanta_t local_tick; /* What tick is the local CPU currently
62 * executing? Updated only by the local
63 * CPU. In QEMU, this may lag behind the
64 * current tick. In a real system, with
65 * proper timers and aligned quanta,
66 * that should only be the
67 * case for a very short time after the
68 * time advanced. With staggered quanta,
69 * it will lag for the duration of the
70 * offset.
71 */
72
73 struct task_struct* linked; /* the task that should be executing */
74 struct task_struct* local; /* the local copy of linked */
75 struct task_struct* scheduled; /* what is actually scheduled */
76
77 unsigned long missed_quanta;
78};
79
80/* Currently, we limit the maximum period of any task to 1000 quanta.
81 * The reason is that it makes the implementation easier since we do not
82 * need to reallocate the release wheel on task arrivals.
83 * In the future
84 */
85#define PFAIR_MAX_PERIOD 1000
86
87/* This is the release queue wheel. It is indexed by pfair_time %
88 * PFAIR_MAX_PERIOD. Each heap is ordered by PFAIR priority, so that it can be
89 * merged with the ready queue.
90 */
91static struct heap release_queue[PFAIR_MAX_PERIOD];
92
93DEFINE_PER_CPU(struct pfair_state, pfair_state);
94struct pfair_state* pstate[NR_CPUS]; /* short cut */
95
96#define NO_CPU 0xffffffff
97
98static quanta_t pfair_time = 0; /* the "official" PFAIR clock */
99static quanta_t merge_time = 0; /* Updated after the release queue has been
100 * merged. Used by drop_all_references().
101 */
102
103static rt_domain_t pfair;
104
105/* The pfair_lock is used to serialize all scheduling events.
106 */
107#define pfair_lock pfair.ready_lock
108
109/* Enable for lots of trace info.
110 * #define PFAIR_DEBUG
111 */
112
113#ifdef PFAIR_DEBUG
114#define PTRACE_TASK(t, f, args...) TRACE_TASK(t, f, # args)
115#define PTRACE(f, args...) TRACE(f, # args)
116#else
117#define PTRACE_TASK(t, f, args...)
118#define PTRACE(f, args...)
119#endif
120
121/* gcc will inline all of these accessor functions... */
122static struct subtask* cur_subtask(struct task_struct* t)
123{
124 return tsk_pfair(t)->subtasks + tsk_pfair(t)->cur;
125}
126
127static quanta_t cur_deadline(struct task_struct* t)
128{
129 return cur_subtask(t)->deadline + tsk_pfair(t)->release;
130}
131
132static quanta_t cur_release(struct task_struct* t)
133{
134#ifdef EARLY_RELEASE
135 /* only the release of the first subtask counts when we early
136 * release */
137 return tsk_pfair(t)->release;
138#else
139 return cur_subtask(t)->release + tsk_pfair(t)->release;
140#endif
141}
142
143static quanta_t cur_sub_release(struct task_struct* t)
144{
145 return cur_subtask(t)->release + tsk_pfair(t)->release;
146}
147
148static quanta_t cur_overlap(struct task_struct* t)
149{
150 return cur_subtask(t)->overlap;
151}
152
153static quanta_t cur_group_deadline(struct task_struct* t)
154{
155 quanta_t gdl = cur_subtask(t)->group_deadline;
156 if (gdl)
157 return gdl + tsk_pfair(t)->release;
158 else
159 return gdl;
160}
161
162e