diff options
| author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2015-08-09 07:18:56 -0400 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2015-08-09 07:20:36 -0400 |
| commit | 8e51b378224ae53244c6917964c88aa2a9d024ad (patch) | |
| tree | 2c79843a5054a32e23a3fc9e02309990e6f66c24 | |
| parent | b7215111b2f62ff312472de821c16904c518f921 (diff) | |
Add PD^2 scheduler plugin2015.1
| -rw-r--r-- | litmus/Kconfig | 13 | ||||
| -rw-r--r-- | litmus/Makefile | 1 | ||||
| -rw-r--r-- | litmus/sched_pfair.c | 1226 |
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 | ||
| 15 | config 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 | |||
| 15 | config RELEASE_MASTER | 28 | config 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 | ||
| 26 | obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o | 26 | obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o |
| 27 | obj-$(CONFIG_PLUGIN_PFAIR) += sched_pfair.o | ||
| 27 | 28 | ||
| 28 | obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o | 29 | obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o |
| 29 | obj-$(CONFIG_SCHED_TASK_TRACE) += sched_task_trace.o | 30 | obj-$(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 | |||
| 33 | static enum cache_level pfair_cluster_level = GLOBAL_CLUSTER; | ||
| 34 | |||
| 35 | struct 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 | |||
| 43 | struct 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 | |||
| 62 | struct 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 | |||
| 92 | struct 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 | |||
| 108 | static inline struct pfair_cluster* cpu_cluster(struct pfair_state* state) | ||
| 109 | { | ||
| 110 | return container_of(state->topology.cluster, struct pfair_cluster, topology); | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline int cpu_id(struct pfair_state* state) | ||
| 114 | { | ||
| 115 | return state->topology.id; | ||
| 116 | } | ||
| 117 | |||
| 118 | static 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 | |||
| 123 | static inline struct pfair_cluster* from_domain(rt_domain_t* rt) | ||
| 124 | { | ||
| 125 | return container_of(rt, struct pfair_cluster, pfair); | ||
| 126 | } | ||
| 127 | |||
| 128 | static 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 | |||
| 134 | static inline raw_spinlock_t* cpu_lock(struct pfair_state* state) | ||
| 135 | { | ||
| 136 | return cluster_lock(cpu_cluster(state)); | ||
| 137 | } | ||
| 138 | |||
| 139 | DEFINE_PER_CPU(struct pfair_state, pfair_state); | ||
| 140 | struct pfair_state* *pstate; /* short cut */ | ||
| 141 | |||
| 142 | static struct pfair_cluster* pfair_clusters; | ||
| 143 | static 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... */ | ||
| 158 | static struct subtask* cur_subtask(struct task_struct* t) | ||
| 159 | { | ||
| 160 | return tsk_pfair(t)->subtasks + tsk_pfair(t)->cur; | ||
| 161 | } | ||
| 162 | |||
| 163 | static quanta_t cur_deadline(struct task_struct* t) | ||
| 164 | { | ||
| 165 | return cur_subtask(t)->deadline + tsk_pfair | ||
