aboutsummaryrefslogtreecommitdiffstats
path: root/native/src/edf/qpa.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/edf/qpa.cpp')
-rw-r--r--native/src/edf/qpa.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/native/src/edf/qpa.cpp b/native/src/edf/qpa.cpp
new file mode 100644
index 0000000..23865ca
--- /dev/null
+++ b/native/src/edf/qpa.cpp
@@ -0,0 +1,163 @@
1#include <algorithm>
2#include <set>
3
4#include <stdlib.h>
5#include "tasks.h"
6#include "math-helper.h"
7#include "stl-helper.h"
8#include "schedulability.h"
9
10#include "edf/qpa.h"
11
12QPATest::QPATest(unsigned int num_processors)
13{
14 if (num_processors != 1)
15 {
16 // This is a uniprocessor test---complain even in non-debug
17 // builds.
18 abort();
19 }
20}
21
22static integral_t edf_busy_interval(const TaskSet &ts)
23{
24 integral_t interval = 0;
25 integral_t total_cost = 0;
26
27 // initial guess: sum of all costs.
28 for (unsigned int i = 0; i < ts.get_task_count(); i++)
29 interval += ts[i].get_wcet();
30
31 total_cost = interval;
32 do {
33 interval = total_cost;
34 total_cost = 0;
35 for (unsigned int i = 0; i < ts.get_task_count(); i++)
36 {
37 integral_t jobs;
38 jobs = divide_with_ceil(interval, ts[i].get_period());
39 total_cost += jobs * ts[i].get_wcet();
40 }
41 } while (interval != total_cost);
42
43 return interval;
44}
45
46static integral_t zhang_burns_interval(const TaskSet &ts)
47{
48 integral_t interval = 0;
49 fractional_t total_scaled_delta = 0;
50 fractional_t total_util;
51
52 ts.get_utilization(total_util);
53
54 for (unsigned int i = 0; i < ts.get_task_count(); i++)
55 {
56 integral_t dl = ts[i].get_deadline();
57 integral_t per = ts[i].get_period();
58 integral_t delta = dl - per;
59
60 interval = std::max(interval, delta);
61
62 fractional_t util;
63 ts[i].get_utilization(util);
64 total_scaled_delta += (per - dl) * util;
65 }
66
67 total_scaled_delta /= (1 - total_util);
68
69 interval = std::max(interval, round_up(total_scaled_delta));
70
71 return interval;
72}
73
74std::set<unsigned long> get_testpoints(const TaskSet &ts,
75 const integral_t &max_time)
76{
77 std::set<unsigned long> points;
78
79 // determine all test points
80 for (unsigned int i = 0; i < ts.get_task_count(); i++)
81 {
82 unsigned long time = ts[i].get_deadline();
83
84 for (unsigned long j = 0; time < max_time; j++)
85 {
86 points.insert(time);
87 time += ts[i].get_period();
88 }
89 }
90 return points;
91}
92
93static integral_t max_deadline(const Task &task,
94 const integral_t &max_time)
95{
96 integral_t dl = max_time - task.get_deadline();
97
98 // implicit floor in integer division
99 dl /= task.get_period();
100 return dl * task.get_period() + task.get_deadline();
101}
102
103
104static unsigned long min_relative_deadline(const TaskSet &ts)
105{
106 unsigned long dl = ULONG_MAX;
107
108 for (unsigned int i = 0; i < ts.get_task_count(); i++)
109 dl = std::min(dl, ts[i].get_deadline());
110
111 return dl;
112}
113
114static integral_t get_largest_testpoint(const TaskSet &ts,
115 const integral_t &max_time)
116{
117 integral_t point = 0;
118
119 for (unsigned int i = 0; i < ts.get_task_count(); i++)
120 {
121 unsigned long dl = ts[i].get_deadline();
122 if (dl < max_time)
123 {
124 integral_t max_dl = max_deadline(ts[i], max_time);
125 if (max_dl == max_time)
126 max_dl -= ts[i].get_period();
127 if (max_dl > point)
128 point = max_dl;
129 }
130 }
131
132 return point;
133}
134
135bool QPATest::is_schedulable(const TaskSet &ts, bool check_preconditions)
136{
137 integral_t max_interval = edf_busy_interval(ts);
138 unsigned long min_interval = min_relative_deadline(ts);
139
140 fractional_t util;
141 ts.get_utilization(util);
142
143 if (util < 1)
144 max_interval = std::min(max_interval, zhang_burns_interval(ts));
145 else if (util > 1)
146 return false;
147
148 integral_t next = get_largest_testpoint(ts, max_interval);
149 integral_t demand;
150 integral_t interval;
151
152 do {
153 interval = next;
154 ts.bound_demand(interval, demand);
155 if (demand < interval)
156 next = demand;
157 else
158 next = get_largest_testpoint(ts, interval);
159
160 } while (demand <= interval && demand > min_interval);
161
162 return demand <= min_interval;
163}