aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2011-04-15 04:02:44 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2011-04-15 04:02:44 -0400
commit4ff76e7063c0ebbd616e92079468ddfce133cb4d (patch)
tree13bd059c58fd7052d226844b8fe9be51461daef3
parent0317947a4d7fa886d90ec500444446894726f680 (diff)
Support for chains of blocking tasks.
-rw-r--r--include/litmus/rt_param.h1
-rw-r--r--litmus/sched_edf_hsb.c280
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 */
459static void slack_timer_arm(hrt_server_t *hrt_server) 466static 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)
584static void reclaim_slack(server_t *slack) 591static 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 */
714static noinline void link_task_to_cpu(cpu_entry_t *entry, 697static 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
845static 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)
922static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) 944static 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 */
959static struct task_struct* next_eligible_srt(void) 1000static 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 */
1263static void check_for_slack_preempt(struct task_struct *task, 1312static 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)
1945static void edf_hsb_task_block(struct task_struct *task) 1994static 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)
1989static struct task_struct* edf_hsb_schedule(struct task_struct *prev) 2051static 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