aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2016-03-16 07:59:07 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-03-20 14:30:35 -0400
commit2a38056cc098c56a04bbe18f4e752f4fa782599f (patch)
treec38619d281c9b7ae23333573b322bab72d8801b3 /include/litmus
parent095f515b2fd903a0140afcc42db9a9f76d688b65 (diff)
Add basic generic reservation-based scheduling infrastructure
Diffstat (limited to 'include/litmus')
-rw-r--r--include/litmus/reservations/alloc.h15
-rw-r--r--include/litmus/reservations/budget-notifier.h50
-rw-r--r--include/litmus/reservations/polling.h19
-rw-r--r--include/litmus/reservations/reservation.h223
-rw-r--r--include/litmus/reservations/table-driven.h23
5 files changed, 330 insertions, 0 deletions
diff --git a/include/litmus/reservations/alloc.h b/include/litmus/reservations/alloc.h
new file mode 100644
index 000000000000..b3471288c9f1
--- /dev/null
+++ b/include/litmus/reservations/alloc.h
@@ -0,0 +1,15 @@
1#ifndef LITMUS_RESERVATIONS_ALLOC_H
2#define LITMUS_RESERVATIONS_ALLOC_H
3
4#include <litmus/reservations/reservation.h>
5
6long alloc_polling_reservation(
7 int res_type,
8 struct reservation_config *config,
9 struct reservation **_res);
10
11long alloc_table_driven_reservation(
12 struct reservation_config *config,
13 struct reservation **_res);
14
15#endif \ No newline at end of file
diff --git a/include/litmus/reservations/budget-notifier.h b/include/litmus/reservations/budget-notifier.h
new file mode 100644
index 000000000000..d831fa9d5153
--- /dev/null
+++ b/include/litmus/reservations/budget-notifier.h
@@ -0,0 +1,50 @@
1#ifndef LITMUS_BUDGET_NOTIFIER_H
2#define LITMUS_BUDGET_NOTIFIER_H
3
4#include <linux/list.h>
5#include <linux/spinlock.h>
6
7struct budget_notifier;
8
9typedef void (*budget_callback_t) (
10 struct budget_notifier *bn
11);
12
13struct budget_notifier {
14 struct list_head list;
15 budget_callback_t budget_exhausted;
16 budget_callback_t budget_replenished;
17};
18
19struct budget_notifier_list {
20 struct list_head list;
21 raw_spinlock_t lock;
22};
23
24void budget_notifier_list_init(struct budget_notifier_list* bnl);
25
26static inline void budget_notifier_add(
27 struct budget_notifier_list *bnl,
28 struct budget_notifier *bn)
29{
30 unsigned long flags;
31
32 raw_spin_lock_irqsave(&bnl->lock, flags);
33 list_add(&bn->list, &bnl->list);
34 raw_spin_unlock_irqrestore(&bnl->lock, flags);
35}
36
37static inline void budget_notifier_remove(
38 struct budget_notifier_list *bnl,
39 struct budget_notifier *bn)
40{
41 unsigned long flags;
42
43 raw_spin_lock_irqsave(&bnl->lock, flags);
44 list_del(&bn->list);
45 raw_spin_unlock_irqrestore(&bnl->lock, flags);
46}
47
48void budget_notifiers_fire(struct budget_notifier_list *bnl, bool replenished);
49
50#endif
diff --git a/include/litmus/reservations/polling.h b/include/litmus/reservations/polling.h
new file mode 100644
index 000000000000..230e12b1088a
--- /dev/null
+++ b/include/litmus/reservations/polling.h
@@ -0,0 +1,19 @@
1#ifndef LITMUS_POLLING_RESERVATIONS_H
2#define LITMUS_POLLING_RESERVATIONS_H
3
4#include <litmus/reservations/reservation.h>
5
6struct polling_reservation {
7 /* extend basic reservation */
8 struct reservation res;
9
10 lt_t max_budget;
11 lt_t period;
12 lt_t deadline;
13 lt_t offset;
14};
15
16void polling_reservation_init(struct polling_reservation *pres, int use_edf_prio,
17 int use_periodic_polling, lt_t budget, lt_t period, lt_t deadline, lt_t offset);
18
19#endif
diff --git a/include/litmus/reservations/reservation.h b/include/litmus/reservations/reservation.h
new file mode 100644
index 000000000000..ef639007969b
--- /dev/null
+++ b/include/litmus/reservations/reservation.h
@@ -0,0 +1,223 @@
1#ifndef LITMUS_RESERVATION_H
2#define LITMUS_RESERVATION_H
3
4#include <linux/list.h>
5#include <linux/hrtimer.h>
6
7#include <litmus/reservations/budget-notifier.h>
8
9struct reservation_client;
10struct reservation_environment;
11struct reservation;
12
13typedef enum {
14 /* reservation has no clients, is not consuming budget */
15 RESERVATION_INACTIVE = 0,
16
17 /* reservation has clients, consumes budget when scheduled */
18 RESERVATION_ACTIVE,
19
20 /* reservation has no clients, but may be consuming budget */
21 RESERVATION_ACTIVE_IDLE,
22
23 /* Reservation has no budget and waits for
24 * replenishment. May or may not have clients. */
25 RESERVATION_DEPLETED,
26} reservation_state_t;
27
28
29/* ************************************************************************** */
30
31/* Select which task to dispatch. If NULL is returned, it means there is nothing
32 * to schedule right now and background work can be scheduled. */
33typedef struct task_struct * (*dispatch_t) (
34 struct reservation_client *client
35);
36
37/* Something that can be managed in a reservation and that can yield
38 * a process for dispatching. Contains a pointer to the reservation
39 * to which it "belongs". */
40struct reservation_client {
41 struct list_head list;
42 struct reservation* reservation;
43 dispatch_t dispatch;
44};
45
46
47/* ************************************************************************** */
48
49/* Called by reservations to request state change. */
50typedef void (*reservation_change_state_t) (
51 struct reservation_environment* env,
52 struct reservation *res,
53 reservation_state_t new_state
54);
55
56/* Called by reservations to request replenishment while not DEPLETED.
57 * Useful for soft reservations that remain ACTIVE with lower priority. */
58typedef void (*request_replenishment_t)(
59 struct reservation_environment* env,
60 struct reservation *res
61);
62
63/* The framework within wich reservations operate. */
64struct reservation_environment {
65 lt_t time_zero;
66 lt_t current_time;
67
68 /* services invoked by reservations */
69 reservation_change_state_t change_state;
70 request_replenishment_t request_replenishment;
71};
72
73/* ************************************************************************** */
74
75/* A new client is added or an existing client resumes. */
76typedef void (*client_arrives_t) (
77 struct reservation *reservation,
78 struct reservation_client *client
79);
80
81/* A client suspends or terminates. */
82typedef void (*client_departs_t) (
83 struct reservation *reservation,
84 struct reservation_client *client,
85 int did_signal_job_completion
86);
87
88/* A previously requested replenishment has occurred. */
89typedef void (*on_replenishment_timer_t) (
90 struct reservation *reservation
91);
92
93/* Update the reservation's budget to reflect execution or idling. */
94typedef void (*drain_budget_t) (
95 struct reservation *reservation,
96 lt_t how_much
97);
98
99/* Select a ready task from one of the clients for scheduling. */
100typedef struct task_struct* (*dispatch_client_t) (
101 struct reservation *reservation,
102 lt_t *time_slice /* May be used to force rescheduling after
103 some amount of time. 0 => no limit */
104);
105
106/* Destructor: called before scheduler is deactivated. */
107typedef void (*shutdown_t)(struct reservation *reservation);
108
109struct reservation_ops {
110 dispatch_client_t dispatch_client;
111
112 client_arrives_t client_arrives;
113 client_departs_t client_departs;
114
115 on_replenishment_timer_t replenish;
116 drain_budget_t drain_budget;
117
118 shutdown_t shutdown;
119};
120
121#define RESERVATION_BACKGROUND_PRIORITY ULLONG_MAX
122
123struct reservation {
124 /* used to queue in environment */
125 struct list_head list;
126 struct list_head replenish_list;
127
128 reservation_state_t state;
129 unsigned int id;
130 unsigned int kind;
131
132 /* exact meaning defined by impl. */
133 lt_t priority;
134 lt_t cur_budget;
135 lt_t next_replenishment;
136
137 /* budget stats */
138 lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */
139 lt_t budget_consumed_total;
140
141 /* list of registered budget callbacks */
142 struct budget_notifier_list budget_notifiers;
143
144 /* for memory reclamation purposes */
145 struct list_head all_list;
146
147 /* interaction with framework */
148 struct reservation_environment *env;
149 struct reservation_ops *ops;
150
151 struct list_head clients;
152};
153
154void reservation_init(struct reservation *res);
155
156/* Default implementations */
157
158/* simply select the first client in the list, set *for_at_most to zero */
159struct task_struct* default_dispatch_client(
160 struct reservation *res,
161 lt_t *for_at_most
162);
163
164/* drain budget at linear rate, enter DEPLETED state when budget used up */
165void common_drain_budget(struct reservation *res, lt_t how_much);
166
167/* "connector" reservation client to hook up tasks with reservations */
168struct task_client {
169 struct reservation_client client;
170 struct task_struct *task;
171};
172
173void task_client_init(struct task_client *tc, struct task_struct *task,
174 struct reservation *reservation);
175
176#define SUP_RESCHEDULE_NOW (0)
177#define SUP_NO_SCHEDULER_UPDATE (ULLONG_MAX)
178
179/* A simple uniprocessor (SUP) flat (i.e., non-hierarchical) reservation
180 * environment.
181 */
182struct sup_reservation_environment {
183 struct reservation_environment env;
184
185 /* ordered by priority */
186 struct list_head active_reservations;
187
188 /* ordered by next_replenishment */
189 struct list_head depleted_reservations;
190
191 /* unordered */
192 struct list_head inactive_reservations;
193
194 /* list of all reservations */
195 struct list_head all_reservations;
196
197 /* - SUP_RESCHEDULE_NOW means call sup_dispatch() now
198 * - SUP_NO_SCHEDULER_UPDATE means nothing to do
199 * any other value means program a timer for the given time
200 */
201 lt_t next_scheduler_update;
202 /* set to true if a call to sup_dispatch() is imminent */
203 bool will_schedule;
204};
205
206/* Contract:
207 * - before calling into sup_ code, or any reservation methods,
208 * update the time with sup_update_time(); and
209 * - after calling into sup_ code, or any reservation methods,
210 * check next_scheduler_update and program timer or trigger
211 * scheduler invocation accordingly.
212 */
213
214void sup_init(struct sup_reservation_environment* sup_env);
215void sup_add_new_reservation(struct sup_reservation_environment* sup_env,
216 struct reservation* new_res);
217void sup_update_time(struct sup_reservation_environment* sup_env, lt_t now);
218struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env);
219
220struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env,
221 unsigned int id);
222
223#endif
diff --git a/include/litmus/reservations/table-driven.h b/include/litmus/reservations/table-driven.h
new file mode 100644
index 000000000000..b6302a2f200d
--- /dev/null
+++ b/include/litmus/reservations/table-driven.h
@@ -0,0 +1,23 @@
1#ifndef LITMUS_RESERVATIONS_TABLE_DRIVEN_H
2#define LITMUS_RESERVATIONS_TABLE_DRIVEN_H
3
4#include <litmus/reservations/reservation.h>
5
6struct table_driven_reservation {
7 /* extend basic reservation */
8 struct reservation res;
9
10 lt_t major_cycle;
11 unsigned int next_interval;
12 unsigned int num_intervals;
13 struct lt_interval *intervals;
14
15 /* info about current scheduling slot */
16 struct lt_interval cur_interval;
17 lt_t major_cycle_start;
18};
19
20void table_driven_reservation_init(struct table_driven_reservation *tdres,
21 lt_t major_cycle, struct lt_interval *intervals, unsigned int num_intervals);
22
23#endif