diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2013-08-15 02:47:03 -0400 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2013-12-13 02:39:06 -0500 |
commit | b98848e9570d00ded81d5b82672003a50c3e4c99 (patch) | |
tree | 29de1ab9085e8ba6f80e83295348b819bad7b9b0 | |
parent | db61527e79699990bbad8a3dff5ae20af8227591 (diff) |
Add holistic MSRP analysis (with PCP/SRP for local resources)
This patch adds holistic analysis of the MSRP, which combines the PCP/SRP
for local resources and task-fair mutex spin locks for global resources.
This is added as its own analysis (rather than patching the task-fair mutex
code directly) because
- the MSRP only applies to partitioned scheduling, and
- to not break existing code that does not expect special treatment of local resources.
Simple tests included. Adds some convenience code to Interference and BlockingBounds.
-rw-r--r-- | native/Makefile | 1 | ||||
-rw-r--r-- | native/include/blocking.h | 3 | ||||
-rw-r--r-- | native/include/sharedres.h | 4 | ||||
-rw-r--r-- | native/include/sharedres_types.h | 7 | ||||
-rw-r--r-- | native/interface/locking.i | 1 | ||||
-rw-r--r-- | native/src/blocking/msrp-holistic.cpp | 90 | ||||
-rw-r--r-- | tests/locking.py | 46 |
7 files changed, 152 insertions, 0 deletions
diff --git a/native/Makefile b/native/Makefile index 54c75d8..965f049 100644 --- a/native/Makefile +++ b/native/Makefile | |||
@@ -111,6 +111,7 @@ SYNC_OBJ = sharedres.o dpcp.o mpcp.o | |||
111 | SYNC_OBJ += fmlp_plus.o global-fmlp.o | 111 | SYNC_OBJ += fmlp_plus.o global-fmlp.o |
112 | SYNC_OBJ += global-omlp.o part-omlp.o clust-omlp.o | 112 | SYNC_OBJ += global-omlp.o part-omlp.o clust-omlp.o |
113 | SYNC_OBJ += rw-phase-fair.o rw-task-fair.o | 113 | SYNC_OBJ += rw-phase-fair.o rw-task-fair.o |
114 | SYNC_OBJ += msrp-holistic.o | ||
114 | 115 | ||
115 | # #### Targets #### | 116 | # #### Targets #### |
116 | 117 | ||
diff --git a/native/include/blocking.h b/native/include/blocking.h index a4e48f5..cbb4d15 100644 --- a/native/include/blocking.h +++ b/native/include/blocking.h | |||
@@ -102,6 +102,9 @@ ResourceSharingInfo extract_local_resources( | |||
102 | ResourceSharingInfo extract_global_resources( | 102 | ResourceSharingInfo extract_global_resources( |
103 | const ResourceSharingInfo& info, | 103 | const ResourceSharingInfo& info, |
104 | const ResourceSet& locals); | 104 | const ResourceSet& locals); |
105 | |||
106 | BlockingBounds pcp_blocking(const ResourceSharingInfo& info); | ||
107 | |||
105 | extern const unsigned int UNLIMITED; | 108 | extern const unsigned int UNLIMITED; |
106 | 109 | ||
107 | #endif | 110 | #endif |
diff --git a/native/include/sharedres.h b/native/include/sharedres.h index 7765fd8..437176b 100644 --- a/native/include/sharedres.h +++ b/native/include/sharedres.h | |||
@@ -18,6 +18,10 @@ BlockingBounds* phase_fair_rw_bounds(const ResourceSharingInfo& info, | |||
18 | unsigned int procs_per_cluster, | 18 | unsigned int procs_per_cluster, |
19 | int dedicated_irq = NO_CPU); | 19 | int dedicated_irq = NO_CPU); |
20 | 20 | ||
21 | BlockingBounds* msrp_bounds_holistic( | ||
22 | const ResourceSharingInfo& info, | ||
23 | int dedicated_irq = NO_CPU); | ||
24 | |||
21 | // s-oblivious protocols | 25 | // s-oblivious protocols |
22 | 26 | ||
23 | BlockingBounds* global_omlp_bounds(const ResourceSharingInfo& info, | 27 | BlockingBounds* global_omlp_bounds(const ResourceSharingInfo& info, |
diff --git a/native/include/sharedres_types.h b/native/include/sharedres_types.h index fbe8f72..800659a 100644 --- a/native/include/sharedres_types.h +++ b/native/include/sharedres_types.h | |||
@@ -240,6 +240,7 @@ struct Interference | |||
240 | unsigned long total_length; | 240 | unsigned long total_length; |
241 | 241 | ||
242 | Interference() : count(0), total_length(0) {} | 242 | Interference() : count(0), total_length(0) {} |
243 | Interference(unsigned int length) : count(1), total_length(length) {} | ||
243 | 244 | ||
244 | Interference& operator+=(const Interference& other) | 245 | Interference& operator+=(const Interference& other) |
245 | { | 246 | { |
@@ -311,6 +312,12 @@ public: | |||
311 | return request_span[idx]; | 312 | return request_span[idx]; |
312 | } | 313 | } |
313 | 314 | ||
315 | void raise_blocking_length(unsigned idx, const Interference& val) | ||
316 | { | ||
317 | assert( idx < size() ); | ||
318 | blocking[idx] = std::max(blocking[idx], val); | ||
319 | } | ||
320 | |||
314 | size_t size() const | 321 | size_t size() const |
315 | { | 322 | { |
316 | return blocking.size(); | 323 | return blocking.size(); |
diff --git a/native/interface/locking.i b/native/interface/locking.i index 208fb74..5f4e75d 100644 --- a/native/interface/locking.i +++ b/native/interface/locking.i | |||
@@ -7,6 +7,7 @@ | |||
7 | %newobject task_fair_mutex_bounds; | 7 | %newobject task_fair_mutex_bounds; |
8 | %newobject task_fair_rw_bounds; | 8 | %newobject task_fair_rw_bounds; |
9 | %newobject phase_fair_rw_bounds; | 9 | %newobject phase_fair_rw_bounds; |
10 | %newobject msrp_bounds_holistic; | ||
10 | 11 | ||
11 | %newobject global_omlp_bounds; | 12 | %newobject global_omlp_bounds; |
12 | %newobject global_fmlp_bounds; | 13 | %newobject global_fmlp_bounds; |
diff --git a/native/src/blocking/msrp-holistic.cpp b/native/src/blocking/msrp-holistic.cpp new file mode 100644 index 0000000..f9b4185 --- /dev/null +++ b/native/src/blocking/msrp-holistic.cpp | |||
@@ -0,0 +1,90 @@ | |||
1 | #include "stl-hashmap.h" | ||
2 | |||
3 | #include "sharedres.h" | ||
4 | #include "blocking.h" | ||
5 | |||
6 | |||
7 | // Analysis of the MSRP: PCP/SRP for local resources, task-fair mutex | ||
8 | // spin locks for global resources | ||
9 | // Applies only to partitioned scheduling. | ||
10 | BlockingBounds* msrp_bounds_holistic( | ||
11 | const ResourceSharingInfo& info, | ||
12 | int dedicated_irq) | ||
13 | { | ||
14 | ResourceSet locals = get_local_resources(info); | ||
15 | ResourceSharingInfo linfo = extract_local_resources(info, locals); | ||
16 | ResourceSharingInfo ginfo = extract_global_resources(info, locals); | ||
17 | |||
18 | BlockingBounds pcp = pcp_blocking(linfo); | ||
19 | |||
20 | BlockingBounds* results = task_fair_mutex_bounds(ginfo, 1, dedicated_irq); | ||
21 | |||
22 | // merge the two analysis results | ||
23 | for (unsigned int i = 0; i < results->size(); i++) | ||
24 | { | ||
25 | unsigned int b_pcp = pcp.get_blocking_term(i); | ||
26 | unsigned int b_spin = results->get_arrival_blocking(i); | ||
27 | |||
28 | if (b_pcp > b_spin) { | ||
29 | // need to account for larger local blocking | ||
30 | Interference new_arrival(b_pcp); | ||
31 | Interference total = (*results)[i]; | ||
32 | // increase total by difference to spin-only blocking | ||
33 | total.total_length += (b_pcp - b_spin); | ||
34 | |||
35 | // update | ||
36 | results->set_arrival_blocking(i, new_arrival); | ||
37 | (*results)[i] = total; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | return results; | ||
42 | } | ||
43 | |||
44 | |||
45 | BlockingBounds pcp_blocking(const ResourceSharingInfo& info) | ||
46 | { | ||
47 | PriorityCeilings prio_ceilings = get_priority_ceilings(info); | ||
48 | |||
49 | // split everything by partition | ||
50 | Clusters clusters; | ||
51 | split_by_cluster(info, clusters); | ||
52 | |||
53 | // blocking results | ||
54 | BlockingBounds results(info); | ||
55 | |||
56 | foreach(clusters, ct) | ||
57 | { | ||
58 | Cluster& cluster = *ct; | ||
59 | foreach(cluster, it) | ||
60 | { | ||
61 | const TaskInfo* tsk = *it; | ||
62 | unsigned int id = tsk->get_id(); | ||
63 | unsigned int prio = tsk->get_priority(); | ||
64 | |||
65 | // check each other task | ||
66 | foreach(cluster, jt) | ||
67 | { | ||
68 | const TaskInfo* other = *jt; | ||
69 | if (id != other->get_id() && | ||
70 | prio <= other->get_priority()) | ||
71 | { | ||
72 | // blocking possible | ||
73 | |||
74 | foreach(other->get_requests(), req) | ||
75 | { | ||
76 | unsigned int res = req->get_resource_id(); | ||
77 | if (prio_ceilings[res] <= prio) { | ||
78 | // this CS could cause ceiling blocking / PI blocking | ||
79 | // make sure blocking term is at least this large | ||
80 | Interference inf(req->get_request_length()); | ||
81 | results.raise_blocking_length(id, inf); | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | return results; | ||
90 | } | ||
diff --git a/tests/locking.py b/tests/locking.py index 2a9766f..1a13a4c 100644 --- a/tests/locking.py +++ b/tests/locking.py | |||
@@ -204,6 +204,52 @@ class Test_bounds(unittest.TestCase): | |||
204 | self.assertEqual(7 + 7 + 77, res.get_arrival_blocking(4)) | 204 | self.assertEqual(7 + 7 + 77, res.get_arrival_blocking(4)) |
205 | self.assertEqual(0, res.get_arrival_blocking(5)) | 205 | self.assertEqual(0, res.get_arrival_blocking(5)) |
206 | 206 | ||
207 | |||
208 | def test_arrival_blocking_msrp(self): | ||
209 | res = cpp.msrp_bounds_holistic(self.rsi1) | ||
210 | self.assertEqual(6 + 7 + 7, res.get_arrival_blocking(0)) | ||
211 | self.assertEqual(5 + 7 + 7, res.get_arrival_blocking(1)) | ||
212 | self.assertEqual(0, res.get_arrival_blocking(2)) | ||
213 | self.assertEqual(0, res.get_arrival_blocking(3)) | ||
214 | self.assertEqual(7 + 7 + 77, res.get_arrival_blocking(4)) | ||
215 | self.assertEqual(0, res.get_arrival_blocking(5)) | ||
216 | |||
217 | def test_local_resources_msrp(self): | ||
218 | self.rsi1.add_request(99, 100, 123456) | ||
219 | res = cpp.msrp_bounds_holistic(self.rsi1) | ||
220 | self.assertEqual(7 + 7 + 77, res.get_arrival_blocking(4)) | ||
221 | |||
222 | def test_local_resources_msrp2(self): | ||
223 | self.rsi1 = cpp.ResourceSharingInfo(7) | ||
224 | |||
225 | self.rsi1.add_task(100, 100, 0, 0) | ||
226 | self.rsi1.add_request(0, 1, 77) | ||
227 | |||
228 | self.rsi1.add_task(50, 50, 0, 1) | ||
229 | self.rsi1.add_request(0, 1, 6) | ||
230 | |||
231 | self.rsi1.add_task(10, 10, 0, 2) | ||
232 | self.rsi1.add_request(0, 1, 5) | ||
233 | |||
234 | self.rsi1.add_task(10, 10, 1, 3) | ||
235 | self.rsi1.add_request(0, 1, 7) | ||
236 | |||
237 | self.rsi1.add_task(20, 20, 2, 4) | ||
238 | self.rsi1.add_request(0, 4, 1) | ||
239 | |||
240 | self.rsi1.add_task(30, 30, 2, 5) | ||
241 | self.rsi1.add_request(0, 1, 7) | ||
242 | self.rsi1.add_request(99, 1, 1) | ||
243 | |||
244 | self.rsi1.add_task(100, 100, 2, 6) | ||
245 | self.rsi1.add_request(99, 100, 123456) | ||
246 | res = cpp.msrp_bounds_holistic(self.rsi1) | ||
247 | self.assertEqual(7 + 7 + 77, res.get_arrival_blocking(4)) | ||
248 | self.assertEqual(123456, res.get_arrival_blocking(5)) | ||
249 | self.assertEqual(123456 + 7 + 77, res.get_blocking_term(5)) | ||
250 | self.assertEqual(0, res.get_blocking_term(6)) | ||
251 | self.assertEqual(0, res.get_arrival_blocking(6)) | ||
252 | |||
207 | def test_arrival_blocking_pf(self): | 253 | def test_arrival_blocking_pf(self): |
208 | c = 1 | 254 | c = 1 |
209 | 255 | ||