diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-04-15 04:02:44 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-04-15 04:02:44 -0400 |
commit | 4ff76e7063c0ebbd616e92079468ddfce133cb4d (patch) | |
tree | 13bd059c58fd7052d226844b8fe9be51461daef3 | |
parent | 0317947a4d7fa886d90ec500444446894726f680 (diff) |
Support for chains of blocking tasks.
-rw-r--r-- | include/litmus/rt_param.h | 1 | ||||
-rw-r--r-- | litmus/sched_edf_hsb.c | 280 |
2 files changed, 173 insertions, 108 deletions
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 26da5f578a6c..d40fdadba62c 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -201,6 +201,7 @@ struct rt_param { | |||
201 | #define RT_F_RUNNING 0x00000000 | 201 | #define RT_F_RUNNING 0x00000000 |
202 | #define RT_F_SLEEP 0x00000001 | 202 | #define RT_F_SLEEP 0x00000001 |
203 | #define RT_F_EXIT_SEM 0x00000008 | 203 | #define RT_F_EXIT_SEM 0x00000008 |
204 | #define RT_F_BLOCK 0x00000010 | ||
204 | 205 | ||
205 | #endif | 206 | #endif |
206 | 207 | ||
diff --git a/litmus/sched_edf_hsb.c b/litmus/sched_edf_hsb.c index 70e254981861..70549de38f62 100644 --- a/litmus/sched_edf_hsb.c +++ b/litmus/sched_edf_hsb.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * admit_[hrt|be]_server | 16 | * admit_[hrt|be]_server |
17 | * | 17 | * |
18 | * TODO system for removing tasks from their release queues | 18 | * TODO system for removing tasks from their release queues |
19 | * TODO clean up link_task_to_cpu and check_slack args | 19 | * TODO clean up link_to_cpu and check_slack args |
20 | * TODO move slack completion into release | 20 | * TODO move slack completion into release |
21 | * TODO fix concurrent arms | 21 | * TODO fix concurrent arms |
22 | * TODO slack and BE servers, include slack higher prio | 22 | * TODO slack and BE servers, include slack higher prio |
@@ -56,11 +56,11 @@ atomic_t servers_running = ATOMIC_INIT(0); /* TODO should be unnecessary */ | |||
56 | 56 | ||
57 | #define TIME(x) \ | 57 | #define TIME(x) \ |
58 | (x) | 58 | (x) |
59 | /* ({lt_t y = x; \ */ | 59 | /* ({lt_t y = x; \ */ |
60 | /* do_div(y, NSEC_PER_MSEC); \ */ | 60 | /* do_div(y, NSEC_PER_MSEC); \ */ |
61 | /* y;}) */ | 61 | /* y;}) */ |
62 | #define TRACE_TIMER(fmt, args...) \ | 62 | #define TRACE_TIMER(fmt, args...) \ |
63 | sched_trace_log_message("%d P%d*[%s@%s:%d]: " fmt " at %d\n", \ | 63 | sched_trace_log_message("%d P%d*[%s@%s:%d]: " fmt " at %d\n", \ |
64 | TRACE_ARGS, ## args, TIME(litmus_clock())) | 64 | TRACE_ARGS, ## args, TIME(litmus_clock())) |
65 | #define TRACE_TASK_TIMER(t, fmt, args...) \ | 65 | #define TRACE_TASK_TIMER(t, fmt, args...) \ |
66 | TRACE_TIMER("(%s/%d:%d) " fmt, (t)->comm, (t)->pid, \ | 66 | TRACE_TIMER("(%s/%d:%d) " fmt, (t)->comm, (t)->pid, \ |
@@ -72,14 +72,14 @@ atomic_t servers_running = ATOMIC_INIT(0); /* TODO should be unnecessary */ | |||
72 | */ | 72 | */ |
73 | #ifdef DEBUG_EDF_HSB | 73 | #ifdef DEBUG_EDF_HSB |
74 | 74 | ||
75 | #define TRACE_SUB(fmt, args...) \ | 75 | #define TRACE_SUB(fmt, args...) \ |
76 | sched_trace_log_message("%d P%d [%s@%s:%d]: " fmt "\n", \ | 76 | sched_trace_log_message("%d P%d [%s@%s:%d]: " fmt "\n", \ |
77 | TRACE_ARGS, ## args) | 77 | TRACE_ARGS, ## args) |
78 | #define TRACE_TASK_SUB(t, fmt, args...) \ | 78 | #define TRACE_TASK_SUB(t, fmt, args...) \ |
79 | TRACE_SUB(TASK_FMT " " fmt, TASK_ARGS(t), ##args) | 79 | TRACE_SUB(TASK_FMT " " fmt, TASK_ARGS(t), ##args) |
80 | #define TRACE_SERVER_SUB(s, fmt, args...) \ | 80 | #define TRACE_SERVER_SUB(s, fmt, args...) \ |
81 | TRACE_SUB(SERVER_FMT " " fmt, SERVER_ARGS(s), ##args) | 81 | TRACE_SUB(SERVER_FMT " " fmt, SERVER_ARGS(s), ##args) |
82 | #define TRACE_TASK_SERVER_SUB(t, s, fmt, args...) \ | 82 | #define TRACE_TASK_SERVER_SUB(t, s, fmt, args...) \ |
83 | TRACE_TASK_SUB(t, SERVER_FMT " " fmt, SERVER_ARGS(s), ##args) | 83 | TRACE_TASK_SUB(t, SERVER_FMT " " fmt, SERVER_ARGS(s), ##args) |
84 | #else | 84 | #else |
85 | #define TRACE_SUB(fmt, args...) | 85 | #define TRACE_SUB(fmt, args...) |
@@ -165,7 +165,7 @@ static struct sched_plugin edf_hsb_plugin __cacheline_aligned_in_smp; | |||
165 | #define task_data(task) ((task_data_t*)tsk_rt(task)->plugin_data) | 165 | #define task_data(task) ((task_data_t*)tsk_rt(task)->plugin_data) |
166 | #define task_srt_server(task) ((server_t*)task_data(task)->srt_server) | 166 | #define task_srt_server(task) ((server_t*)task_data(task)->srt_server) |
167 | #define server_slack(s) ((server_t*)s->data) | 167 | #define server_slack(s) ((server_t*)s->data) |
168 | #define server_has_slack(s) ((server_t*)(s)->deadline != 0) | 168 | #define server_has_slack(s) (server_slack(s)->deadline != 0) |
169 | #define local_cpu_entry (&__get_cpu_var(cpu_entries)) | 169 | #define local_cpu_entry (&__get_cpu_var(cpu_entries)) |
170 | #define global_lock (&srt_domain.ready_lock) | 170 | #define global_lock (&srt_domain.ready_lock) |
171 | #define is_active_plugin (litmus == &edf_hsb_plugin) | 171 | #define is_active_plugin (litmus == &edf_hsb_plugin) |
@@ -329,13 +329,21 @@ static void check_donate_slack(server_t *donator, struct task_struct *was_schedu | |||
329 | if (donator->budget < SLACK_MIN) | 329 | if (donator->budget < SLACK_MIN) |
330 | return; | 330 | return; |
331 | 331 | ||
332 | if (server_has_slack(donator)) { | ||
333 | server_t *slack = server_slack(donator); | ||
334 | TRACE_SERVER_SUB(donator, "dead: %d, rel: %d, job: %d already donated", | ||
335 | slack->deadline, slack->release, slack->job_no); | ||
336 | return; | ||
337 | } | ||
338 | |||
332 | if (donator->type == S_HRT) | 339 | if (donator->type == S_HRT) |
333 | hrt_server = container_of(donator, hrt_server_t, server); | 340 | hrt_server = container_of(donator, hrt_server_t, server); |
334 | 341 | ||
335 | /* Donate if the server is waiting for a task release */ | 342 | /* Donate if the server is waiting for a task release */ |
336 | if ((donator->type == S_SRT && | 343 | if ((donator->type == S_SRT && |
337 | donator->job_no <= task_job_no(was_scheduled)) || | 344 | donator->job_no <= task_job_no(was_scheduled)) || |
338 | (donator->type == S_HRT && hrt_server->no_slack && | 345 | (donator->type == S_HRT && |
346 | hrt_server->no_slack && hrt_server->ready && | ||
339 | !__jobs_pending(&hrt_server->hrt_domain)) || | 347 | !__jobs_pending(&hrt_server->hrt_domain)) || |
340 | (donator->type == S_BE && | 348 | (donator->type == S_BE && |
341 | !__jobs_pending(&be_domain))) { | 349 | !__jobs_pending(&be_domain))) { |
@@ -368,7 +376,6 @@ static void check_slack_candidate(struct task_struct *task) | |||
368 | !head_in_list(&task_data(task)->candidate_list)) { | 376 | !head_in_list(&task_data(task)->candidate_list)) { |
369 | 377 | ||
370 | add_slack_candidate(task); | 378 | add_slack_candidate(task); |
371 | sched_trace_action(task, 8); | ||
372 | } | 379 | } |
373 | } | 380 | } |
374 | 381 | ||
@@ -458,7 +465,7 @@ static inline int check_hrt_server_initialized(hrt_server_t *hrt_server) | |||
458 | */ | 465 | */ |
459 | static void slack_timer_arm(hrt_server_t *hrt_server) | 466 | static void slack_timer_arm(hrt_server_t *hrt_server) |
460 | { | 467 | { |
461 | int cpu; | 468 | int cpu, err; |
462 | cpu_entry_t *entry; | 469 | cpu_entry_t *entry; |
463 | struct hrtimer *timer; | 470 | struct hrtimer *timer; |
464 | lt_t when_to_fire; | 471 | lt_t when_to_fire; |
@@ -502,19 +509,19 @@ static void slack_timer_arm(hrt_server_t *hrt_server) | |||
502 | TRACE("immediate: %llu", when_to_fire); | 509 | TRACE("immediate: %llu", when_to_fire); |
503 | hrt_server->no_slack = 1; | 510 | hrt_server->no_slack = 1; |
504 | } else if (cpu != smp_processor_id()) { | 511 | } else if (cpu != smp_processor_id()) { |
505 | atomic_set(&hrt_server->slack_timer_info.state, | 512 | err = hrtimer_start_on(cpu, |
506 | HRTIMER_START_ON_INACTIVE); | 513 | &hrt_server->slack_timer_info, |
507 | hrtimer_start_on(cpu, | 514 | &hrt_server->slack_timer, |
508 | &hrt_server->slack_timer_info, | 515 | ns_to_ktime(when_to_fire), |
509 | &hrt_server->slack_timer, | 516 | HRTIMER_MODE_ABS_PINNED); |
510 | ns_to_ktime(when_to_fire), | 517 | if (err) |
511 | HRTIMER_MODE_ABS_PINNED); | 518 | TRACE_SERVER_SUB(&hrt_server->server, "failed to arm slack"); |
512 | } else { | 519 | } else { |
513 | __hrtimer_start_range_ns(timer, ns_to_ktime(when_to_fire), | 520 | __hrtimer_start_range_ns(timer, ns_to_ktime(when_to_fire), |
514 | 0, HRTIMER_MODE_ABS_PINNED, 0); | 521 | 0, HRTIMER_MODE_ABS_PINNED, 0); |
515 | } | 522 | } |
516 | 523 | ||
517 | TRACE_SUB("slack timer armed to fire at %llu on P%d", | 524 | TRACE_SUB("slack timer 0x%x armed to fire at %llu on P%d", |
518 | TIME(when_to_fire), entry->cpu); | 525 | TIME(when_to_fire), entry->cpu); |
519 | } | 526 | } |
520 | 527 | ||
@@ -584,14 +591,10 @@ static void requeue_server(server_t *server) | |||
584 | static void reclaim_slack(server_t *slack) | 591 | static void reclaim_slack(server_t *slack) |
585 | { | 592 | { |
586 | lt_t exec; | 593 | lt_t exec; |
587 | hrt_server_t *hrt_server; | ||
588 | server_t *donator = server_slack(slack); | 594 | server_t *donator = server_slack(slack); |
589 | 595 | ||
590 | /* SRT servers do not ever reclaim slack */ | 596 | /* SRT servers do not ever reclaim slack */ |
591 | if (donator->type == S_SRT) | 597 | sched_trace_action(NULL, 5); |
592 | return; | ||
593 | else if (donator->type == S_HRT) | ||
594 | sched_trace_action(NULL, 5); | ||
595 | 598 | ||
596 | exec = slack->wcet - slack->budget; | 599 | exec = slack->wcet - slack->budget; |
597 | TRACE_SERVER_SUB(donator, "reclaiming %llu slack", TIME(exec)); | 600 | TRACE_SERVER_SUB(donator, "reclaiming %llu slack", TIME(exec)); |
@@ -606,27 +609,6 @@ static void reclaim_slack(server_t *slack) | |||
606 | /* If budget exhausted, server needs to wait for next release */ | 609 | /* If budget exhausted, server needs to wait for next release */ |
607 | if (!donator->budget) { | 610 | if (!donator->budget) { |
608 | TRACE_SERVER_SUB(donator, "exhausted by slack"); | 611 | TRACE_SERVER_SUB(donator, "exhausted by slack"); |
609 | /* if (donator->type == S_HRT) { */ | ||
610 | /* hrt_server = container_of(donator, */ | ||
611 | /* hrt_server_t, */ | ||
612 | /* server); */ | ||
613 | /* /\* BUG_ON(!hrt_server->ready); *\/ */ | ||
614 | /* /\* TRACE_SERVER_SUB(donator, "exhausted"); *\/ */ | ||
615 | /* /\* hrt_server->ready = 0; *\/ */ | ||
616 | /* /\* slack_timer_cancel(hrt_server); *\/ */ | ||
617 | /* } else if (donator->type == S_BE) { */ | ||
618 | /* TRACE_SERVER_SUB(donator, "BE removed from ready"); */ | ||
619 | /* /\* bheap_delete(server_order, &be_ready_servers, *\/ */ | ||
620 | /* /\* donator->hn); *\/ */ | ||
621 | /* } */ | ||
622 | |||
623 | /* /\* Prepare servers for their next period. SRT servers are */ | ||
624 | /* * handled with their SRT tasks and don't need assistance. */ | ||
625 | /* *\/ */ | ||
626 | /* if (donator->type != S_SRT) { */ | ||
627 | /* /\* server_release(donator); *\/ */ | ||
628 | /* /\* requeue_server(donator); *\/ */ | ||
629 | /* } */ | ||
630 | } | 612 | } |
631 | } | 613 | } |
632 | 614 | ||
@@ -651,6 +633,7 @@ static noinline void link_server(cpu_entry_t *entry, | |||
651 | } else if (next_server->type == S_SLACK) { | 633 | } else if (next_server->type == S_SLACK) { |
652 | /* Should have already been removed from slack list */ | 634 | /* Should have already been removed from slack list */ |
653 | BUG_ON(head_in_list(&task_data(entry->linked)->candidate_list)); | 635 | BUG_ON(head_in_list(&task_data(entry->linked)->candidate_list)); |
636 | sched_trace_action(entry->linked, 4); | ||
654 | } else { /* BE */ | 637 | } else { /* BE */ |
655 | /* Should have already been removed from ready heap */ | 638 | /* Should have already been removed from ready heap */ |
656 | BUG_ON(bheap_node_in_heap(next_server->hn)); | 639 | BUG_ON(bheap_node_in_heap(next_server->hn)); |
@@ -692,7 +675,7 @@ static noinline void unlink_server(cpu_entry_t *entry, int requeue) | |||
692 | 675 | ||
693 | if (server->type == S_SLACK && server->deadline) { | 676 | if (server->type == S_SLACK && server->deadline) { |
694 | add_slack(server); | 677 | add_slack(server); |
695 | //sched_trace_action(entry->linked, 6); | 678 | sched_trace_action(entry->linked, 6); |
696 | 679 | ||
697 | /* Donator needs to absorb slack execution time */ | 680 | /* Donator needs to absorb slack execution time */ |
698 | reclaim_slack(server); | 681 | reclaim_slack(server); |
@@ -711,10 +694,9 @@ static noinline void unlink_server(cpu_entry_t *entry, int requeue) | |||
711 | * scheduled on a different CPU. The last argument is only needed | 694 | * scheduled on a different CPU. The last argument is only needed |
712 | * for BE tasks as their servers can't be determined here. | 695 | * for BE tasks as their servers can't be determined here. |
713 | */ | 696 | */ |
714 | static noinline void link_task_to_cpu(cpu_entry_t *entry, | 697 | static noinline void link_to_cpu(cpu_entry_t *entry, |
715 | struct task_struct* linked, | 698 | struct task_struct* linked, |
716 | server_t* next_server, | 699 | server_t* next_server) |
717 | int swap_on_sched) | ||
718 | { | 700 | { |
719 | cpu_entry_t *sched; | 701 | cpu_entry_t *sched; |
720 | server_t *tmp_server; | 702 | server_t *tmp_server; |
@@ -723,7 +705,7 @@ static noinline void link_task_to_cpu(cpu_entry_t *entry, | |||
723 | 705 | ||
724 | BUG_ON(linked && !is_realtime(linked)); | 706 | BUG_ON(linked && !is_realtime(linked)); |
725 | BUG_ON(linked && is_hrt(linked) && entry->cpu != task_cpu(linked)); | 707 | BUG_ON(linked && is_hrt(linked) && entry->cpu != task_cpu(linked)); |
726 | BUG_ON(entry->cpu == edf_hsb_release_master); | 708 | BUG_ON(entry->cpu == edf_hsb_release_master); |
727 | 709 | ||
728 | if (linked) | 710 | if (linked) |
729 | TRACE_TASK_SERVER_SUB(linked, next_server, "linking to P%d", | 711 | TRACE_TASK_SERVER_SUB(linked, next_server, "linking to P%d", |
@@ -748,7 +730,6 @@ static noinline void link_task_to_cpu(cpu_entry_t *entry, | |||
748 | 730 | ||
749 | /* Swap link with entry on which linked is scheduled */ | 731 | /* Swap link with entry on which linked is scheduled */ |
750 | if (entry != sched && !is_hrt(linked) && | 732 | if (entry != sched && !is_hrt(linked) && |
751 | swap_on_sched && | ||
752 | (!sched->linked || !is_hrt(sched->linked))) { | 733 | (!sched->linked || !is_hrt(sched->linked))) { |
753 | TRACE_TASK_SUB(linked, "already scheduled on P%d", | 734 | TRACE_TASK_SUB(linked, "already scheduled on P%d", |
754 | sched->cpu); | 735 | sched->cpu); |
@@ -811,7 +792,7 @@ static noinline void unlink(struct task_struct* t) | |||
811 | if (t->rt_param.linked_on != NO_CPU) { | 792 | if (t->rt_param.linked_on != NO_CPU) { |
812 | /* Unlink */ | 793 | /* Unlink */ |
813 | entry = task_linked_entry(t); | 794 | entry = task_linked_entry(t); |
814 | link_task_to_cpu(entry, NULL, NULL, 0); | 795 | link_to_cpu(entry, NULL, NULL); |
815 | } else if (is_queued(t)) { | 796 | } else if (is_queued(t)) { |
816 | 797 | ||
817 | if (is_released(t, litmus_clock())) { | 798 | if (is_released(t, litmus_clock())) { |
@@ -861,6 +842,47 @@ static inline void catchup_server(server_t *server, lt_t time) | |||
861 | TRACE_SERVER_SUB(server, "catching up to %llu", time); | 842 | TRACE_SERVER_SUB(server, "catching up to %llu", time); |
862 | } | 843 | } |
863 | 844 | ||
845 | static int catchup_srt_server(struct task_struct *task) | ||
846 | { | ||
847 | int jobs, rv = 0; | ||
848 | lt_t release; | ||
849 | lt_t now = litmus_clock(); | ||
850 | server_t *srt_server = task_srt_server(task); | ||
851 | |||
852 | if (lt_before(srt_server->deadline, now) && | ||
853 | srt_server->job_no > 1) { | ||
854 | /* Calculate the number of jobs behind the server is */ | ||
855 | jobs = lt_subtract(now, srt_server->deadline) / | ||
856 | srt_server->period + 1; | ||
857 | |||
858 | /* Get the new release */ | ||
859 | release = srt_server->release + jobs * srt_server->period; | ||
860 | |||
861 | TRACE_SERVER_SUB(srt_server, "catching up to %llu, job %d", | ||
862 | release, srt_server->job_no + jobs); | ||
863 | |||
864 | /* Update server state */ | ||
865 | server_release_at(srt_server, release); | ||
866 | srt_server->job_no += jobs - 1; | ||
867 | |||
868 | /* Force task to take characteristics of server */ | ||
869 | tsk_rt(task)->job_params.release = srt_server->deadline; | ||
870 | tsk_rt(task)->job_params.deadline = srt_server->release; | ||
871 | |||
872 | rv = 1; | ||
873 | |||
874 | sched_trace_action(task, 2); | ||
875 | |||
876 | } else if (lt_before(srt_server->deadline, now) && | ||
877 | srt_server->job_no <= 1) { | ||
878 | |||
879 | server_release_at(srt_server, get_release(task)); | ||
880 | srt_server->job_no = task_job_no(task); | ||
881 | } | ||
882 | |||
883 | return rv; | ||
884 | } | ||
885 | |||
864 | /* | 886 | /* |
865 | * Returns the next eligible slack server. This will remove any expired | 887 | * Returns the next eligible slack server. This will remove any expired |
866 | * slack servers still present in the list. | 888 | * slack servers still present in the list. |
@@ -922,20 +944,34 @@ static struct task_struct* next_eligible_slack(void) | |||
922 | static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) | 944 | static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) |
923 | { | 945 | { |
924 | lt_t now = litmus_clock(); | 946 | lt_t now = litmus_clock(); |
947 | lt_t dead, slack, budget; | ||
925 | struct task_struct *task = __peek_ready(&hrt_server->hrt_domain); | 948 | struct task_struct *task = __peek_ready(&hrt_server->hrt_domain); |
926 | 949 | ||
927 | /* Catch up server if it is initialized, not running, and late */ | 950 | /* Catch up server if it is initialized, not running, and late */ |
928 | if (task && | 951 | if (task && |
929 | check_hrt_server_initialized(hrt_server) && | 952 | check_hrt_server_initialized(hrt_server) && |
930 | !is_server_linked(&hrt_server->server) && | 953 | !is_server_linked(&hrt_server->server)) { |
931 | lt_before_eq(hrt_server->server.deadline, now)) { | 954 | |
955 | dead = hrt_server->server.deadline; | ||
956 | budget = hrt_server->server.budget; | ||
957 | slack = lt_subtract(dead, budget); | ||
958 | |||
959 | TRACE_SUB("%llu", now); | ||
960 | |||
961 | if (lt_before_eq(dead, now)) { | ||
962 | /* The server missed a release */ | ||
963 | catchup_server(&hrt_server->server, now); | ||
964 | slack_timer_arm(hrt_server); | ||
965 | TRACE_SERVER_SUB(&hrt_server->server, "now ready"); | ||
966 | hrt_server->ready = 1; | ||
967 | hrt_server->no_slack = 0; | ||
968 | sched_trace_action(NULL, 2); /* Release */ | ||
969 | } else if (lt_before_eq(slack, now) && !hrt_server->no_slack) { | ||
970 | /* The server missed the shift to no slack */ | ||
971 | hrt_server->no_slack = 1; | ||
972 | sched_trace_action(NULL, 3); | ||
973 | } | ||
932 | 974 | ||
933 | catchup_server(&hrt_server->server, now); | ||
934 | slack_timer_arm(hrt_server); | ||
935 | TRACE_SERVER_SUB(&hrt_server->server, "now ready"); | ||
936 | hrt_server->ready = 1; | ||
937 | hrt_server->no_slack = 0; | ||
938 | sched_trace_action(NULL, 2); /* Release */ | ||
939 | } else { | 975 | } else { |
940 | TRACE_SERVER_SUB(&hrt_server->server, "%llu %d %llu", | 976 | TRACE_SERVER_SUB(&hrt_server->server, "%llu %d %llu", |
941 | hrt_server->server.deadline, | 977 | hrt_server->server.deadline, |
@@ -945,9 +981,14 @@ static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) | |||
945 | 981 | ||
946 | if (!hrt_server->server.budget || | 982 | if (!hrt_server->server.budget || |
947 | (task && !is_eligible(task, hrt_server))) { | 983 | (task && !is_eligible(task, hrt_server))) { |
948 | if (task) | 984 | if (task) |
949 | TRACE_TASK_SUB(task, "not eligible"); | 985 | TRACE_TASK_SUB(task, "not eligible"); |
950 | task = NULL; | 986 | task = NULL; |
987 | |||
988 | /* Donate slack if we have nothing to schedule */ | ||
989 | if (hrt_server->ready && hrt_server->no_slack) { | ||
990 | check_donate_slack(&hrt_server->server, NULL); | ||
991 | } | ||
951 | } | 992 | } |
952 | 993 | ||
953 | return task; | 994 | return task; |
@@ -958,29 +999,36 @@ static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) | |||
958 | */ | 999 | */ |
959 | static struct task_struct* next_eligible_srt(void) | 1000 | static struct task_struct* next_eligible_srt(void) |
960 | { | 1001 | { |
961 | struct task_struct *next_srt = __peek_ready(&srt_domain); | 1002 | int done = 0; |
962 | server_t *srt_server; | 1003 | struct task_struct *next_srt; |
963 | 1004 | ||
964 | /* A blocking task might pollute the SRT domain if the | 1005 | while (!done) { |
965 | * task blocked while it was being run by a slack server. | ||
966 | * Remove and ignore this task. | ||
967 | */ | ||
968 | while (next_srt && (!is_running(next_srt) || | ||
969 | unlikely(!is_realtime(next_srt)))) { | ||
970 | TRACE_TASK_SUB(next_srt, "removing blocking task"); | ||
971 | remove(&srt_domain, next_srt); | ||
972 | next_srt = __peek_ready(&srt_domain); | 1006 | next_srt = __peek_ready(&srt_domain); |
973 | } | ||
974 | 1007 | ||
975 | /* Catch up srt server. This happens when the job is tardy due | 1008 | /* A blocking task might pollute the SRT domain if the |
976 | * to overutilization of the system. | 1009 | * task blocked while it was being run by a slack server. |
977 | */ | 1010 | * Remove and ignore this task. |
978 | if (next_srt) { | 1011 | */ |
979 | srt_server = task_srt_server(next_srt); | 1012 | while (next_srt && (get_rt_flags(next_srt) == RT_F_BLOCK || |
1013 | unlikely(!is_realtime(next_srt)))) { | ||
1014 | TRACE_TASK_SUB(next_srt, "removing finished task"); | ||
1015 | remove(&srt_domain, next_srt); | ||
1016 | next_srt = __peek_ready(&srt_domain); | ||
1017 | } | ||
1018 | |||
1019 | /* If the task blocked for awhile or has otherwise not been | ||
1020 | * accessed, its server could have fallen behind. | ||
1021 | */ | ||
1022 | if (next_srt) { | ||
1023 | done = !catchup_srt_server(next_srt); | ||
980 | 1024 | ||
981 | if (lt_before(srt_server->deadline, get_deadline(next_srt))) { | 1025 | /* The parameters were modified. Re-insert the task. */ |
982 | server_release_at(srt_server, get_release(next_srt)); | 1026 | if (!done) { |
983 | srt_server->job_no = task_job_no(next_srt); | 1027 | remove(&srt_domain, next_srt); |
1028 | __add_ready(&srt_domain, next_srt); | ||
1029 | } | ||
1030 | } else { | ||
1031 | done = 1; | ||
984 | } | 1032 | } |
985 | } | 1033 | } |
986 | 1034 | ||
@@ -1007,6 +1055,7 @@ static server_t* next_eligible_be_server(void) | |||
1007 | catchup_server(be_server, now); | 1055 | catchup_server(be_server, now); |
1008 | bheap_insert(server_order, &be_ready_servers, | 1056 | bheap_insert(server_order, &be_ready_servers, |
1009 | be_server->hn); | 1057 | be_server->hn); |
1058 | |||
1010 | be_server = next_be_server(); | 1059 | be_server = next_be_server(); |
1011 | sched_trace_action(NULL, 2); /* Release */ | 1060 | sched_trace_action(NULL, 2); /* Release */ |
1012 | } | 1061 | } |
@@ -1214,7 +1263,7 @@ static void edf_hsb_pick_next(cpu_entry_t *entry) | |||
1214 | "removing and picked"); | 1263 | "removing and picked"); |
1215 | 1264 | ||
1216 | /* A slack preemption could cause something that was already | 1265 | /* A slack preemption could cause something that was already |
1217 | * running to be 'swapped' to this CPU in link_task_to_cpu. | 1266 | * running to be 'swapped' to this CPU in link_to_cpu. |
1218 | */ | 1267 | */ |
1219 | if (entry->linked) { | 1268 | if (entry->linked) { |
1220 | linked = entry->linked; | 1269 | linked = entry->linked; |
@@ -1222,7 +1271,7 @@ static void edf_hsb_pick_next(cpu_entry_t *entry) | |||
1222 | requeue(linked, get_rt_domain(entry, linked)); | 1271 | requeue(linked, get_rt_domain(entry, linked)); |
1223 | TRACE_TASK_SUB(linked, "preempted next pick"); | 1272 | TRACE_TASK_SUB(linked, "preempted next pick"); |
1224 | } | 1273 | } |
1225 | link_task_to_cpu(entry, next_task, next_server, 1); | 1274 | link_to_cpu(entry, next_task, next_server); |
1226 | } | 1275 | } |
1227 | } | 1276 | } |
1228 | 1277 | ||
@@ -1243,7 +1292,7 @@ static void preempt(cpu_entry_t *entry, struct task_struct *next, | |||
1243 | 1292 | ||
1244 | check_for_slack_preempt(next, next_server, entry, slack_resched); | 1293 | check_for_slack_preempt(next, next_server, entry, slack_resched); |
1245 | linked = entry->linked; | 1294 | linked = entry->linked; |
1246 | link_task_to_cpu(entry, next, next_server, 1); | 1295 | link_to_cpu(entry, next, next_server); |
1247 | 1296 | ||
1248 | /* No need for this if only the server was preempted */ | 1297 | /* No need for this if only the server was preempted */ |
1249 | if (!linked || linked != entry->linked) { | 1298 | if (!linked || linked != entry->linked) { |
@@ -1261,9 +1310,9 @@ static void preempt(cpu_entry_t *entry, struct task_struct *next, | |||
1261 | * 2. slack donated by server is running a task on a different CPU | 1310 | * 2. slack donated by server is running a task on a different CPU |
1262 | */ | 1311 | */ |
1263 | static void check_for_slack_preempt(struct task_struct *task, | 1312 | static void check_for_slack_preempt(struct task_struct *task, |
1264 | server_t *server, | 1313 | server_t *server, |
1265 | cpu_entry_t *next_entry, | 1314 | cpu_entry_t *next_entry, |
1266 | int resched) | 1315 | int resched) |
1267 | { | 1316 | { |
1268 | cpu_entry_t *entry = NULL; | 1317 | cpu_entry_t *entry = NULL; |
1269 | server_t *slack = server_slack(server); | 1318 | server_t *slack = server_slack(server); |
@@ -1333,7 +1382,7 @@ static void check_for_global_preempt(void) | |||
1333 | #else | 1382 | #else |
1334 | if (!pref->linked) | 1383 | if (!pref->linked) |
1335 | #endif | 1384 | #endif |
1336 | entry = pref; | 1385 | entry = pref; |
1337 | } | 1386 | } |
1338 | 1387 | ||
1339 | /* Preempt only if we have an earlier deadline */ | 1388 | /* Preempt only if we have an earlier deadline */ |
@@ -1499,7 +1548,7 @@ static enum hrtimer_restart slack_timer_fire(struct hrtimer *timer) | |||
1499 | 1548 | ||
1500 | /* Donate slack if there is nothing to do */ | 1549 | /* Donate slack if there is nothing to do */ |
1501 | if (!entry->linked || !is_hrt(entry->linked)) { | 1550 | if (!entry->linked || !is_hrt(entry->linked)) { |
1502 | donate_slack(&server->server); | 1551 | check_donate_slack(&server->server, NULL); |
1503 | check_for_global_preempt(); | 1552 | check_for_global_preempt(); |
1504 | } | 1553 | } |
1505 | 1554 | ||
@@ -1907,7 +1956,7 @@ static long edf_hsb_admit_task(struct task_struct *task) | |||
1907 | if (is_hrt(task)) { | 1956 | if (is_hrt(task)) { |
1908 | return check_hrt_server_initialized(&entry->hrt_server) && | 1957 | return check_hrt_server_initialized(&entry->hrt_server) && |
1909 | ((task_cpu(task) == task->rt_param.task_params.cpu) && | 1958 | ((task_cpu(task) == task->rt_param.task_params.cpu) && |
1910 | (task_cpu(task) == entry->cpu)) ? 0 : -EINVAL; | 1959 | (task_cpu(task) == entry->cpu)) ? 0 : -EINVAL; |
1911 | } else { | 1960 | } else { |
1912 | /* If the task is not HRT, we don't want to force the user | 1961 | /* If the task is not HRT, we don't want to force the user |
1913 | * to specify a CPU. | 1962 | * to specify a CPU. |
@@ -1945,11 +1994,24 @@ static long edf_hsb_deactivate_plugin(void) | |||
1945 | static void edf_hsb_task_block(struct task_struct *task) | 1994 | static void edf_hsb_task_block(struct task_struct *task) |
1946 | { | 1995 | { |
1947 | unsigned long flags; | 1996 | unsigned long flags; |
1997 | cpu_entry_t *entry = task_sched_entry(task); | ||
1998 | server_t *linked, *srt; | ||
1948 | 1999 | ||
1949 | TRACE_TASK(task, "block at %llu\n", litmus_clock()); | 2000 | TRACE_TASK(task, "block at %llu\n", litmus_clock()); |
1950 | 2001 | ||
1951 | raw_spin_lock_irqsave(global_lock, flags); | 2002 | raw_spin_lock_irqsave(global_lock, flags); |
2003 | |||
2004 | set_rt_flags(task, RT_F_BLOCK); | ||
2005 | |||
2006 | linked = entry->linked_server; | ||
2007 | srt = task_srt_server(task); | ||
2008 | |||
1952 | unlink(task); | 2009 | unlink(task); |
2010 | |||
2011 | if (is_srt(task) && srt == linked) { | ||
2012 | check_donate_slack(task_srt_server(task), task); | ||
2013 | } | ||
2014 | |||
1953 | raw_spin_unlock_irqrestore(global_lock, flags); | 2015 | raw_spin_unlock_irqrestore(global_lock, flags); |
1954 | } | 2016 | } |
1955 | 2017 | ||
@@ -1989,7 +2051,7 @@ static void edf_hsb_task_exit(struct task_struct *task) | |||
1989 | static struct task_struct* edf_hsb_schedule(struct task_struct *prev) | 2051 | static struct task_struct* edf_hsb_schedule(struct task_struct *prev) |
1990 | { | 2052 | { |
1991 | unsigned long flags; | 2053 | unsigned long flags; |
1992 | int blocks, out_of_time, preempted, sleep, was_slack; | 2054 | int blocks, preempted, sleep, was_slack; |
1993 | struct task_struct *curr; | 2055 | struct task_struct *curr; |
1994 | cpu_entry_t *entry = local_cpu_entry; | 2056 | cpu_entry_t *entry = local_cpu_entry; |
1995 | 2057 | ||
@@ -2007,11 +2069,6 @@ static struct task_struct* edf_hsb_schedule(struct task_struct *prev) | |||
2007 | 2069 | ||
2008 | curr = entry->scheduled; | 2070 | curr = entry->scheduled; |
2009 | 2071 | ||
2010 | if (curr != prev && prev->pid == 0) { | ||
2011 | TRACE_SUB("should bug"); | ||
2012 | } else { | ||
2013 | BUG_ON(curr && !is_realtime(prev)); | ||
2014 | } | ||
2015 | TRACE("server_budget: %llu, server_deadline: %llu, " | 2072 | TRACE("server_budget: %llu, server_deadline: %llu, " |
2016 | "curr_time: %llu, no_slack: %d, ready: %d\n", | 2073 | "curr_time: %llu, no_slack: %d, ready: %d\n", |
2017 | TIME(entry->hrt_server.server.budget), | 2074 | TIME(entry->hrt_server.server.budget), |
@@ -2019,23 +2076,27 @@ static struct task_struct* edf_hsb_schedule(struct task_struct *prev) | |||
2019 | TIME(litmus_clock()), entry->hrt_server.no_slack, | 2076 | TIME(litmus_clock()), entry->hrt_server.no_slack, |
2020 | entry->hrt_server.ready); | 2077 | entry->hrt_server.ready); |
2021 | 2078 | ||
2079 | if (curr != prev && prev->pid == 0) { | ||
2080 | TRACE_SUB("should bug"); | ||
2081 | } else { | ||
2082 | BUG_ON(curr && !is_realtime(prev)); | ||
2083 | } | ||
2084 | |||
2022 | /* Determine state */ | 2085 | /* Determine state */ |
2023 | blocks = curr && !is_running(curr); | 2086 | blocks = curr && !is_running(curr); |
2024 | preempted = entry->scheduled != entry->linked; | 2087 | preempted = entry->scheduled != entry->linked; |
2025 | sleep = curr && get_rt_flags(curr) == RT_F_SLEEP; | 2088 | sleep = curr && get_rt_flags(curr) == RT_F_SLEEP; |
2026 | out_of_time = curr && budget_enforced(curr) && | ||
2027 | budget_exhausted(curr); | ||
2028 | was_slack = !list_empty(&slack_queue); | 2089 | was_slack = !list_empty(&slack_queue); |
2029 | 2090 | ||
2030 | TRACE("blocks: %d, preempted: %d, sleep: %d, oot: %d\n", | 2091 | TRACE("blocks: %d, preempted: %d, sleep: %d\n", |
2031 | blocks, preempted, sleep, out_of_time); | 2092 | blocks, preempted, sleep); |
2032 | if (blocks) | 2093 | if (blocks) |
2033 | unlink(entry->scheduled); | 2094 | unlink(entry->scheduled); |
2034 | 2095 | ||
2035 | /* If the task has gone to sleep or exhausted its budget, it | 2096 | /* If the task has gone to sleep or exhausted its budget, it |
2036 | * must complete its current job. | 2097 | * must complete its current job. |
2037 | */ | 2098 | */ |
2038 | if ((out_of_time || sleep) && !blocks && !preempted) | 2099 | if (sleep && !blocks && !preempted) |
2039 | job_completion(entry, entry->scheduled); | 2100 | job_completion(entry, entry->scheduled); |
2040 | 2101 | ||
2041 | /* Pick the next task if there isn't one currently */ | 2102 | /* Pick the next task if there isn't one currently */ |
@@ -2154,9 +2215,12 @@ static void edf_hsb_task_wake_up(struct task_struct *task) | |||
2154 | get_rt_phase(task)); | 2215 | get_rt_phase(task)); |
2155 | 2216 | ||
2156 | if (!is_be(task)) { | 2217 | if (!is_be(task)) { |
2218 | if (is_srt(task)) { | ||
2219 | catchup_srt_server(task); | ||
2220 | } | ||
2221 | |||
2157 | /* Non-BE tasks are not sporadic in this model */ | 2222 | /* Non-BE tasks are not sporadic in this model */ |
2158 | set_rt_flags(task, RT_F_RUNNING); | 2223 | set_rt_flags(task, RT_F_RUNNING); |
2159 | |||
2160 | /* The job blocked while it was being run by a slack server */ | 2224 | /* The job blocked while it was being run by a slack server */ |
2161 | if (is_queued(task)) { | 2225 | if (is_queued(task)) { |
2162 | check_slack_candidate(task); | 2226 | check_slack_candidate(task); |
@@ -2225,14 +2289,14 @@ static int __init init_edf_hsb(void) | |||
2225 | rv = register_sched_plugin(&edf_hsb_plugin); | 2289 | rv = register_sched_plugin(&edf_hsb_plugin); |
2226 | if (rv) { | 2290 | if (rv) { |
2227 | printk(KERN_ERR "Could not register plugin %s.\n", | 2291 | printk(KERN_ERR "Could not register plugin %s.\n", |
2228 | edf_hsb_plugin.plugin_name); | 2292 | edf_hsb_plugin.plugin_name); |
2229 | goto out; | 2293 | goto out; |
2230 | } | 2294 | } |
2231 | 2295 | ||
2232 | rv = make_plugin_proc_dir(&edf_hsb_plugin, &edf_hsb_proc_dir); | 2296 | rv = make_plugin_proc_dir(&edf_hsb_plugin, &edf_hsb_proc_dir); |
2233 | if (rv) { | 2297 | if (rv) { |
2234 | printk(KERN_ERR "Could not create %s procfs dir.\n", | 2298 | printk(KERN_ERR "Could not create %s procfs dir.\n", |
2235 | edf_hsb_plugin.plugin_name); | 2299 | edf_hsb_plugin.plugin_name); |
2236 | goto out; | 2300 | goto out; |
2237 | } | 2301 | } |
2238 | 2302 | ||