aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2015-08-09 07:18:56 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2015-08-09 07:20:36 -0400
commit8e51b378224ae53244c6917964c88aa2a9d024ad (patch)
tree2c79843a5054a32e23a3fc9e02309990e6f66c24
parentb7215111b2f62ff312472de821c16904c518f921 (diff)
Add PD^2 scheduler plugin2015.1
-rw-r--r--litmus/Kconfig13
-rw-r--r--litmus/Makefile1
-rw-r--r--litmus/sched_pfair.c1226
3 files changed, 1240 insertions, 0 deletions
diff --git a/litmus/Kconfig b/litmus/Kconfig
index 38d9e433b345..babb43deffb5 100644
--- a/litmus/Kconfig
+++ b/litmus/Kconfig
@@ -12,6 +12,19 @@ config PLUGIN_CEDF
12 On smaller platforms (e.g., ARM PB11MPCore), using C-EDF 12 On smaller platforms (e.g., ARM PB11MPCore), using C-EDF
13 makes little sense since there aren't any shared caches. 13 makes little sense since there aren't any shared caches.
14 14
15config PLUGIN_PFAIR
16 bool "PFAIR"
17 default y
18 help
19 Include the PFAIR plugin (i.e., the PD^2 scheduler) in the kernel.
20 The PFAIR plugin requires high resolution timers (for staggered
21 quanta) and also requires HZ_PERIODIC (i.e., periodic timer ticks
22 even if a processor is idle, as quanta could be missed otherwise).
23 Further, the PFAIR plugin uses the system tick and thus requires
24 HZ=1000 to achive reasonable granularity.
25
26 If unsure, say Yes.
27
15config RELEASE_MASTER 28config RELEASE_MASTER
16 bool "Release-master Support" 29 bool "Release-master Support"
17 depends on ARCH_HAS_SEND_PULL_TIMERS && SMP 30 depends on ARCH_HAS_SEND_PULL_TIMERS && SMP
diff --git a/litmus/Makefile b/litmus/Makefile
index 7d637197d736..7970cd55e7fd 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -24,6 +24,7 @@ obj-y = sched_plugin.o litmus.o \
24 sched_pfp.o 24 sched_pfp.o
25 25
26obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o 26obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o
27obj-$(CONFIG_PLUGIN_PFAIR) += sched_pfair.o
27 28
28obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o 29obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
29obj-$(CONFIG_SCHED_TASK_TRACE) += sched_task_trace.o 30obj-$(CONFIG_SCHED_TASK_TRACE) += sched_task_trace.o
diff --git a/litmus/sched_pfair.c b/litmus/sched_pfair.c
new file mode 100644
index 000000000000..3f82378f5ca8
--- /dev/null
+++ b/litmus/sched_pfair.c
@@ -0,0 +1,1226 @@
1/*
2 * kernel/sched_pfair.c
3 *
4 * Implementation of the PD^2 pfair scheduling algorithm. This
5 * implementation realizes "early releasing," i.e., it is work-conserving.
6 *
7 */
8
9#include <asm/div64.h>
10#include <linux/delay.h>
11#include <linux/module.h>
12#include <linux/spinlock.h>
13#include <linux/percpu.h>
14#include <linux/sched.h>
15#include <linux/list.h>
16#include <linux/slab.h>
17
18#include <litmus/litmus.h>
19#include <litmus/jobs.h>
20#include <litmus/preempt.h>
21#include <litmus/rt_domain.h>
22#include <litmus/sched_plugin.h>
23#include <litmus/sched_trace.h>
24#include <litmus/trace.h>
25
26#include <litmus/bheap.h>
27
28/* to configure the cluster size */
29#include <litmus/litmus_proc.h>
30
31#include <litmus/clustered.h>
32
33static enum cache_level pfair_cluster_level = GLOBAL_CLUSTER;
34
35struct subtask {
36 /* measured in quanta relative to job release */
37 quanta_t release;
38 quanta_t deadline;
39 quanta_t overlap; /* called "b bit" by PD^2 */
40 quanta_t group_deadline;
41};
42
43struct pfair_param {
44 quanta_t quanta; /* number of subtasks */
45 quanta_t cur; /* index of current subtask */
46
47 quanta_t release; /* in quanta */
48 quanta_t period; /* in quanta */
49
50 quanta_t last_quantum; /* when scheduled last */
51 int last_cpu; /* where scheduled last */
52
53 unsigned int needs_requeue:1;
54
55 struct pfair_cluster* cluster; /* where this task is scheduled */
56
57 struct subtask subtasks[0]; /* allocate together with pfair_param */
58};
59
60#define tsk_pfair(tsk) ((tsk)->rt_param.pfair)
61
62struct pfair_state {
63 struct cluster_cpu topology;
64
65 struct hrtimer quantum_timer;
66
67 volatile quanta_t cur_tick; /* updated by the CPU that is advancing
68 * the time */
69 volatile quanta_t local_tick; /* What tick is the local CPU currently
70 * executing? Updated only by the local
71 * CPU. In QEMU, this may lag behind the
72 * current tick. In a real system, with
73 * proper timers and aligned quanta,
74 * that should only be the case for a
75 * very short time after the time
76 * advanced. With staggered quanta, it
77 * will lag for the duration of the
78 * offset.
79 */
80
81 struct task_struct* linked; /* the task that should be executing */
82 struct task_struct* local; /* the local copy of linked */
83 struct task_struct* scheduled; /* what is actually scheduled */
84
85 struct list_head out_of_budget; /* list of tasks that exhausted their allocation */
86
87 lt_t offset; /* stagger offset */
88 unsigned int missed_updates;
89 unsigned int missed_quanta;
90};
91
92struct pfair_cluster {
93 struct scheduling_cluster topology;
94
95 /* The "global" time in this cluster. */
96 quanta_t pfair_time; /* the "official" PFAIR clock */
97
98 /* The ready queue for this cluster. */
99 rt_domain_t pfair;
100
101 /* The set of jobs that should have their release enacted at the next
102 * quantum boundary.
103 */
104 struct bheap release_queue;
105 raw_spinlock_t release_lock;
106};
107
108static inline struct pfair_cluster* cpu_cluster(struct pfair_state* state)
109{
110 return container_of(state->topology.cluster, struct pfair_cluster, topology);
111}
112
113static inline int cpu_id(struct pfair_state* state)
114{
115 return state->topology.id;
116}
117
118static inline struct pfair_state* from_cluster_list(struct list_head* pos)
119{
120 return list_entry(pos, struct pfair_state, topology.cluster_list);
121}
122
123static inline struct pfair_cluster* from_domain(rt_domain_t* rt)
124{
125 return container_of(rt, struct pfair_cluster, pfair);
126}
127
128static inline raw_spinlock_t* cluster_lock(struct pfair_cluster* cluster)
129{
130 /* The ready_lock is used to serialize all scheduling events. */
131 return &cluster->pfair.ready_lock;
132}
133
134static inline raw_spinlock_t* cpu_lock(struct pfair_state* state)
135{
136 return cluster_lock(cpu_cluster(state));
137}
138
139DEFINE_PER_CPU(struct pfair_state, pfair_state);
140struct pfair_state* *pstate; /* short cut */
141
142static struct pfair_cluster* pfair_clusters;
143static int num_pfair_clusters;
144
145/* Enable for lots of trace info.
146 * #define PFAIR_DEBUG
147 */
148
149#ifdef PFAIR_DEBUG
150#define PTRACE_TASK(t, f, args...) TRACE_TASK(t, f, ## args)
151#define PTRACE(f, args...) TRACE(f, ## args)
152#else
153#define PTRACE_TASK(t, f, args...)
154#define PTRACE(f, args...)
155#endif
156
157/* gcc will inline all of these accessor functions... */
158static struct subtask* cur_subtask(struct task_struct* t)
159{
160 return tsk_pfair(t)->subtasks + tsk_pfair(t)->cur;
161}
162
163static quanta_t cur_deadline(struct task_struct* t)
164{
165 return cur_subtask(t)->deadline + tsk_pfair