aboutsummaryrefslogtreecommitdiffstats
path: root/native/src
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2012-05-16 12:01:56 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2012-05-16 12:01:56 -0400
commit546b17c0f6360f4e83e6f0dda8db99656aa94077 (patch)
treec5e52133b35b2fe5fd0e76b6ddafc71232e04e7a /native/src
parentf906d6f40b3f447fd1ba65df3f5e4406972a2331 (diff)
Move MPPC++: Break out the MPCP code into own file
Part of refactoring sharedres.cpp.
Diffstat (limited to 'native/src')
-rw-r--r--native/src/blocking/mpcp.cpp320
-rw-r--r--native/src/sharedres.cpp322
2 files changed, 323 insertions, 319 deletions
diff --git a/native/src/blocking/mpcp.cpp b/native/src/blocking/mpcp.cpp
new file mode 100644
index 0000000..8b87556
--- /dev/null
+++ b/native/src/blocking/mpcp.cpp
@@ -0,0 +1,320 @@
1#include "sharedres.h"
2#include "blocking.h"
3
4#include "stl-helper.h"
5#include "math-helper.h"
6
7// *************************** MPCP ******************************************
8
9
10typedef std::vector<unsigned int> PriorityCeilings;
11
12static void determine_priority_ceilings(const Resources& resources,
13 PriorityCeilings& ceilings)
14{
15 ceilings.reserve(resources.size());
16
17 foreach(resources, it)
18 {
19 unsigned int ceiling = UINT_MAX;
20 const ContentionSet& cs = *it;
21
22 foreach(cs, jt)
23 {
24 const RequestBound* req = *jt;
25 ceiling = std::min(ceiling, req->get_task()->get_priority());
26 }
27
28 ceilings.push_back(ceiling);
29 }
30}
31
32typedef std::vector<unsigned long> ResponseTimes;
33typedef std::vector<ResponseTimes> TaskResponseTimes;
34typedef std::vector<TaskResponseTimes> ClusterResponseTimes;
35
36static unsigned long get_max_gcs_length(const TaskInfo* tsk,
37 const PriorityCeilings& ceilings,
38 unsigned int preempted_ceiling)
39{
40 unsigned long gcs_length = 0;
41
42 foreach(tsk->get_requests(), it)
43 {
44 unsigned int prio = ceilings[it->get_resource_id()];
45 if (prio < preempted_ceiling)
46 gcs_length = std::max(gcs_length,
47 (unsigned long) it->get_request_length());
48 }
49
50 return gcs_length;
51}
52
53static void determine_gcs_response_times(const TaskInfo* tsk,
54 const Cluster& cluster,
55 const PriorityCeilings& ceilings,
56 ResponseTimes& times)
57{
58 times.reserve(tsk->get_requests().size());
59
60 foreach(tsk->get_requests(), it)
61 {
62 unsigned long resp = it->get_request_length();
63 unsigned int prio = ceilings[it->get_resource_id()];
64
65 // Equation (2) in LNR:09.
66 // One request of each local gcs that can preempt our ceiling,
67 // but at most one per task (since tasks are sequential).
68
69 foreach(cluster, jt)
70 {
71 const TaskInfo* t = *jt;
72
73 if (t != tsk)
74 resp += get_max_gcs_length(t, ceilings, prio);
75 }
76
77 times.push_back(resp);
78 }
79}
80
81static void determine_gcs_response_times(const Cluster& cluster,
82 const PriorityCeilings& ceilings,
83 TaskResponseTimes& times)
84{
85 times.reserve(cluster.size());
86 foreach(cluster, it)
87 {
88 times.push_back(ResponseTimes());
89 determine_gcs_response_times(*it, cluster, ceilings,
90 times.back());
91 }
92}
93
94static void determine_gcs_response_times(const Clusters& clusters,
95 const PriorityCeilings& ceilings,
96 ClusterResponseTimes& times)
97{
98 times.reserve(clusters.size());
99 foreach(clusters, it)
100 {
101 times.push_back(TaskResponseTimes());
102 determine_gcs_response_times(*it, ceilings, times.back());
103 }
104}
105
106static unsigned long response_time_for(unsigned int res_id,
107 unsigned long interval,
108 const TaskInfo* tsk,
109 const ResponseTimes& resp,
110 bool multiple)
111{
112 const Requests& requests = tsk->get_requests();
113 unsigned int i = 0;
114
115 for (i = 0; i < requests.size(); i++)
116 if (requests[i].get_resource_id() == res_id)
117 {
118 if (multiple)
119 {
120 // Equation (3) in LNR:09.
121 // How many jobs?
122 unsigned long num_jobs;
123 num_jobs = divide_with_ceil(interval, tsk->get_period());
124 num_jobs += 1;
125
126 // Note: this may represent multiple gcs, so multiply.
127 return num_jobs * resp[i] * requests[i].get_num_requests();
128 }
129 else
130 // Just one request.
131 return resp[i];
132 }
133 // if we get here, then the task does not access res_id
134 return 0;
135}
136
137static unsigned long mpcp_remote_blocking(unsigned int res_id,
138 unsigned long interval,
139 const TaskInfo* tsk,
140 const Cluster& cluster,
141 const TaskResponseTimes times,
142 unsigned long& max_lower)
143{
144 unsigned int i;
145 unsigned long blocking = 0;
146
147 // consider each task in cluster
148 for (i = 0; i < cluster.size(); i++)
149 {
150 const TaskInfo* t = cluster[i];
151 if (t != tsk)
152 {
153 if (t->get_priority() < tsk->get_priority())
154 // This is a higher-priority task;
155 // it can block multiple times.
156 blocking += response_time_for(res_id, interval,
157 t, times[i], true);
158 else
159 // This is a lower-priority task;
160 // it can block only once.
161 max_lower = std::max(max_lower,
162 response_time_for(res_id, interval,
163 t, times[i], false));
164 }
165 }
166
167 return blocking;
168}
169
170static unsigned long mpcp_remote_blocking(unsigned int res_id,
171 unsigned long interval,
172 const TaskInfo* tsk,
173 const Clusters& clusters,
174 const ClusterResponseTimes times,
175 unsigned long& max_lower)
176{
177 unsigned int i;
178 unsigned long blocking;
179
180 max_lower = 0;
181 blocking = 0;
182
183 for (i = 0; i < clusters.size(); i++)
184 {
185 blocking += mpcp_remote_blocking(res_id, interval,
186 tsk, clusters[i], times[i],
187 max_lower);
188 }
189 return blocking;
190}
191
192static unsigned long mpcp_remote_blocking(unsigned int res_id,
193 const TaskInfo* tsk,
194 const Clusters& clusters,
195 const ClusterResponseTimes times)
196{
197 unsigned long interval;
198 unsigned long blocking = 1;
199 unsigned long max_lower;
200
201 do
202 {
203 // last bound
204 interval = blocking;
205 // Bail out if it doesn't converge.
206 if (interval > tsk->get_response())
207 return UNLIMITED;
208
209 blocking = mpcp_remote_blocking(res_id, interval,
210 tsk, clusters, times,
211 max_lower);
212
213 // Account for the maximum lower-priority gcs
214 // that could get in the way.
215 blocking += max_lower;
216
217 // Loop until it converges.
218 } while ( interval != blocking );
219
220 return blocking;
221}
222
223static unsigned long mpcp_remote_blocking(const TaskInfo* tsk,
224 const Clusters& clusters,
225 const ClusterResponseTimes times)
226{
227 unsigned long blocking = 0;
228
229
230 const Requests& requests = tsk->get_requests();
231 unsigned int i = 0;
232
233 for (i = 0; i < requests.size(); i++)
234 {
235 unsigned int b;
236 b = mpcp_remote_blocking(requests[i].get_resource_id(),
237 tsk, clusters, times);
238 if (b != UNLIMITED)
239 // may represent multiple, multiply accordingly
240 blocking += b * requests[i].get_num_requests();
241 else
242 // bail out if it didn't converge
243 return b;
244 }
245
246 return blocking;
247}
248
249static unsigned long mpcp_arrival_blocking(const TaskInfo* tsk,
250 const Cluster& cluster,
251 bool virtual_spinning)
252{
253 unsigned int prio = tsk->get_priority();
254 unsigned int blocking = 0;
255 unsigned int i;
256
257 for (i = 0; i < cluster.size(); i++)
258 if (cluster[i] != tsk && cluster[i]->get_priority() >= prio)
259 blocking += cluster[i]->get_max_request_length();
260
261 if (virtual_spinning)
262 // Equation (4) in LNR:09.
263 return blocking;
264 else
265 // Equation (1) in LNR:09.
266 return blocking * tsk->get_num_arrivals();
267}
268
269BlockingBounds* mpcp_bounds(const ResourceSharingInfo& info,
270 bool use_virtual_spinning)
271{
272 Resources resources;
273 Clusters clusters;
274
275 split_by_resource(info, resources);
276 split_by_cluster(info, clusters);
277
278 // 2) Determine priority ceiling for each request.
279 PriorityCeilings gc;
280 determine_priority_ceilings(resources, gc);
281
282
283 // 3) For each request, determine response time. This only depends on the
284 // priority ceiling for each request.
285 ClusterResponseTimes responses;
286 determine_gcs_response_times(clusters, gc, responses);
287
288 unsigned int i;
289
290 BlockingBounds* _results = new BlockingBounds(info);
291 BlockingBounds& results = *_results;
292
293 for (i = 0; i < info.get_tasks().size(); i++)
294 {
295 const TaskInfo& tsk = info.get_tasks()[i];
296
297 unsigned long remote, local = 0;
298
299 // 4) Determine remote blocking for each request. This depends on the
300 // response times for each remote request.
301 remote = mpcp_remote_blocking(&tsk, clusters, responses);
302
303 // 5) Determine arrival blocking for each task.
304 if (remote != UNLIMITED)
305 local = mpcp_arrival_blocking(&tsk, clusters[tsk.get_cluster()],
306 use_virtual_spinning);
307
308 // 6) Sum up blocking: remote blocking + arrival blocking.
309 results[i].total_length = remote + local;
310
311
312 Interference inf;
313 inf.total_length = remote;
314 results.set_remote_blocking(i, inf);
315 }
316
317 return _results;
318}
319
320
diff --git a/native/src/sharedres.cpp b/native/src/sharedres.cpp
index 935d20f..a3b4ed9 100644
--- a/native/src/sharedres.cpp
+++ b/native/src/sharedres.cpp
@@ -22,7 +22,7 @@
22 22
23#include "blocking.h" 23#include "blocking.h"
24 24
25static const unsigned int UNLIMITED = UINT_MAX; 25const unsigned int UNLIMITED = UINT_MAX;
26 26
27std::ostream& operator<<(std::ostream &os, const TaskInfo &ti) 27std::ostream& operator<<(std::ostream &os, const TaskInfo &ti)
28{ 28{
@@ -78,10 +78,8 @@ unsigned int RequestBound::get_max_num_requests(unsigned long interval) const
78 78
79// ****** non-exported helpers ******* 79// ****** non-exported helpers *******
80 80
81typedef std::vector<const TaskInfo*> Cluster;
82typedef std::vector<Cluster> Clusters;
83 81
84static void split_by_cluster(const ResourceSharingInfo& info, Clusters& clusters) 82void split_by_cluster(const ResourceSharingInfo& info, Clusters& clusters)
85{ 83{
86 foreach(info.get_tasks(), it) 84 foreach(info.get_tasks(), it)
87 { 85 {
@@ -111,7 +109,7 @@ void sort_by_priority(Clusters& clusters)
111} 109}
112 110
113 111
114static void split_by_resource(const ResourceSharingInfo& info, Resources& resources) 112void split_by_resource(const ResourceSharingInfo& info, Resources& resources)
115{ 113{
116 foreach(info.get_tasks(), it) 114 foreach(info.get_tasks(), it)
117 { 115 {
@@ -1720,317 +1718,3 @@ BlockingBounds* part_fmlp_bounds(const ResourceSharingInfo& info, bool preemptiv
1720 return _results; 1718 return _results;
1721} 1719}
1722 1720
1723// *************************** MPCP ******************************************
1724
1725
1726typedef std::vector<unsigned int> PriorityCeilings;
1727
1728static void determine_priority_ceilings(const Resources& resources,
1729 PriorityCeilings& ceilings)
1730{
1731 ceilings.reserve(resources.size());
1732
1733 foreach(resources, it)
1734 {
1735 unsigned int ceiling = UINT_MAX;
1736 const ContentionSet& cs = *it;
1737
1738 foreach(cs, jt)
1739 {
1740 const RequestBound* req = *jt;
1741 ceiling = std::min(ceiling, req->get_task()->get_priority());
1742 }
1743
1744 ceilings.push_back(ceiling);
1745 }
1746}
1747
1748typedef std::vector<unsigned long> ResponseTimes;
1749typedef std::vector<ResponseTimes> TaskResponseTimes;
1750typedef std::vector<TaskResponseTimes> ClusterResponseTimes;
1751
1752static unsigned long get_max_gcs_length(const TaskInfo* tsk,
1753 const PriorityCeilings& ceilings,
1754 unsigned int preempted_ceiling)
1755{
1756 unsigned long gcs_length = 0;
1757
1758 foreach(tsk->get_requests(), it)
1759 {
1760 unsigned int prio = ceilings[it->get_resource_id()];
1761 if (prio < preempted_ceiling)
1762 gcs_length = std::max(gcs_length,
1763 (unsigned long) it->get_request_length());
1764 }
1765
1766 return gcs_length;
1767}
1768
1769static void determine_gcs_response_times(const TaskInfo* tsk,
1770 const Cluster& cluster,
1771 const PriorityCeilings& ceilings,
1772 ResponseTimes& times)
1773{
1774 times.reserve(tsk->get_requests().size());
1775
1776 foreach(tsk->get_requests(), it)
1777 {
1778 unsigned long resp = it->get_request_length();
1779 unsigned int prio = ceilings[it->get_resource_id()];
1780
1781 // Equation (2) in LNR:09.
1782 // One request of each local gcs that can preempt our ceiling,
1783 // but at most one per task (since tasks are sequential).
1784
1785 foreach(cluster, jt)
1786 {
1787 const TaskInfo* t = *jt;
1788
1789 if (t != tsk)
1790 resp += get_max_gcs_length(t, ceilings, prio);
1791 }
1792
1793 times.push_back(resp);
1794 }
1795}
1796
1797static void determine_gcs_response_times(const Cluster& cluster,
1798 const PriorityCeilings& ceilings,
1799 TaskResponseTimes& times)
1800{
1801 times.reserve(cluster.size());
1802 foreach(cluster, it)
1803 {
1804 times.push_back(ResponseTimes());
1805 determine_gcs_response_times(*it, cluster, ceilings,
1806 times.back());
1807 }
1808}
1809
1810static void determine_gcs_response_times(const Clusters& clusters,
1811 const PriorityCeilings& ceilings,
1812 ClusterResponseTimes& times)
1813{
1814 times.reserve(clusters.size());
1815 foreach(clusters, it)
1816 {
1817 times.push_back(TaskResponseTimes());
1818 determine_gcs_response_times(*it, ceilings, times.back());
1819 }
1820}
1821
1822static unsigned long response_time_for(unsigned int res_id,
1823 unsigned long interval,
1824 const TaskInfo* tsk,
1825 const ResponseTimes& resp,
1826 bool multiple)
1827{
1828 const Requests& requests = tsk->get_requests();
1829 unsigned int i = 0;
1830
1831 for (i = 0; i < requests.size(); i++)
1832 if (requests[i].get_resource_id() == res_id)
1833 {
1834 if (multiple)
1835 {
1836 // Equation (3) in LNR:09.
1837 // How many jobs?
1838 unsigned long num_jobs;
1839 num_jobs = divide_with_ceil(interval, tsk->get_period());
1840 num_jobs += 1;
1841
1842 // Note: this may represent multiple gcs, so multiply.
1843 return num_jobs * resp[i] * requests[i].get_num_requests();
1844 }
1845 else
1846 // Just one request.
1847 return resp[i];
1848 }
1849 // if we get here, then the task does not access res_id
1850 return 0;
1851}
1852
1853static unsigned long mpcp_remote_blocking(unsigned int res_id,
1854 unsigned long interval,
1855 const TaskInfo* tsk,
1856 const Cluster& cluster,
1857 const TaskResponseTimes times,
1858 unsigned long& max_lower)
1859{
1860 unsigned int i;
1861 unsigned long blocking = 0;
1862
1863 // consider each task in cluster
1864 for (i = 0; i < cluster.size(); i++)
1865 {
1866 const TaskInfo* t = cluster[i];
1867 if (t != tsk)
1868 {
1869 if (t->get_priority() < tsk->get_priority())
1870 // This is a higher-priority task;
1871 // it can block multiple times.
1872 blocking += response_time_for(res_id, interval,
1873 t, times[i], true);
1874 else
1875 // This is a lower-priority task;
1876 // it can block only once.
1877 max_lower = std::max(max_lower,
1878 response_time_for(res_id, interval,
1879 t, times[i], false));
1880 }
1881 }
1882
1883 return blocking;
1884}
1885
1886static unsigned long mpcp_remote_blocking(unsigned int res_id,
1887 unsigned long interval,
1888 const TaskInfo* tsk,
1889 const Clusters& clusters,
1890 const ClusterResponseTimes times,
1891 unsigned long& max_lower)
1892{
1893 unsigned int i;
1894 unsigned long blocking;
1895
1896 max_lower = 0;
1897 blocking = 0;
1898
1899 for (i = 0; i < clusters.size(); i++)
1900 {
1901 blocking += mpcp_remote_blocking(res_id, interval,
1902 tsk, clusters[i], times[i],
1903 max_lower);
1904 }
1905 return blocking;
1906}
1907
1908static unsigned long mpcp_remote_blocking(unsigned int res_id,
1909 const TaskInfo* tsk,
1910 const Clusters& clusters,
1911 const ClusterResponseTimes times)
1912{
1913 unsigned long interval;
1914 unsigned long blocking = 1;
1915 unsigned long max_lower;
1916
1917 do
1918 {
1919 // last bound
1920 interval = blocking;
1921 // Bail out if it doesn't converge.
1922 if (interval > tsk->get_response())
1923 return UNLIMITED;
1924
1925 blocking = mpcp_remote_blocking(res_id, interval,
1926 tsk, clusters, times,
1927 max_lower);
1928
1929 // Account for the maximum lower-priority gcs
1930 // that could get in the way.
1931 blocking += max_lower;
1932
1933 // Loop until it converges.
1934 } while ( interval != blocking );
1935
1936 return blocking;
1937}
1938
1939static unsigned long mpcp_remote_blocking(const TaskInfo* tsk,
1940 const Clusters& clusters,
1941 const ClusterResponseTimes times)
1942{
1943 unsigned long blocking = 0;
1944
1945
1946 const Requests& requests = tsk->get_requests();
1947 unsigned int i = 0;
1948
1949 for (i = 0; i < requests.size(); i++)
1950 {
1951 unsigned int b;
1952 b = mpcp_remote_blocking(requests[i].get_resource_id(),
1953 tsk, clusters, times);
1954 if (b != UNLIMITED)
1955 // may represent multiple, multiply accordingly
1956 blocking += b * requests[i].get_num_requests();
1957 else
1958 // bail out if it didn't converge
1959 return b;
1960 }
1961
1962 return blocking;
1963}
1964
1965static unsigned long mpcp_arrival_blocking(const TaskInfo* tsk,
1966 const Cluster& cluster,
1967 bool virtual_spinning)
1968{
1969 unsigned int prio = tsk->get_priority();
1970 unsigned int blocking = 0;
1971 unsigned int i;
1972
1973 for (i = 0; i < cluster.size(); i++)
1974 if (cluster[i] != tsk && cluster[i]->get_priority() >= prio)
1975 blocking += cluster[i]->get_max_request_length();
1976
1977 if (virtual_spinning)
1978 // Equation (4) in LNR:09.
1979 return blocking;
1980 else
1981 // Equation (1) in LNR:09.
1982 return blocking * tsk->get_num_arrivals();
1983}
1984
1985BlockingBounds* mpcp_bounds(const ResourceSharingInfo& info,
1986 bool use_virtual_spinning)
1987{
1988 Resources resources;
1989 Clusters clusters;
1990
1991 split_by_resource(info, resources);
1992 split_by_cluster(info, clusters);
1993
1994 // 2) Determine priority ceiling for each request.
1995 PriorityCeilings gc;
1996 determine_priority_ceilings(resources, gc);
1997
1998
1999 // 3) For each request, determine response time. This only depends on the
2000 // priority ceiling for each request.
2001 ClusterResponseTimes responses;
2002 determine_gcs_response_times(clusters, gc, responses);
2003
2004 unsigned int i;
2005
2006 BlockingBounds* _results = new BlockingBounds(info);
2007 BlockingBounds& results = *_results;
2008
2009 for (i = 0; i < info.get_tasks().size(); i++)
2010 {
2011 const TaskInfo& tsk = info.get_tasks()[i];
2012
2013 unsigned long remote, local = 0;
2014
2015 // 4) Determine remote blocking for each request. This depends on the
2016 // response times for each remote request.
2017 remote = mpcp_remote_blocking(&tsk, clusters, responses);
2018
2019 // 5) Determine arrival blocking for each task.
2020 if (remote != UNLIMITED)
2021 local = mpcp_arrival_blocking(&tsk, clusters[tsk.get_cluster()],
2022 use_virtual_spinning);
2023
2024 // 6) Sum up blocking: remote blocking + arrival blocking.
2025 results[i].total_length = remote + local;
2026
2027
2028 Interference inf;
2029 inf.total_length = remote;
2030 results.set_remote_blocking(i, inf);
2031 }
2032
2033 return _results;
2034}
2035
2036