diff options
Diffstat (limited to 'litmus/sched_mc_ce.c')
-rw-r--r-- | litmus/sched_mc_ce.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/litmus/sched_mc_ce.c b/litmus/sched_mc_ce.c index 63b0470e1f52..c5066918f282 100644 --- a/litmus/sched_mc_ce.c +++ b/litmus/sched_mc_ce.c | |||
@@ -52,6 +52,10 @@ struct ce_pid_entry { | |||
52 | unsigned int expected_job; | 52 | unsigned int expected_job; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* | ||
56 | * Each CPU needs a mapping of level A ID (integer) to struct pid so that we | ||
57 | * can get its task struct. | ||
58 | */ | ||
55 | struct ce_pid_table { | 59 | struct ce_pid_table { |
56 | struct ce_pid_entry entries[CONFIG_PLUGIN_MC_LEVEL_A_MAX_TASKS]; | 60 | struct ce_pid_entry entries[CONFIG_PLUGIN_MC_LEVEL_A_MAX_TASKS]; |
57 | int num_pid_entries; | 61 | int num_pid_entries; |
@@ -434,7 +438,10 @@ void mc_ce_task_exit_common(struct task_struct *ts) | |||
434 | * Timer stuff | 438 | * Timer stuff |
435 | **********************************************************/ | 439 | **********************************************************/ |
436 | 440 | ||
437 | void mc_ce_timer_callback_common(struct domain *dom, struct hrtimer *timer) | 441 | /* |
442 | * Returns the next absolute time that the timer should fire. | ||
443 | */ | ||
444 | lt_t mc_ce_timer_callback_common(struct domain *dom) | ||
438 | { | 445 | { |
439 | /* relative and absolute times for cycles */ | 446 | /* relative and absolute times for cycles */ |
440 | lt_t now, offset_rel, cycle_start_abs, next_timer_abs; | 447 | lt_t now, offset_rel, cycle_start_abs, next_timer_abs; |
@@ -455,9 +462,7 @@ void mc_ce_timer_callback_common(struct domain *dom, struct hrtimer *timer) | |||
455 | cycle_start_abs = now - offset_rel; | 462 | cycle_start_abs = now - offset_rel; |
456 | idx = mc_ce_schedule_at(dom, offset_rel); | 463 | idx = mc_ce_schedule_at(dom, offset_rel); |
457 | pid_entry = get_pid_entry(ce_data->cpu, idx); | 464 | pid_entry = get_pid_entry(ce_data->cpu, idx); |
458 | /* set the timer to fire at the next cycle start */ | ||
459 | next_timer_abs = cycle_start_abs + pid_entry->acc_time; | 465 | next_timer_abs = cycle_start_abs + pid_entry->acc_time; |
460 | hrtimer_set_expires(timer, ns_to_ktime(next_timer_abs)); | ||
461 | 466 | ||
462 | STRACE("timer: now: %llu offset_rel: %llu cycle_start_abs: %llu " | 467 | STRACE("timer: now: %llu offset_rel: %llu cycle_start_abs: %llu " |
463 | "next_timer_abs: %llu\n", now, offset_rel, | 468 | "next_timer_abs: %llu\n", now, offset_rel, |
@@ -495,32 +500,52 @@ void mc_ce_timer_callback_common(struct domain *dom, struct hrtimer *timer) | |||
495 | sched_trace_task_release(should_schedule); | 500 | sched_trace_task_release(should_schedule); |
496 | set_rt_flags(ce_data->should_schedule, RT_F_RUNNING); | 501 | set_rt_flags(ce_data->should_schedule, RT_F_RUNNING); |
497 | } | 502 | } |
503 | return next_timer_abs; | ||
498 | } | 504 | } |
499 | 505 | ||
500 | /* | 506 | /* |
501 | * What to do when a timer fires. The timer should only be armed if the number | 507 | * What to do when a timer fires. The timer should only be armed if the number |
502 | * of PID entries is positive. | 508 | * of PID entries is positive. |
503 | */ | 509 | */ |
510 | #ifdef CONFIG_MERGE_TIMERS | ||
511 | static void mc_ce_timer_callback(struct rt_event *e) | ||
512 | #else | ||
504 | static enum hrtimer_restart mc_ce_timer_callback(struct hrtimer *timer) | 513 | static enum hrtimer_restart mc_ce_timer_callback(struct hrtimer *timer) |
514 | #endif | ||
505 | { | 515 | { |
506 | struct ce_dom_data *ce_data; | 516 | struct ce_dom_data *ce_data; |
507 | unsigned long flags; | 517 | unsigned long flags; |
508 | struct domain *dom; | 518 | struct domain *dom; |
509 | 519 | lt_t next_timer_abs; | |
520 | #ifdef CONFIG_MERGE_TIMERS | ||
521 | struct event_group *event_group; | ||
522 | ce_data = container_of(e, struct ce_dom_data, event); | ||
523 | event_group = get_event_group_for(ce_data->cpu); | ||
524 | #else | ||
510 | ce_data = container_of(timer, struct ce_dom_data, timer); | 525 | ce_data = container_of(timer, struct ce_dom_data, timer); |
526 | #endif | ||
511 | dom = get_domain_for(ce_data->cpu); | 527 | dom = get_domain_for(ce_data->cpu); |
512 | 528 | ||
513 | TRACE("timer callback on CPU %d (before lock)\n", ce_data->cpu); | 529 | TRACE("timer callback on CPU %d (before lock)\n", ce_data->cpu); |
514 | 530 | ||
515 | raw_spin_lock_irqsave(dom->lock, flags); | 531 | raw_spin_lock_irqsave(dom->lock, flags); |
516 | mc_ce_timer_callback_common(dom, timer); | 532 | next_timer_abs = mc_ce_timer_callback_common(dom); |
533 | |||
534 | /* setup an event or timer for the next release in the CE schedule */ | ||
535 | #ifdef CONFIG_MERGE_TIMERS | ||
536 | add_event(event_group, e, next_timer_abs); | ||
537 | #else | ||
538 | hrtimer_set_expires(timer, ns_to_ktime(next_timer_abs)); | ||
539 | #endif | ||
517 | 540 | ||
518 | if (ce_data->scheduled != ce_data->should_schedule) | 541 | if (ce_data->scheduled != ce_data->should_schedule) |
519 | preempt_if_preemptable(ce_data->scheduled, ce_data->cpu); | 542 | preempt_if_preemptable(ce_data->scheduled, ce_data->cpu); |
520 | 543 | ||
521 | raw_spin_unlock_irqrestore(dom->lock, flags); | 544 | raw_spin_unlock_irqrestore(dom->lock, flags); |
522 | 545 | ||
546 | #ifndef CONFIG_MERGE_TIMERS | ||
523 | return HRTIMER_RESTART; | 547 | return HRTIMER_RESTART; |
548 | #endif | ||
524 | } | 549 | } |
525 | 550 | ||
526 | /* | 551 | /* |
@@ -530,7 +555,10 @@ static int cancel_all_timers(void) | |||
530 | { | 555 | { |
531 | struct ce_dom_data *ce_data; | 556 | struct ce_dom_data *ce_data; |
532 | struct domain *dom; | 557 | struct domain *dom; |
533 | int cpu, cancel_res, ret = 0; | 558 | int cpu, ret = 0; |
559 | #ifndef CONFIG_MERGE_TIMERS | ||
560 | int cancel_res; | ||
561 | #endif | ||
534 | 562 | ||
535 | TRACE("cancel all timers\n"); | 563 | TRACE("cancel all timers\n"); |
536 | 564 | ||
@@ -538,10 +566,14 @@ static int cancel_all_timers(void) | |||
538 | dom = get_domain_for(cpu); | 566 | dom = get_domain_for(cpu); |
539 | ce_data = dom->data; | 567 | ce_data = dom->data; |
540 | ce_data->should_schedule = NULL; | 568 | ce_data->should_schedule = NULL; |
569 | #ifdef CONFIG_MERGE_TIMERS | ||
570 | cancel_event(&ce_data->event); | ||
571 | #else | ||
541 | cancel_res = hrtimer_cancel(&ce_data->timer); | 572 | cancel_res = hrtimer_cancel(&ce_data->timer); |
542 | atomic_set(&ce_data->timer_info.state, | 573 | atomic_set(&ce_data->timer_info.state, |
543 | HRTIMER_START_ON_INACTIVE); | 574 | HRTIMER_START_ON_INACTIVE); |
544 | ret = ret || cancel_res; | 575 | ret = ret || cancel_res; |
576 | #endif | ||
545 | } | 577 | } |
546 | return ret; | 578 | return ret; |
547 | } | 579 | } |
@@ -570,9 +602,14 @@ static void arm_all_timers(void) | |||
570 | for (idx = 0; idx < pid_table->num_pid_entries; idx++) { | 602 | for (idx = 0; idx < pid_table->num_pid_entries; idx++) { |
571 | pid_table->entries[idx].expected_job = 0; | 603 | pid_table->entries[idx].expected_job = 0; |
572 | } | 604 | } |
605 | #ifdef CONFIG_MERGE_TIMERS | ||
606 | TRACE("adding event for CPU %d\n", cpu); | ||
607 | add_event(get_event_group_for(cpu), &ce_data->event, start); | ||
608 | #else | ||
573 | TRACE("arming timer for CPU %d\n", cpu); | 609 | TRACE("arming timer for CPU %d\n", cpu); |
574 | hrtimer_start_on(cpu, &ce_data->timer_info, &ce_data->timer, | 610 | hrtimer_start_on(cpu, &ce_data->timer_info, &ce_data->timer, |
575 | ns_to_ktime(start), HRTIMER_MODE_ABS_PINNED); | 611 | ns_to_ktime(start), HRTIMER_MODE_ABS_PINNED); |
612 | #endif | ||
576 | } | 613 | } |
577 | } | 614 | } |
578 | 615 | ||