aboutsummaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2012-11-27 06:33:12 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2012-11-27 06:33:29 -0500
commit31114f8a3be33b0289f09df4506ba25664aa517c (patch)
tree97530e8d365eec120e2cb23c666fabd188dd36aa /native
parenta9d8499bbdfc69b24b65d38c370616a4f79e6b1c (diff)
Add QPA EDF uniprocessor test
Based on Zhang and Burns (2009), "Schedulability Analysis for Real-Time Systems with EDF Scheduling", IEEE Transactions on Computers, Vol 58, No 9.
Diffstat (limited to 'native')
-rw-r--r--native/Makefile3
-rw-r--r--native/include/edf/qpa.h16
-rw-r--r--native/include/math-helper.h22
-rw-r--r--native/interface/sched.i2
-rw-r--r--native/src/edf/qpa.cpp163
5 files changed, 205 insertions, 1 deletions
diff --git a/native/Makefile b/native/Makefile
index 6fb9c16..d9bfa1f 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -63,7 +63,8 @@ vpath %.cpp src src/edf src/blocking
63 63
64# #### Common C++ source files #### 64# #### Common C++ source files ####
65 65
66EDF_OBJ = baker.o baruah.o gfb.o bcl.o bcl_iterative.o rta.o ffdbf.o gedf.o gel_pl.o load.o cpu_time.o 66EDF_OBJ = baker.o baruah.o gfb.o bcl.o bcl_iterative.o rta.o
67EDF_OBJ += ffdbf.o gedf.o gel_pl.o load.o cpu_time.o qpa.o
67SCHED_OBJ = sim.o schedule_sim.o 68SCHED_OBJ = sim.o schedule_sim.o
68CORE_OBJ = tasks.o 69CORE_OBJ = tasks.o
69SYNC_OBJ = sharedres.o dpcp.o mpcp.o 70SYNC_OBJ = sharedres.o dpcp.o mpcp.o
diff --git a/native/include/edf/qpa.h b/native/include/edf/qpa.h
new file mode 100644
index 0000000..18123aa
--- /dev/null
+++ b/native/include/edf/qpa.h
@@ -0,0 +1,16 @@
1#ifndef QPA_H
2#define QPA_H
3
4class QPATest : public SchedulabilityTest
5{
6 private:
7 unsigned int m;
8
9 public:
10 QPATest(unsigned int num_processors);
11
12 bool is_schedulable(const TaskSet &ts, bool check_preconditions = true);
13
14};
15
16#endif
diff --git a/native/include/math-helper.h b/native/include/math-helper.h
index 063558c..850e3a5 100644
--- a/native/include/math-helper.h
+++ b/native/include/math-helper.h
@@ -1,6 +1,8 @@
1#ifndef MATH_HELPER_H 1#ifndef MATH_HELPER_H
2#define MATH_HELPER_H 2#define MATH_HELPER_H
3 3
4#include "time-types.h"
5
4static inline unsigned long divide_with_ceil(unsigned long numer, 6static inline unsigned long divide_with_ceil(unsigned long numer,
5 unsigned long denom) 7 unsigned long denom)
6{ 8{
@@ -11,4 +13,24 @@ static inline unsigned long divide_with_ceil(unsigned long numer,
11 return (numer / denom) + 1; 13 return (numer / denom) + 1;
12} 14}
13 15
16
17
18
19static inline integral_t divide_with_ceil(const integral_t &numer,
20 const integral_t &denom)
21{
22 integral_t result;
23 mpz_cdiv_q(result.get_mpz_t(), numer.get_mpz_t(), denom.get_mpz_t());
24 return result;
25}
26
27
28static inline integral_t round_up(const fractional_t &f)
29{
30 integral_t result;
31 mpz_cdiv_q(result.get_mpz_t(), f.get_num_mpz_t(), f.get_den_mpz_t());
32 return result * f.get_den();
33}
34
35
14#endif 36#endif
diff --git a/native/interface/sched.i b/native/interface/sched.i
index d0809b6..238f36e 100644
--- a/native/interface/sched.i
+++ b/native/interface/sched.i
@@ -13,6 +13,7 @@
13#include "edf/load.h" 13#include "edf/load.h"
14#include "edf/gedf.h" 14#include "edf/gedf.h"
15#include "edf/gel_pl.h" 15#include "edf/gel_pl.h"
16#include "edf/qpa.h"
16#include "sharedres.h" 17#include "sharedres.h"
17%} 18%}
18 19
@@ -41,3 +42,4 @@
41#include "edf/load.h" 42#include "edf/load.h"
42#include "edf/gedf.h" 43#include "edf/gedf.h"
43#include "edf/gel_pl.h" 44#include "edf/gel_pl.h"
45#include "edf/qpa.h"
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}