diff options
Diffstat (limited to 'native/src/sharedres.cpp')
| -rw-r--r-- | native/src/sharedres.cpp | 322 |
1 files changed, 3 insertions, 319 deletions
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 | |||
