diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-03-16 07:59:07 -0400 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-03-20 14:30:35 -0400 |
commit | 2a38056cc098c56a04bbe18f4e752f4fa782599f (patch) | |
tree | c38619d281c9b7ae23333573b322bab72d8801b3 /include/litmus | |
parent | 095f515b2fd903a0140afcc42db9a9f76d688b65 (diff) |
Add basic generic reservation-based scheduling infrastructure
Diffstat (limited to 'include/litmus')
-rw-r--r-- | include/litmus/reservations/alloc.h | 15 | ||||
-rw-r--r-- | include/litmus/reservations/budget-notifier.h | 50 | ||||
-rw-r--r-- | include/litmus/reservations/polling.h | 19 | ||||
-rw-r--r-- | include/litmus/reservations/reservation.h | 223 | ||||
-rw-r--r-- | include/litmus/reservations/table-driven.h | 23 |
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 | |||
6 | long alloc_polling_reservation( | ||
7 | int res_type, | ||
8 | struct reservation_config *config, | ||
9 | struct reservation **_res); | ||
10 | |||
11 | long 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 | |||
7 | struct budget_notifier; | ||
8 | |||
9 | typedef void (*budget_callback_t) ( | ||
10 | struct budget_notifier *bn | ||
11 | ); | ||
12 | |||
13 | struct budget_notifier { | ||
14 | struct list_head list; | ||
15 | budget_callback_t budget_exhausted; | ||
16 | budget_callback_t budget_replenished; | ||
17 | }; | ||
18 | |||
19 | struct budget_notifier_list { | ||
20 | struct list_head list; | ||
21 | raw_spinlock_t lock; | ||
22 | }; | ||
23 | |||
24 | void budget_notifier_list_init(struct budget_notifier_list* bnl); | ||
25 | |||
26 | static 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 | |||
37 | static 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 | |||
48 | void 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 | |||
6 | struct 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 | |||
16 | void 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 | |||
9 | struct reservation_client; | ||
10 | struct reservation_environment; | ||
11 | struct reservation; | ||
12 | |||
13 | typedef 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. */ | ||
33 | typedef 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". */ | ||
40 | struct 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. */ | ||
50 | typedef 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. */ | ||
58 | typedef void (*request_replenishment_t)( | ||
59 | struct reservation_environment* env, | ||
60 | struct reservation *res | ||
61 | ); | ||
62 | |||
63 | /* The framework within wich reservations operate. */ | ||
64 | struct 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. */ | ||
76 | typedef void (*client_arrives_t) ( | ||
77 | struct reservation *reservation, | ||
78 | struct reservation_client *client | ||
79 | ); | ||
80 | |||
81 | /* A client suspends or terminates. */ | ||
82 | typedef 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. */ | ||
89 | typedef void (*on_replenishment_timer_t) ( | ||
90 | struct reservation *reservation | ||
91 | ); | ||
92 | |||
93 | /* Update the reservation's budget to reflect execution or idling. */ | ||
94 | typedef 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. */ | ||
100 | typedef 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. */ | ||
107 | typedef void (*shutdown_t)(struct reservation *reservation); | ||
108 | |||
109 | struct 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 | |||
123 | struct 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 | |||
154 | void 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 */ | ||
159 | struct 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 */ | ||
165 | void common_drain_budget(struct reservation *res, lt_t how_much); | ||
166 | |||
167 | /* "connector" reservation client to hook up tasks with reservations */ | ||
168 | struct task_client { | ||
169 | struct reservation_client client; | ||
170 | struct task_struct *task; | ||
171 | }; | ||
172 | |||
173 | void 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 | */ | ||
182 | struct 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 | |||
214 | void sup_init(struct sup_reservation_environment* sup_env); | ||
215 | void sup_add_new_reservation(struct sup_reservation_environment* sup_env, | ||
216 | struct reservation* new_res); | ||
217 | void sup_update_time(struct sup_reservation_environment* sup_env, lt_t now); | ||
218 | struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env); | ||
219 | |||
220 | struct 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 | |||
6 | struct 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 | |||
20 | void 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 | ||