diff options
| author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-05-16 12:01:56 -0400 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-05-16 12:01:56 -0400 |
| commit | 546b17c0f6360f4e83e6f0dda8db99656aa94077 (patch) | |
| tree | c5e52133b35b2fe5fd0e76b6ddafc71232e04e7a /native/src | |
| parent | f906d6f40b3f447fd1ba65df3f5e4406972a2331 (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.cpp | 320 | ||||
| -rw-r--r-- | native/src/sharedres.cpp | 322 |
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 | |||
| 10 | typedef std::vector<unsigned int> PriorityCeilings; | ||
| 11 | |||
| 12 | static 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 | |||
| 32 | typedef std::vector<unsigned long> ResponseTimes; | ||
| 33 | typedef std::vector<ResponseTimes> TaskResponseTimes; | ||
| 34 | typedef std::vector<TaskResponseTimes> ClusterResponseTimes; | ||
| 35 | |||
| 36 | static 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 | |||
| 53 | static 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 | |||
| 81 | static 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 | |||
| 94 | static 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 | |||
| 106 | static 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 | |||
| 137 | static 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 | |||
| 170 | static 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 | |||
| 192 | static 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 | |||
| 223 | static 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 | |||
| 249 | static 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 | |||
| 269 | BlockingBounds* 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 | ||
| 25 | static const unsigned int UNLIMITED = UINT_MAX; | 25 | const unsigned int UNLIMITED = UINT_MAX; |
| 26 | 26 | ||
| 27 | std::ostream& operator<<(std::ostream &os, const TaskInfo &ti) | 27 | std::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 | ||
| 81 | typedef std::vector<const TaskInfo*> Cluster; | ||
| 82 | typedef std::vector<Cluster> Clusters; | ||
| 83 | 81 | ||
| 84 | static void split_by_cluster(const ResourceSharingInfo& info, Clusters& clusters) | 82 | void 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 | ||
| 114 | static void split_by_resource(const ResourceSharingInfo& info, Resources& resources) | 112 | void 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 | |||
| 1726 | typedef std::vector<unsigned int> PriorityCeilings; | ||
| 1727 | |||
| 1728 | static 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 | |||
| 1748 | typedef std::vector<unsigned long> ResponseTimes; | ||
| 1749 | typedef std::vector<ResponseTimes> TaskResponseTimes; | ||
| 1750 | typedef std::vector<TaskResponseTimes> ClusterResponseTimes; | ||
| 1751 | |||
| 1752 | static 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 | |||
| 1769 | static 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 | |||
| 1797 | static 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 | |||
| 1810 | static 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 | |||
| 1822 | static 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 | |||
| 1853 | static 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 | |||
| 1886 | static 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 | |||
| 1908 | static 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 | |||
| 1939 | static 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 | |||
| 1965 | static 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 | |||
| 1985 | BlockingBounds* 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 | |||
