aboutsummaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2012-08-07 14:28:29 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-02-12 06:49:40 -0500
commit4d45e06a55ad463247edd949e6d0c98a69fcf332 (patch)
treee522d252342ca658397323301af1a77c03e515d5 /native
parenta4ff45bfbaef292ee1106b759c7ae80213b03cd4 (diff)
Add DPCP and DFLP linear program generation
These files implement the generation and evaluation of linear programs that bound maximum s-aware pi-blocking under the DPCP and the DFLP.
Diffstat (limited to 'native')
-rw-r--r--native/Makefile5
-rw-r--r--native/include/linprog/model.h7
-rw-r--r--native/include/lp_common.h159
-rw-r--r--native/src/blocking/linprog/lp_common.cpp177
-rw-r--r--native/src/blocking/linprog/lp_dflp.cpp152
-rw-r--r--native/src/blocking/linprog/lp_dpcp.cpp374
6 files changed, 871 insertions, 3 deletions
diff --git a/native/Makefile b/native/Makefile
index 71a6835..c2a08e5 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -81,7 +81,7 @@ LDFLAGS = $(LIBS)
81SWIGFLAGS = -python -c++ -outdir . -includeall -Iinclude 81SWIGFLAGS = -python -c++ -outdir . -includeall -Iinclude
82 82
83vpath %.cc interface 83vpath %.cc interface
84vpath %.cpp src src/edf src/blocking src/linprog 84vpath %.cpp src src/edf src/blocking src/blocking/linprog src/linprog
85 85
86# #### Common C++ source files #### 86# #### Common C++ source files ####
87 87
@@ -100,7 +100,8 @@ ALL = testmain _sched.so _locking.so _sim.so
100 100
101# Compile LP-based code only if we have a solver. 101# Compile LP-based code only if we have a solver.
102ifneq ($(CPLEX),) 102ifneq ($(CPLEX),)
103LP_OBJ = cplex.o io.o 103LP_OBJ = lp_common.o lp_dflp.o lp_dpcp.o
104LP_OBJ += cplex.o io.o
104endif 105endif
105 106
106.PHONY: all clean 107.PHONY: all clean
diff --git a/native/include/linprog/model.h b/native/include/linprog/model.h
index 27729dd..22f96e4 100644
--- a/native/include/linprog/model.h
+++ b/native/include/linprog/model.h
@@ -53,7 +53,7 @@ class LinearProgram
53 Constraints inequalities; 53 Constraints inequalities;
54 54
55public: 55public:
56 LinearProgram() : objective(0) {}; 56 LinearProgram() : objective(new LinearExpression()) {};
57 57
58 ~LinearProgram() 58 ~LinearProgram()
59 { 59 {
@@ -91,6 +91,11 @@ public:
91 return objective; 91 return objective;
92 } 92 }
93 93
94 LinearExpression *get_objective()
95 {
96 return objective;
97 }
98
94 const Constraints& get_equalities() const 99 const Constraints& get_equalities() const
95 { 100 {
96 return equalities; 101 return equalities;
diff --git a/native/include/lp_common.h b/native/include/lp_common.h
new file mode 100644
index 0000000..06519d1
--- /dev/null
+++ b/native/include/lp_common.h
@@ -0,0 +1,159 @@
1#ifndef LP_COMMON_H_
2#define LP_COMMON_H_
3
4#include <stdint.h>
5
6#include "sharedres_types.h"
7#include "blocking.h"
8
9#include "stl-helper.h"
10#include "stl-hashmap.h"
11
12#include "linprog/model.h"
13#include "linprog/cplex.h"
14
15enum blocking_type
16{
17 BLOCKING_DIRECT,
18 BLOCKING_INDIRECT,
19 BLOCKING_PREEMPT
20};
21
22class VarMapper {
23private:
24 hashmap<uint64_t, unsigned int> map;
25
26 void insert(uint64_t key)
27 {
28 unsigned int idx = map.size();
29 map[key] = idx;
30 }
31
32 static uint64_t encode_request(uint64_t task_id, uint64_t res_id, uint64_t req_id,
33 uint64_t blocking_type)
34 {
35 assert(task_id < (1 << 30));
36 assert(res_id < (1 << 10));
37 assert(req_id < (1 << 22));
38 assert(blocking_type < (1 << 2));
39
40 return (blocking_type << 62) | (task_id << 30) | (req_id << 10) | res_id;
41 }
42
43public:
44
45 unsigned int lookup(unsigned int task_id, unsigned int res_id, unsigned int req_id,
46 blocking_type type)
47 {
48 uint64_t key = encode_request(task_id, res_id, req_id, type);
49 if (!map.count(key))
50 insert(key);
51 return map[key];
52 }
53
54 void clear()
55 {
56 map.clear();
57 }
58
59 unsigned int get_num_vars()
60 {
61 return map.size();
62 }
63};
64
65void set_blocking_objective(
66 VarMapper& vars,
67 const ResourceSharingInfo& info, const ResourceLocality&,
68 const TaskInfo& ti,
69 LinearProgram& lp,
70 LinearExpression *local_obj = 0,
71 LinearExpression *remote_obj = 0);
72
73void add_mutex_constraints(VarMapper& vars,
74 const ResourceSharingInfo& info,
75 const TaskInfo& ti, LinearProgram& lp);
76
77void add_topology_constraints(VarMapper& vars,
78 const ResourceSharingInfo& info, const ResourceLocality& locality,
79 const TaskInfo& ti, LinearProgram& lp);
80
81void add_local_lower_priority_constraints(
82 VarMapper& vars,
83 const ResourceSharingInfo& info,
84 const ResourceLocality& locality,
85 const TaskInfo& ti,
86 LinearProgram& lp);
87
88// A generic for loop that iterates 'request_index_variable' from 0 to the
89// maximum number of requests issued by task tx while ti is pending. 'tx_request'
90// should be of type RequestBound&.
91#define foreach_request_instance(tx_request, task_ti, request_index_variable) \
92 for ( \
93 unsigned int __max_num_requests = (tx_request).get_max_num_requests((task_ti).get_response()), \
94 request_index_variable = 0; \
95 request_index_variable < __max_num_requests; \
96 request_index_variable++ \
97 )
98
99// iterate over each task using 'task_iter', skipping 'excluded_task'
100#define foreach_task_except(tasks, excluded_task, task_iter) \
101 foreach(tasks, task_iter) \
102 if (task_iter->get_id() != (excluded_task).get_id())
103
104// iterate only over tasks with equal or lower priority
105#define foreach_lowereq_priority_task(tasks, reference_task, task_iter) \
106 foreach(tasks, task_iter) \
107 if (task_iter->get_priority() >= (reference_task).get_priority())
108
109// iterate only over tasks with equal or lower priority, excluding 'reference_task'
110#define foreach_lowereq_priority_task_except(tasks, reference_task, task_iter) \
111 foreach(tasks, task_iter) \
112 if (task_iter->get_priority() >= (reference_task).get_priority() && \
113 task_iter->get_id() != (reference_task).get_id())
114
115
116// iterate only over tasks with higher priority
117#define foreach_higher_priority_task(tasks, reference_task, task_iter) \
118 foreach(tasks, task_iter) \
119 if (task_iter->get_priority() < (reference_task).get_priority())
120
121// iterate over requests not in the local cluster
122#define foreach_remote_request(requests, locality, task_ti, request_iter) \
123 foreach(requests, request_iter) \
124 if ((locality)[request_iter->get_resource_id()] \
125 != (int) (task_ti).get_cluster())
126
127// iterate over requests for resources in a specific cluster
128#define foreach_request_in_cluster(requests, locality, cluster, request_iter) \
129 foreach(requests, request_iter) \
130 if ((locality)[request_iter->get_resource_id()] \
131 == (int) (cluster))
132
133// iterate over each task using 'task_iter', skipping tasks in the same
134// cluster as 'local_task'
135#define foreach_remote_task(tasks, local_task, task_iter) \
136 foreach(tasks, task_iter) \
137 if (task_iter->get_cluster() != (local_task).get_cluster())
138
139#define foreach_local_task(tasks, local_task, task_iter) \
140 foreach(tasks, task_iter) \
141 if (task_iter->get_cluster() == (local_task).get_cluster())
142
143#define foreach_local_task_except(tasks, local_task, task_iter) \
144 foreach(tasks, task_iter) \
145 if (task_iter->get_cluster() == (local_task).get_cluster() && \
146 task_iter->get_id() != (local_task).get_id())
147
148#define foreach_local_lowereq_priority_task_except(tasks, local_task, task_iter) \
149 foreach(tasks, task_iter) \
150 if (task_iter->get_cluster() == (local_task).get_cluster() && \
151 task_iter->get_id() != (local_task).get_id() && \
152 task_iter->get_priority() >= (local_task).get_priority())
153
154#define foreach_request_for(requests, res_id, req_iter) \
155 foreach(requests, req_iter) \
156 if (req_iter->get_resource_id() == res_id)
157
158
159#endif /* LP_COMMON_H_ */
diff --git a/native/src/blocking/linprog/lp_common.cpp b/native/src/blocking/linprog/lp_common.cpp
new file mode 100644
index 0000000..808ff28
--- /dev/null
+++ b/native/src/blocking/linprog/lp_common.cpp
@@ -0,0 +1,177 @@
1#include "lp_common.h"
2
3// LP-based analysis of semaphore protocols.
4// Based on the paper:
5// B. Brandenburg, "Improved Analysis and Evaluation of Real-Time Semaphore
6// Protocols for P-FP Scheduling", Proceedings of the 19th IEEE Real-Time and
7// Embedded Technology and Applications Symposium (RTAS 2013), April 2013.
8
9void set_blocking_objective(
10 VarMapper& vars,
11 const ResourceSharingInfo& info, const ResourceLocality& locality,
12 const TaskInfo& ti,
13 LinearProgram& lp,
14 LinearExpression *local_obj,
15 LinearExpression *remote_obj)
16{
17 LinearExpression *obj;
18
19 obj = lp.get_objective();
20
21 foreach_task_except(info.get_tasks(), ti, tx)
22 {
23 unsigned int t = tx->get_id();
24 foreach(tx->get_requests(), request)
25 {
26 unsigned int q = request->get_resource_id();
27 bool local = locality[q] == (int) ti.get_cluster();
28 double length;
29
30 // Sanity check topology info in debug mode.
31 assert(locality[q] != NO_CPU);
32
33 length = request->get_request_length();
34
35 foreach_request_instance(*request, ti, v)
36 {
37 unsigned int var_id;
38
39 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
40 obj->add_term(length, var_id);
41 if (local && local_obj)
42 local_obj->add_term(length, var_id);
43 else if (!local && remote_obj)
44 remote_obj->add_term(length, var_id);
45
46 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
47 obj->add_term(length, var_id);
48 if (local && local_obj)
49 local_obj->add_term(length, var_id);
50 else if (!local && remote_obj)
51 remote_obj->add_term(length, var_id);
52
53 var_id = vars.lookup(t, q, v, BLOCKING_PREEMPT);
54 obj->add_term(length, var_id);
55 if (local && local_obj)
56 local_obj->add_term(length, var_id);
57 else if (!local && remote_obj)
58 remote_obj->add_term(length, var_id);
59 }
60 }
61 }
62}
63
64// Constraint 1 in [Brandenburg 2013]
65void add_mutex_constraints(
66 VarMapper& vars,
67 const ResourceSharingInfo& info,
68 const TaskInfo& ti,
69 LinearProgram& lp)
70{
71
72 foreach_task_except(info.get_tasks(), ti, tx)
73 {
74 unsigned int t = tx->get_id();
75 foreach(tx->get_requests(), request)
76 {
77 unsigned int q = request->get_resource_id();
78 foreach_request_instance(*request, ti, v)
79 {
80 LinearExpression *exp = new LinearExpression();
81 unsigned int var_id;
82
83 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
84 exp->add_var(var_id);
85
86 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
87 exp->add_var(var_id);
88
89 var_id = vars.lookup(t, q, v, BLOCKING_PREEMPT);
90 exp->add_var(var_id);
91
92 lp.add_inequality(exp, 1);
93 }
94 }
95 }
96}
97
98// Constraint 2 in [Brandenburg 2013]
99void add_topology_constraints(
100 VarMapper& vars,
101 const ResourceSharingInfo& info,
102 const ResourceLocality& locality,
103 const TaskInfo& ti,
104 LinearProgram& lp)
105{
106 LinearExpression *exp = new LinearExpression();
107
108 foreach_task_except(info.get_tasks(), ti, tx)
109 {
110 unsigned int t = tx->get_id();
111 foreach_remote_request(tx->get_requests(), locality, ti, request)
112 {
113 unsigned int q = request->get_resource_id();
114 foreach_request_instance(*request, ti, v)
115 {
116 unsigned int var_id;
117 var_id = vars.lookup(t, q, v, BLOCKING_PREEMPT);
118 exp->add_var(var_id);
119 }
120 }
121 }
122 lp.add_equality(exp, 0);
123}
124
125static unsigned int max_num_arrivals_remote(
126 const ResourceLocality& locality,
127 const TaskInfo& ti)
128{
129 // initialize to 1 to account for job release
130 unsigned int count = 1;
131
132 // count how often resources on remote cores are accessed
133 foreach(ti.get_requests(), req)
134 if (locality[req->get_resource_id()] != (int) ti.get_cluster())
135 count += req->get_num_requests();
136
137 return count;
138}
139
140
141// Constraint 3 in [Brandenburg 2013]
142// One priority-boosting-related preemption per local task
143// each time that Ji arrives (is released or resumed)
144void add_local_lower_priority_constraints(
145 VarMapper& vars,
146 const ResourceSharingInfo& info,
147 const ResourceLocality& locality,
148 const TaskInfo& ti,
149 LinearProgram& lp)
150{
151 unsigned int num_arrivals = max_num_arrivals_remote(locality, ti);
152
153 foreach_local_lowereq_priority_task_except(info.get_tasks(), ti, tx)
154 {
155 LinearExpression *exp = new LinearExpression();
156
157 unsigned int t = tx->get_id();
158 foreach(tx->get_requests(), request)
159 {
160 unsigned int q = request->get_resource_id();
161
162 // is it a resource local to Ti?
163 if (locality[q] == (int) ti.get_cluster())
164 {
165 foreach_request_instance(*request, ti, v)
166 {
167 unsigned int var_id;
168 var_id = vars.lookup(t, q, v,
169 BLOCKING_PREEMPT);
170 exp->add_var(var_id);
171 }
172 }
173 }
174 lp.add_equality(exp, num_arrivals);
175 }
176}
177
diff --git a/native/src/blocking/linprog/lp_dflp.cpp b/native/src/blocking/linprog/lp_dflp.cpp
new file mode 100644
index 0000000..6b416be
--- /dev/null
+++ b/native/src/blocking/linprog/lp_dflp.cpp
@@ -0,0 +1,152 @@
1#include <iostream>
2
3#include "lp_common.h"
4#include "stl-hashmap.h"
5
6// Constraint 5
7// only one blocking request each time a job of T_i
8// issues a request, with regard to each cluster and each task.
9static void add_fifo_cluster_constraints(
10 VarMapper& vars,
11 const ResourceSharingInfo& info,
12 const ResourceLocality& locality,
13 const TaskInfo& ti,
14 LinearProgram& lp)
15{
16 hashmap<unsigned int, unsigned int> per_cluster_counts;
17
18 foreach(ti.get_requests(), req)
19 per_cluster_counts[locality[req->get_resource_id()]] += req->get_num_requests();
20
21 foreach_task_except(info.get_tasks(), ti, tx)
22 {
23 unsigned int t = tx->get_id();
24
25 // one constraint for each cluster accessed by tx
26 hashmap<unsigned int, LinearExpression *> constraints;
27
28 foreach(tx->get_requests(), request)
29 {
30 unsigned int q = request->get_resource_id();
31 unsigned int c = locality[q];
32 LinearExpression *exp;
33
34 if (constraints.find(c) == constraints.end())
35 constraints[c] = new LinearExpression();
36
37 exp = constraints[c];
38
39 foreach_request_instance(*request, ti, v)
40 {
41 unsigned int var_id;
42 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
43 exp->add_var(var_id);
44 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
45 exp->add_var(var_id);
46 }
47 }
48
49 // add each per-cluster constraint
50 foreach(constraints, it)
51 lp.add_inequality(it->second, per_cluster_counts[it->first]);
52 }
53}
54
55// Constraint 4
56// only one *directly* blocking request each time a job of T_i
57// issues a request, with regard to each resource and each task.
58static void add_fifo_resource_constraints(
59 VarMapper& vars,
60 const ResourceSharingInfo& info,
61 const ResourceLocality& locality,
62 const TaskInfo& ti,
63 LinearProgram& lp)
64{
65 hashmap<unsigned int, unsigned int> per_resource_counts;
66
67 foreach(ti.get_requests(), req)
68 per_resource_counts[req->get_resource_id()] = req->get_num_requests();
69
70 foreach_task_except(info.get_tasks(), ti, tx)
71 {
72 unsigned int t = tx->get_id();
73 //for all requests accessed by tx
74 foreach(tx->get_requests(), request)
75 {
76 unsigned int q = request->get_resource_id();
77 LinearExpression *exp = new LinearExpression();
78
79 foreach_request_instance(*request, ti, v)
80 {
81 unsigned int var_id;
82 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
83 exp->add_var(var_id);
84 }
85
86 lp.add_inequality(exp, per_resource_counts[q]);
87 }
88 }
89}
90
91void add_dflp_constraints(
92 VarMapper& vars,
93 const ResourceSharingInfo& info,
94 const ResourceLocality& locality,
95 const TaskInfo& ti,
96 LinearProgram& lp)
97{
98 // Constraint 1
99 add_mutex_constraints(vars, info, ti, lp);
100 // Constraint 2
101 add_topology_constraints(vars, info, locality, ti, lp);
102 // Constraint 3
103 add_local_lower_priority_constraints(vars, info, locality, ti, lp);
104 // Constraint 4
105 add_fifo_resource_constraints(vars, info, locality, ti, lp);
106 // Constraint 5
107 add_fifo_cluster_constraints(vars, info, locality, ti, lp);
108}
109
110static void apply_dflp_bounds_for_task(
111 unsigned int i,
112 BlockingBounds& bounds,
113 const ResourceSharingInfo& info,
114 const ResourceLocality& locality)
115{
116 LinearProgram lp;
117 VarMapper vars;
118 const TaskInfo& ti = info.get_tasks()[i];
119 LinearExpression *local_obj = new LinearExpression();
120
121 set_blocking_objective(vars, info, locality, ti, lp, local_obj);
122
123 add_dflp_constraints(vars, info, locality, ti, lp);
124
125 Solution *sol = cplex_solve(lp, vars.get_num_vars());
126
127 assert(sol != NULL);
128
129 Interference total, remote, local;
130
131 total.total_length = sol->evaluate(*lp.get_objective());
132 local.total_length = sol->evaluate(*local_obj);
133 remote.total_length = total.total_length - local.total_length;
134
135 bounds[i] = total;
136 bounds.set_remote_blocking(i, remote);
137 bounds.set_local_blocking(i, local);
138
139 delete local_obj;
140 delete sol;
141}
142
143BlockingBounds* lp_dflp_bounds(const ResourceSharingInfo& info,
144 const ResourceLocality& locality)
145{
146 BlockingBounds *results = new BlockingBounds(info);
147
148 for (unsigned int i = 0; i < info.get_tasks().size(); i++)
149 apply_dflp_bounds_for_task(i, *results, info, locality);
150
151 return results;
152}
diff --git a/native/src/blocking/linprog/lp_dpcp.cpp b/native/src/blocking/linprog/lp_dpcp.cpp
new file mode 100644
index 0000000..fbd0cd5
--- /dev/null
+++ b/native/src/blocking/linprog/lp_dpcp.cpp
@@ -0,0 +1,374 @@
1#include <iostream>
2#include <set>
3#include <algorithm>
4
5#include "lp_common.h"
6#include "blocking.h"
7#include "stl-hashmap.h"
8
9#define NO_WAIT_TIME_BOUND (-1)
10
11class MaxWaitTimes
12{
13private:
14 // mapping of resource id to previously computed maximum wait time
15 hashmap<unsigned int, long> max_wait_time;
16
17 // parameters for wait time calculation
18 const ResourceSharingInfo& info;
19 const ResourceLocality& locality;
20 const TaskInfo& ti;
21 const PriorityCeilings& prio_ceiling;
22
23 void bound_wait_time(unsigned int res_id);
24
25public:
26 MaxWaitTimes(const ResourceSharingInfo& _info, const ResourceLocality& _loc,
27 const TaskInfo& _ti, const std::vector<unsigned int>& _pc)
28 : info(_info), locality(_loc), ti(_ti), prio_ceiling(_pc)
29 {};
30
31 long operator[](unsigned int res_id)
32 {
33 if (!max_wait_time.count(res_id))
34 bound_wait_time(res_id);
35 return max_wait_time[res_id];
36 }
37};
38
39void MaxWaitTimes::bound_wait_time(unsigned int res_id)
40{
41 unsigned int own_length = 0, delay_by_lower = 0, delay_by_higher = 0;
42
43 unsigned int c = locality[res_id];
44
45 // find ti's maximum request length
46 foreach(ti.get_requests(), ti_req)
47 if (ti_req->get_resource_id() == res_id)
48 own_length = std::max(own_length,
49 ti_req->get_request_length());
50
51 // find maximum lower-priority request length that blocks
52 foreach_lowereq_priority_task(info.get_tasks(), ti, tx)
53 {
54 // on the cluster in which res_id is located
55 foreach_request_in_cluster(tx->get_requests(), locality,
56 c, request)
57 {
58 unsigned int q = request->get_resource_id();
59 // can block?
60 if (prio_ceiling[q] <= ti.get_priority())
61 delay_by_lower = std::max(delay_by_lower,
62 request->get_request_length());
63 }
64 }
65
66 // response-time analysis to find final maximum wait time
67
68 unsigned long next_estimate = own_length + delay_by_lower;
69 unsigned long estimate = 0;
70
71 while (next_estimate <= ti.get_response() && next_estimate != estimate)
72 {
73 delay_by_higher = 0;
74 estimate = next_estimate;
75
76 foreach_higher_priority_task(info.get_tasks(), ti, tx)
77 {
78 foreach_request_in_cluster(tx->get_requests(), locality,
79 c, request)
80 {
81 unsigned int nreqs = request->get_max_num_requests(estimate);
82 unsigned long rlen = request->get_request_length();
83
84 delay_by_higher += nreqs * rlen;
85 }
86 }
87
88 next_estimate = own_length + delay_by_lower + delay_by_higher;
89 }
90
91 if (estimate <= ti.get_response())
92 max_wait_time[res_id] = estimate;
93 else
94 max_wait_time[res_id] = NO_WAIT_TIME_BOUND;
95}
96
97// Constraint 8
98// Ti's maximum wait times limit the maximum number of times
99// that higher-priority tasks can directly and indirectly delay Ti.
100static void add_max_wait_time_constraints(
101 VarMapper& vars,
102 const ResourceSharingInfo& info,
103 const ResourceLocality& locality,
104 const TaskInfo& ti,
105 const PriorityCeilings& prio_ceilings,
106 LinearProgram& lp)
107{
108 MaxWaitTimes max_wait_time = MaxWaitTimes(info, locality, ti, prio_ceilings);
109
110 foreach_higher_priority_task(info.get_tasks(), ti, tx)
111 {
112 unsigned int t = tx->get_id();
113 foreach(tx->get_requests(), request)
114 {
115 unsigned int q = request->get_resource_id();
116 unsigned int c = locality[q];
117
118 unsigned int max_num_reqs = 0;
119 bool bounded = true;
120
121 // Figure out how often and how long ti is waiting in
122 // total in cluster c. To do so, look at each of ti's
123 // requests for a resource located in cluster c.
124
125 foreach_request_in_cluster(ti.get_requests(), locality,
126 c, ti_req)
127 {
128 unsigned int y = ti_req->get_resource_id();
129 long wait = max_wait_time[y];
130
131 if (wait == NO_WAIT_TIME_BOUND)
132 {
133 bounded = false;
134 break;
135 }
136
137 unsigned int nreqs = request->get_max_num_requests(wait);
138 max_num_reqs += nreqs * ti_req->get_num_requests();
139 }
140
141
142 if (bounded)
143 {
144 LinearExpression *exp = new LinearExpression();
145 foreach_request_instance(*request, ti, v)
146 {
147 unsigned int var_id;
148 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
149 exp->add_var(var_id);
150 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
151 exp->add_var(var_id);
152 }
153 lp.add_inequality(exp, max_num_reqs);
154 }
155 }
156 }
157}
158
159// Substitute for Constraint 8
160// no direct or indirect blocking due to resources
161// on clusters that ti doesn't even access.
162static void add_independent_cluster_constraints(
163 VarMapper& vars,
164 const ResourceSharingInfo& info,
165 const ResourceLocality& locality,
166 const TaskInfo& ti,
167 LinearProgram& lp)
168{
169
170 //find all clusters that ti accesses
171 std::set<int> accessed_clusters;
172 foreach(ti.get_requests(), req)
173 {
174 int c = locality[req->get_resource_id()];
175 accessed_clusters.insert(c);
176 }
177
178 LinearExpression *exp = new LinearExpression();
179
180 foreach_task_except(info.get_tasks(), ti, tx)
181 {
182 unsigned int t = tx->get_id();
183 foreach(tx->get_requests(), request)
184 {
185 unsigned int q = request->get_resource_id();
186 if (accessed_clusters.count(locality[q]) == 0)
187 {
188 foreach_request_instance(*request, ti, v)
189 {
190 unsigned int var_id;
191 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
192 exp->add_var(var_id);
193 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
194 exp->add_var(var_id);
195 }
196 }
197 }
198 }
199
200 lp.add_equality(exp, 0);
201}
202
203// Constraint 6
204static void add_conflict_set_constraints(
205 VarMapper& vars,
206 const ResourceSharingInfo& info,
207 const ResourceLocality& locality,
208 const TaskInfo& ti,
209 const PriorityCeilings& prio_ceiling,
210 LinearProgram& lp)
211{
212 LinearExpression *exp = new LinearExpression();
213
214 foreach_task_except(info.get_tasks(), ti, tx)
215 {
216 unsigned int t = tx->get_id();
217 foreach(tx->get_requests(), request)
218 {
219 unsigned int q = request->get_resource_id();
220 if (prio_ceiling[q] > ti.get_priority())
221 {
222 // smaller ID <=> higher priority
223 // Priority ceiling is lower than ti's priority,
224 // so it cannot block ti.
225 foreach_request_instance(*request, ti, v)
226 {
227 unsigned int var_id;
228 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
229 exp->add_var(var_id);
230 var_id = vars.lookup(t, q, v, BLOCKING_INDIRECT);
231 exp->add_var(var_id);
232 }
233 }
234 }
235 }
236
237 // force blocking fractions to zero
238 lp.add_equality(exp, 0);
239}
240
241// Constraint 7
242// Each request can be directly delayed at most
243// once by a lower-priority task.
244static void add_atmostonce_lower_prio_constraints(
245 VarMapper& vars,
246 const ResourceSharingInfo& info,
247 const ResourceLocality& locality,
248 const TaskInfo& ti,
249 const PriorityCeilings& priority_ceiling,
250 LinearProgram& lp)
251{
252 // Count the number of times that each cluster is accessed by ti.
253 hashmap<unsigned int, unsigned int> per_cluster_counts;
254 foreach(ti.get_requests(), req)
255 per_cluster_counts[locality[req->get_resource_id()]] += req->get_num_requests();
256
257 // build one constraint for each cluster
258 hashmap<unsigned int, LinearExpression *> constraints;
259
260 foreach_lowereq_priority_task_except(info.get_tasks(), ti, tx)
261 {
262 unsigned int t = tx->get_id();
263
264 foreach(tx->get_requests(), request)
265 {
266 unsigned int q = request->get_resource_id();
267
268 if (priority_ceiling[q] <= ti.get_priority())
269 {
270 // yes, can block us
271 unsigned int c = locality[q];
272 LinearExpression *exp;
273
274 if (constraints.find(c) == constraints.end())
275 constraints[c] = new LinearExpression();
276
277 exp = constraints[c];
278
279 foreach_request_instance(*request, ti, v)
280 {
281 unsigned int var_id;
282 var_id = vars.lookup(t, q, v, BLOCKING_DIRECT);
283 exp->add_var(var_id);
284 }
285 }
286 }
287 }
288
289 // add each per-cluster constraint
290 foreach(constraints, it)
291 lp.add_inequality(it->second, per_cluster_counts[it->first]);
292}
293
294void add_dpcp_constraints(
295 VarMapper& vars,
296 const ResourceSharingInfo& info,
297 const ResourceLocality& locality,
298 const TaskInfo& ti,
299 const PriorityCeilings& prio_ceilings,
300 LinearProgram& lp,
301 bool use_rta)
302{
303 // Constraint 1
304 add_mutex_constraints(vars, info, ti, lp);
305 // Constraint 2
306 add_topology_constraints(vars, info, locality, ti, lp);
307 // Constraint 3
308 add_local_lower_priority_constraints(vars, info, locality, ti, lp);
309 // Constraint 7
310 add_atmostonce_lower_prio_constraints(vars, info, locality,
311 ti, prio_ceilings, lp);
312 // Constraint 6
313 add_conflict_set_constraints(vars, info, locality, ti,
314 prio_ceilings, lp);
315
316 if (use_rta)
317 // Constraint 8
318 add_max_wait_time_constraints(vars, info, locality, ti, prio_ceilings,
319 lp);
320 else
321 add_independent_cluster_constraints(vars, info, locality, ti, lp);
322}
323
324static void apply_dpcp_bounds_for_task(
325 unsigned int i,
326 BlockingBounds& bounds,
327 const ResourceSharingInfo& info,
328 const ResourceLocality& locality,
329 const PriorityCeilings& prio_ceilings,
330 bool use_rta)
331{
332 LinearProgram lp;
333 VarMapper vars;
334 const TaskInfo& ti = info.get_tasks()[i];
335 LinearExpression *local_obj = new LinearExpression();
336
337 set_blocking_objective(vars, info, locality, ti, lp, local_obj);
338
339 add_dpcp_constraints(vars, info, locality, ti,
340 prio_ceilings, lp, use_rta);
341
342 Solution *sol = cplex_solve(lp, vars.get_num_vars());
343
344 assert(sol != NULL);
345
346 Interference total, remote, local;
347
348 total.total_length = sol->evaluate(*lp.get_objective());
349 local.total_length = sol->evaluate(*local_obj);
350 remote.total_length = total.total_length - local.total_length;
351
352 bounds[i] = total;
353 bounds.set_remote_blocking(i, remote);
354 bounds.set_local_blocking(i, local);
355
356 delete local_obj;
357 delete sol;
358}
359
360
361BlockingBounds* lp_dpcp_bounds(const ResourceSharingInfo& info,
362 const ResourceLocality& locality,
363 bool use_rta)
364{
365 BlockingBounds* results = new BlockingBounds(info);
366
367 PriorityCeilings prio_ceilings = get_priority_ceilings(info);
368
369 for (unsigned int i = 0; i < info.get_tasks().size(); i++)
370 apply_dpcp_bounds_for_task(i, *results, info,
371 locality, prio_ceilings, use_rta);
372
373 return results;
374}