diff options
author | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-03-23 08:20:51 -0400 |
---|---|---|
committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-03-23 08:20:51 -0400 |
commit | ff210e0441b743890ad85c7335e41894b34a1431 (patch) | |
tree | 21027c2433f5ca9a26731b3af72fa6eb620df369 /litmus/polling_reservations.c | |
parent | 2e23e3f0cc7c3249b510e94b5b3ec92577b67e81 (diff) |
MC2 scheduler and partition modules
Diffstat (limited to 'litmus/polling_reservations.c')
-rw-r--r-- | litmus/polling_reservations.c | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c new file mode 100644 index 000000000000..4a2fee575127 --- /dev/null +++ b/litmus/polling_reservations.c | |||
@@ -0,0 +1,564 @@ | |||
1 | #include <linux/sched.h> | ||
2 | |||
3 | #include <litmus/litmus.h> | ||
4 | #include <litmus/reservation.h> | ||
5 | #include <litmus/polling_reservations.h> | ||
6 | |||
7 | |||
8 | static void periodic_polling_client_arrives( | ||
9 | struct reservation* res, | ||
10 | struct reservation_client *client | ||
11 | ) | ||
12 | { | ||
13 | struct polling_reservation *pres = | ||
14 | container_of(res, struct polling_reservation, res); | ||
15 | lt_t instances, tmp; | ||
16 | |||
17 | list_add_tail(&client->list, &res->clients); | ||
18 | |||
19 | switch (res->state) { | ||
20 | case RESERVATION_INACTIVE: | ||
21 | /* Figure out next replenishment time. */ | ||
22 | if (res->env->time_zero == 0) { | ||
23 | tmp = res->env->current_time - res->env->time_zero; | ||
24 | instances = div64_u64(tmp, pres->period); | ||
25 | res->next_replenishment = | ||
26 | (instances + 1) * pres->period + pres->offset; | ||
27 | } | ||
28 | else { | ||
29 | tmp = res->env->current_time - res->env->time_zero; | ||
30 | instances = div64_u64(tmp, pres->period); | ||
31 | res->next_replenishment = res->env->time_zero + instances * pres->period; | ||
32 | } | ||
33 | |||
34 | TRACE("ENV_TIME_ZERO %llu\n", res->env->time_zero); | ||
35 | TRACE("pol-res: R%d activate tmp=%llu instances=%llu period=%llu nextrp=%llu cur=%llu\n", | ||
36 | res->id, tmp, instances, pres->period, res->next_replenishment, | ||
37 | res->env->current_time); | ||
38 | |||
39 | res->env->change_state(res->env, res, | ||
40 | RESERVATION_DEPLETED); | ||
41 | break; | ||
42 | |||
43 | case RESERVATION_ACTIVE: | ||
44 | case RESERVATION_DEPLETED: | ||
45 | /* do nothing */ | ||
46 | break; | ||
47 | |||
48 | case RESERVATION_ACTIVE_IDLE: | ||
49 | res->blocked_by_ghost = 0; | ||
50 | res->env->change_state(res->env, res, | ||
51 | RESERVATION_ACTIVE); | ||
52 | break; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | |||
57 | static void periodic_polling_client_departs( | ||
58 | struct reservation *res, | ||
59 | struct reservation_client *client, | ||
60 | int did_signal_job_completion | ||
61 | ) | ||
62 | { | ||
63 | list_del(&client->list); | ||
64 | |||
65 | switch (res->state) { | ||
66 | case RESERVATION_INACTIVE: | ||
67 | case RESERVATION_ACTIVE_IDLE: | ||
68 | BUG(); /* INACTIVE or IDLE <=> no client */ | ||
69 | break; | ||
70 | |||
71 | case RESERVATION_ACTIVE: | ||
72 | if (list_empty(&res->clients)) { | ||
73 | res->env->change_state(res->env, res, | ||
74 | // RESERVATION_ACTIVE_IDLE); | ||
75 | res->cur_budget ? | ||
76 | RESERVATION_ACTIVE_IDLE : | ||
77 | RESERVATION_DEPLETED); | ||
78 | // did_signal_job_completion ? | ||
79 | // RESERVATION_DEPLETED : | ||
80 | // RESERVATION_ACTIVE_IDLE); | ||
81 | } /* else: nothing to do, more clients ready */ | ||
82 | break; | ||
83 | |||
84 | case RESERVATION_DEPLETED: | ||
85 | /* do nothing */ | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void periodic_polling_on_replenishment( | ||
91 | struct reservation *res | ||
92 | ) | ||
93 | { | ||
94 | struct polling_reservation *pres = | ||
95 | container_of(res, struct polling_reservation, res); | ||
96 | |||
97 | /* replenish budget */ | ||
98 | res->cur_budget = pres->max_budget; | ||
99 | res->next_replenishment += pres->period; | ||
100 | res->budget_consumed = 0; | ||
101 | |||
102 | TRACE("polling_replenish(%u): next_replenishment=%llu\n", res->id, res->next_replenishment); | ||
103 | switch (res->state) { | ||
104 | case RESERVATION_DEPLETED: | ||
105 | case RESERVATION_INACTIVE: | ||
106 | case RESERVATION_ACTIVE_IDLE: | ||
107 | if (list_empty(&res->clients)) | ||
108 | /* no clients => poll again later */ | ||
109 | res->env->change_state(res->env, res, | ||
110 | RESERVATION_INACTIVE); | ||
111 | else | ||
112 | /* we have clients & budget => ACTIVE */ | ||
113 | res->env->change_state(res->env, res, | ||
114 | RESERVATION_ACTIVE); | ||
115 | break; | ||
116 | |||
117 | case RESERVATION_ACTIVE: | ||
118 | /* Replenished while active => tardy? In any case, | ||
119 | * go ahead and stay active. */ | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void periodic_polling_on_replenishment_edf( | ||
125 | struct reservation *res | ||
126 | ) | ||
127 | { | ||
128 | struct polling_reservation *pres = | ||
129 | container_of(res, struct polling_reservation, res); | ||
130 | |||
131 | /* update current priority */ | ||
132 | res->priority = res->next_replenishment + pres->deadline; | ||
133 | |||
134 | /* do common updates */ | ||
135 | periodic_polling_on_replenishment(res); | ||
136 | } | ||
137 | |||
138 | static void common_drain_budget( | ||
139 | struct reservation *res, | ||
140 | lt_t how_much) | ||
141 | { | ||
142 | if (how_much >= res->cur_budget) | ||
143 | res->cur_budget = 0; | ||
144 | else | ||
145 | res->cur_budget -= how_much; | ||
146 | |||
147 | res->budget_consumed += how_much; | ||
148 | res->budget_consumed_total += how_much; | ||
149 | |||
150 | switch (res->state) { | ||
151 | case RESERVATION_DEPLETED: | ||
152 | case RESERVATION_INACTIVE: | ||
153 | //BUG(); | ||
154 | TRACE("!!!!!!!!!!!!!!!STATE ERROR R%d STATE(%d)\n", res->id, res->state); | ||
155 | break; | ||
156 | |||
157 | case RESERVATION_ACTIVE_IDLE: | ||
158 | case RESERVATION_ACTIVE: | ||
159 | if (!res->cur_budget) { | ||
160 | res->env->change_state(res->env, res, | ||
161 | RESERVATION_DEPLETED); | ||
162 | } /* else: stay in current state */ | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static struct reservation_ops periodic_polling_ops_fp = { | ||
168 | .dispatch_client = default_dispatch_client, | ||
169 | .client_arrives = periodic_polling_client_arrives, | ||
170 | .client_departs = periodic_polling_client_departs, | ||
171 | .replenish = periodic_polling_on_replenishment, | ||
172 | .drain_budget = common_drain_budget, | ||
173 | }; | ||
174 | |||
175 | static struct reservation_ops periodic_polling_ops_edf = { | ||
176 | .dispatch_client = default_dispatch_client, | ||
177 | .client_arrives = periodic_polling_client_arrives, | ||
178 | .client_departs = periodic_polling_client_departs, | ||
179 | .replenish = periodic_polling_on_replenishment_edf, | ||
180 | .drain_budget = common_drain_budget, | ||
181 | }; | ||
182 | |||
183 | |||
184 | |||
185 | |||
186 | static void sporadic_polling_client_arrives_fp( | ||
187 | struct reservation* res, | ||
188 | struct reservation_client *client | ||
189 | ) | ||
190 | { | ||
191 | struct polling_reservation *pres = | ||
192 | container_of(res, struct polling_reservation, res); | ||
193 | |||
194 | list_add_tail(&client->list, &res->clients); | ||
195 | |||
196 | switch (res->state) { | ||
197 | case RESERVATION_INACTIVE: | ||
198 | /* Replenish now. */ | ||
199 | res->cur_budget = pres->max_budget; | ||
200 | res->next_replenishment = | ||
201 | res->env->current_time + pres->period; | ||
202 | |||
203 | res->env->change_state(res->env, res, | ||
204 | RESERVATION_ACTIVE); | ||
205 | break; | ||
206 | |||
207 | case RESERVATION_ACTIVE: | ||
208 | case RESERVATION_DEPLETED: | ||
209 | /* do nothing */ | ||
210 | break; | ||
211 | |||
212 | case RESERVATION_ACTIVE_IDLE: | ||
213 | res->env->change_state(res->env, res, | ||
214 | RESERVATION_ACTIVE); | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void sporadic_polling_client_arrives_edf( | ||
220 | struct reservation* res, | ||
221 | struct reservation_client *client | ||
222 | ) | ||
223 | { | ||
224 | struct polling_reservation *pres = | ||
225 | container_of(res, struct polling_reservation, res); | ||
226 | |||
227 | list_add_tail(&client->list, &res->clients); | ||
228 | |||
229 | switch (res->state) { | ||
230 | case RESERVATION_INACTIVE: | ||
231 | /* Replenish now. */ | ||
232 | res->cur_budget = pres->max_budget; | ||
233 | res->next_replenishment = | ||
234 | res->env->current_time + pres->period; | ||
235 | res->priority = | ||
236 | res->env->current_time + pres->deadline; | ||
237 | |||
238 | res->env->change_state(res->env, res, | ||
239 | RESERVATION_ACTIVE); | ||
240 | break; | ||
241 | |||
242 | case RESERVATION_ACTIVE: | ||
243 | case RESERVATION_DEPLETED: | ||
244 | /* do nothing */ | ||
245 | break; | ||
246 | |||
247 | case RESERVATION_ACTIVE_IDLE: | ||
248 | res->env->change_state(res->env, res, | ||
249 | RESERVATION_ACTIVE); | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static struct reservation_ops sporadic_polling_ops_fp = { | ||
255 | .dispatch_client = default_dispatch_client, | ||
256 | .client_arrives = sporadic_polling_client_arrives_fp, | ||
257 | .client_departs = periodic_polling_client_departs, | ||
258 | .replenish = periodic_polling_on_replenishment, | ||
259 | .drain_budget = common_drain_budget, | ||
260 | }; | ||
261 | |||
262 | static struct reservation_ops sporadic_polling_ops_edf = { | ||
263 | .dispatch_client = default_dispatch_client, | ||
264 | .client_arrives = sporadic_polling_client_arrives_edf, | ||
265 | .client_departs = periodic_polling_client_departs, | ||
266 | .replenish = periodic_polling_on_replenishment_edf, | ||
267 | .drain_budget = common_drain_budget, | ||
268 | }; | ||
269 | |||
270 | void polling_reservation_init( | ||
271 | struct polling_reservation *pres, | ||
272 | int use_edf_prio, | ||
273 | int use_periodic_polling, | ||
274 | lt_t budget, lt_t period, lt_t deadline, lt_t offset | ||
275 | ) | ||
276 | { | ||
277 | if (!deadline) | ||
278 | deadline = period; | ||
279 | BUG_ON(budget > period); | ||
280 | BUG_ON(budget > deadline); | ||
281 | BUG_ON(offset >= period); | ||
282 | |||
283 | reservation_init(&pres->res); | ||
284 | pres->max_budget = budget; | ||
285 | pres->period = period; | ||
286 | pres->deadline = deadline; | ||
287 | pres->offset = offset; | ||
288 | TRACE_TASK(current, "polling_reservation_init: periodic %d, use_edf %d\n", use_periodic_polling, use_edf_prio); | ||
289 | if (use_periodic_polling) { | ||
290 | if (use_edf_prio) | ||
291 | pres->res.ops = &periodic_polling_ops_edf; | ||
292 | else | ||
293 | pres->res.ops = &periodic_polling_ops_fp; | ||
294 | } else { | ||
295 | if (use_edf_prio) | ||
296 | pres->res.ops = &sporadic_polling_ops_edf; | ||
297 | else | ||
298 | pres->res.ops = &sporadic_polling_ops_fp; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | static lt_t td_cur_major_cycle_start(struct table_driven_reservation *tdres) | ||
304 | { | ||
305 | lt_t x, tmp; | ||
306 | |||
307 | tmp = tdres->res.env->current_time - tdres->res.env->time_zero; | ||
308 | x = div64_u64(tmp, tdres->major_cycle); | ||
309 | x *= tdres->major_cycle; | ||
310 | return x; | ||
311 | } | ||
312 | |||
313 | |||
314 | static lt_t td_next_major_cycle_start(struct table_driven_reservation *tdres) | ||
315 | { | ||
316 | lt_t x, tmp; | ||
317 | |||
318 | tmp = tdres->res.env->current_time - tdres->res.env->time_zero; | ||
319 | x = div64_u64(tmp, tdres->major_cycle) + 1; | ||
320 | x *= tdres->major_cycle; | ||
321 | return x; | ||
322 | } | ||
323 | |||
324 | static void td_client_arrives( | ||
325 | struct reservation* res, | ||
326 | struct reservation_client *client | ||
327 | ) | ||
328 | { | ||
329 | struct table_driven_reservation *tdres = | ||
330 | container_of(res, struct table_driven_reservation, res); | ||
331 | |||
332 | list_add_tail(&client->list, &res->clients); | ||
333 | |||
334 | switch (res->state) { | ||
335 | case RESERVATION_INACTIVE: | ||
336 | /* Figure out first replenishment time. */ | ||
337 | tdres->major_cycle_start = td_next_major_cycle_start(tdres); | ||
338 | res->next_replenishment = tdres->major_cycle_start; | ||
339 | res->next_replenishment += tdres->intervals[0].start; | ||
340 | tdres->next_interval = 0; | ||
341 | |||
342 | res->env->change_state(res->env, res, | ||
343 | RESERVATION_DEPLETED); | ||
344 | break; | ||
345 | |||
346 | case RESERVATION_ACTIVE: | ||
347 | case RESERVATION_DEPLETED: | ||
348 | /* do nothing */ | ||
349 | break; | ||
350 | |||
351 | case RESERVATION_ACTIVE_IDLE: | ||
352 | res->env->change_state(res->env, res, | ||
353 | RESERVATION_ACTIVE); | ||
354 | break; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | static void td_client_departs( | ||
359 | struct reservation *res, | ||
360 | struct reservation_client *client, | ||
361 | int did_signal_job_completion | ||
362 | ) | ||
363 | { | ||
364 | list_del(&client->list); | ||
365 | |||
366 | switch (res->state) { | ||
367 | case RESERVATION_INACTIVE: | ||
368 | case RESERVATION_ACTIVE_IDLE: | ||
369 | //BUG(); /* INACTIVE or IDLE <=> no client */ | ||
370 | break; | ||
371 | |||
372 | case RESERVATION_ACTIVE: | ||
373 | if (list_empty(&res->clients)) { | ||
374 | res->env->change_state(res->env, res, | ||
375 | RESERVATION_ACTIVE_IDLE); | ||
376 | } /* else: nothing to do, more clients ready */ | ||
377 | break; | ||
378 | |||
379 | case RESERVATION_DEPLETED: | ||
380 | /* do nothing */ | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres) | ||
386 | { | ||
387 | lt_t now = tdres->res.env->current_time; | ||
388 | lt_t end = tdres->cur_interval.end; | ||
389 | //TRACE("td_remaining(%u): start=%llu now=%llu end=%llu state=%d\n", tdres->res.id, tdres->cur_interval.start, now, end, tdres->res.state); | ||
390 | if (now >= end) | ||
391 | return 0; | ||
392 | else | ||
393 | return end - now; | ||
394 | } | ||
395 | |||
396 | static void td_replenish( | ||
397 | struct reservation *res) | ||
398 | { | ||
399 | struct table_driven_reservation *tdres = | ||
400 | container_of(res, struct table_driven_reservation, res); | ||
401 | |||
402 | //TRACE("td_replenish(%u): expected_replenishment=%llu\n", res->id, res->next_replenishment); | ||
403 | |||
404 | /* figure out current interval */ | ||
405 | tdres->cur_interval.start = tdres->major_cycle_start + | ||
406 | tdres->intervals[tdres->next_interval].start; | ||
407 | tdres->cur_interval.end = tdres->major_cycle_start + | ||
408 | tdres->intervals[tdres->next_interval].end; | ||
409 | /* TRACE("major_cycle_start=%llu => [%llu, %llu]\n", | ||
410 | tdres->major_cycle_start, | ||
411 | tdres->cur_interval.start, | ||
412 | tdres->cur_interval.end); | ||
413 | */ | ||
414 | /* reset budget */ | ||
415 | res->cur_budget = td_time_remaining_until_end(tdres); | ||
416 | res->budget_consumed = 0; | ||
417 | //TRACE("td_replenish(%u): %s budget=%llu\n", res->id, res->cur_budget ? "" : "WARNING", res->cur_budget); | ||
418 | |||
419 | /* prepare next slot */ | ||
420 | tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals; | ||
421 | if (!tdres->next_interval) | ||
422 | /* wrap to next major cycle */ | ||
423 | tdres->major_cycle_start += tdres->major_cycle; | ||
424 | |||
425 | /* determine next time this reservation becomes eligible to execute */ | ||
426 | res->next_replenishment = tdres->major_cycle_start; | ||
427 | res->next_replenishment += tdres->intervals[tdres->next_interval].start; | ||
428 | //TRACE("td_replenish(%u): next_replenishment=%llu\n", res->id, res->next_replenishment); | ||
429 | |||
430 | |||
431 | switch (res->state) { | ||
432 | case RESERVATION_DEPLETED: | ||
433 | case RESERVATION_ACTIVE: | ||
434 | case RESERVATION_ACTIVE_IDLE: | ||
435 | if (list_empty(&res->clients)) | ||
436 | res->env->change_state(res->env, res, | ||
437 | RESERVATION_ACTIVE_IDLE); | ||
438 | else | ||
439 | /* we have clients & budget => ACTIVE */ | ||
440 | res->env->change_state(res->env, res, | ||
441 | RESERVATION_ACTIVE); | ||
442 | break; | ||
443 | |||
444 | case RESERVATION_INACTIVE: | ||
445 | BUG(); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | static void td_drain_budget( | ||
451 | struct reservation *res, | ||
452 | lt_t how_much) | ||
453 | { | ||
454 | struct table_driven_reservation *tdres = | ||
455 | container_of(res, struct table_driven_reservation, res); | ||
456 | |||
457 | res->budget_consumed += how_much; | ||
458 | res->budget_consumed_total += how_much; | ||
459 | |||
460 | /* Table-driven scheduling: instead of tracking the budget, we compute | ||
461 | * how much time is left in this allocation interval. */ | ||
462 | |||
463 | /* sanity check: we should never try to drain from future slots */ | ||
464 | //TRACE("TD_DRAIN STATE(%d) [%llu,%llu] %llu ?\n", res->state, tdres->cur_interval.start, tdres->cur_interval.end, res->env->current_time); | ||
465 | //BUG_ON(tdres->cur_interval.start > res->env->current_time); | ||
466 | if (tdres->cur_interval.start > res->env->current_time) | ||
467 | TRACE("TD_DRAIN BUG!!!!!!!!!!\n"); | ||
468 | |||
469 | switch (res->state) { | ||
470 | case RESERVATION_DEPLETED: | ||
471 | case RESERVATION_INACTIVE: | ||
472 | //BUG(); | ||
473 | TRACE("TD_DRAIN!!!!!!!!! RES_STATE = %d\n", res->state); | ||
474 | break; | ||
475 | |||
476 | case RESERVATION_ACTIVE_IDLE: | ||
477 | case RESERVATION_ACTIVE: | ||
478 | res->cur_budget = td_time_remaining_until_end(tdres); | ||
479 | //TRACE("td_drain_budget(%u): drained to budget=%llu\n", res->id, res->cur_budget); | ||
480 | if (!res->cur_budget) { | ||
481 | res->env->change_state(res->env, res, | ||
482 | RESERVATION_DEPLETED); | ||
483 | } else { | ||
484 | /* sanity check budget calculation */ | ||
485 | //BUG_ON(res->env->current_time >= tdres->cur_interval.end); | ||
486 | //BUG_ON(res->env->current_time < tdres->cur_interval.start); | ||
487 | if (res->env->current_time >= tdres->cur_interval.end) | ||
488 | printk(KERN_ALERT "TD_DRAIN_BUDGET WARNING1\n"); | ||
489 | if (res->env->current_time < tdres->cur_interval.start) | ||
490 | printk(KERN_ALERT "TD_DRAIN_BUDGET WARNING2\n"); | ||
491 | } | ||
492 | |||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | static struct task_struct* td_dispatch_client( | ||
498 | struct reservation *res, | ||
499 | lt_t *for_at_most) | ||
500 | { | ||
501 | struct task_struct *t; | ||
502 | struct table_driven_reservation *tdres = | ||
503 | container_of(res, struct table_driven_reservation, res); | ||
504 | |||
505 | /* usual logic for selecting a client */ | ||
506 | t = default_dispatch_client(res, for_at_most); | ||
507 | |||
508 | TRACE_TASK(t, "td_dispatch_client(%u): selected, budget=%llu\n", | ||
509 | res->id, res->cur_budget); | ||
510 | |||
511 | /* check how much budget we have left in this time slot */ | ||
512 | res->cur_budget = td_time_remaining_until_end(tdres); | ||
513 | |||
514 | TRACE_TASK(t, "td_dispatch_client(%u): updated to budget=%llu next=%d\n", | ||
515 | res->id, res->cur_budget, tdres->next_interval); | ||
516 | |||
517 | if (unlikely(!res->cur_budget)) { | ||
518 | /* Unlikely case: if we ran out of budget, the user configured | ||
519 | * a broken scheduling table (overlapping table slots). | ||
520 | * Not much we can do about this, but we can't dispatch a job | ||
521 | * now without causing overload. So let's register this reservation | ||
522 | * as depleted and wait for the next allocation. */ | ||
523 | TRACE("td_dispatch_client(%u): budget unexpectedly depleted " | ||
524 | "(check scheduling table for unintended overlap)\n", | ||
525 | res->id); | ||
526 | res->env->change_state(res->env, res, | ||
527 | RESERVATION_DEPLETED); | ||
528 | return NULL; | ||
529 | } else | ||
530 | return t; | ||
531 | } | ||
532 | |||
533 | static struct reservation_ops td_ops = { | ||
534 | .dispatch_client = td_dispatch_client, | ||
535 | .client_arrives = td_client_arrives, | ||
536 | .client_departs = td_client_departs, | ||
537 | .replenish = td_replenish, | ||
538 | .drain_budget = td_drain_budget, | ||
539 | }; | ||
540 | |||
541 | void table_driven_reservation_init( | ||
542 | struct table_driven_reservation *tdres, | ||
543 | lt_t major_cycle, | ||
544 | struct lt_interval *intervals, | ||
545 | unsigned int num_intervals) | ||
546 | { | ||
547 | unsigned int i; | ||
548 | |||
549 | /* sanity checking */ | ||
550 | BUG_ON(!num_intervals); | ||
551 | for (i = 0; i < num_intervals; i++) | ||
552 | BUG_ON(intervals[i].end <= intervals[i].start); | ||
553 | for (i = 0; i + 1 < num_intervals; i++) | ||
554 | BUG_ON(intervals[i + 1].start <= intervals[i].end); | ||
555 | BUG_ON(intervals[num_intervals - 1].end > major_cycle); | ||
556 | |||
557 | reservation_init(&tdres->res); | ||
558 | tdres->major_cycle = major_cycle; | ||
559 | tdres->intervals = intervals; | ||
560 | tdres->cur_interval.start = 0; | ||
561 | tdres->cur_interval.end = 0; | ||
562 | tdres->num_intervals = num_intervals; | ||
563 | tdres->res.ops = &td_ops; | ||
564 | } | ||