- Timestamp:
- 05/22/11 05:52:01 (13 years ago)
- Files:
-
- trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (modified) (8 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r1970 r1985 142 142 m_SyncIsoHandler = NULL; 143 143 for (i = 0, cnt = 0; i < max; i++) { 144 145 // FIXME: This is a very crude guard against some other thread 146 // deleting handlers while this function is running. While this 147 // didn't tend to happen with the old kernel firewire stack, delays 148 // in shutdown experienced in the new stack mean it can happen that 149 // a handler disappears during the running of this function. This 150 // test should prevent "out of range" exceptions in most cases. 151 // However, it is racy: if the deletion happens between this 152 // conditional and the following at() call, an out of range 153 // condition can still happen. 154 if (i>=m_manager.m_IsoHandlers.size()) 155 continue; 156 144 157 IsoHandler *h = m_manager.m_IsoHandlers.at(i); 145 158 assert(h); … … 1238 1251 #endif 1239 1252 { 1253 pthread_mutex_init(&m_disable_lock, NULL); 1240 1254 } 1241 1255 … … 1299 1313 // raw1394_destroy_handle() will do any iso system shutdown required. 1300 1314 // raw1394_iso_shutdown(m_handle); 1315 1316 // Typically, by the time this function is called the IsoTask thread would 1317 // have called disable() on the handler (in the FW_ISORCV/FW_ISOXMT 1318 // threads). However, the raw1394_destroy_handle() call therein takes 1319 // upwards of 20 milliseconds to complete under the new kernel firewire 1320 // stack, and may not have completed by the time ~IsoHandler() is called by 1321 // the "jackd" thread. Thus, wait for the lock before testing the state 1322 // of the handle so any in-progress disable() is complete. 1323 if (pthread_mutex_trylock(&m_disable_lock) == EBUSY) { 1324 pthread_mutex_lock(&m_disable_lock); 1325 pthread_mutex_unlock(&m_disable_lock); 1326 } 1301 1327 if(m_handle) { 1302 1328 if (m_State == eHS_Running) { … … 1305 1331 } 1306 1332 } 1333 pthread_mutex_destroy(&m_disable_lock); 1307 1334 } 1308 1335 … … 1794 1821 IsoHandlerManager::IsoHandler::disable() 1795 1822 { 1823 signed int i, have_lock = 0; 1824 1796 1825 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n", 1797 1826 this, (m_type==eHT_Receive?"Receive":"Transmit")); 1827 1828 i = pthread_mutex_trylock(&m_disable_lock); 1829 if (i == 0) 1830 have_lock = 1; 1831 else 1832 if (i == EBUSY) { 1833 // Some other thread is disabling this handler, a process which can 1834 // take considerable time when using the new kernel firewire stack. 1835 // Wait until it is finished before returning so the present caller 1836 // can act knowing that the disable has occurred and is complete 1837 // (which is what normally would be expected). 1838 debugOutput( DEBUG_LEVEL_VERBOSE, "waiting for disable lock\n"); 1839 pthread_mutex_lock(&m_disable_lock); 1840 debugOutput( DEBUG_LEVEL_VERBOSE, "now have disable lock\n"); 1841 if (m_State == eHS_Stopped) { 1842 debugOutput( DEBUG_LEVEL_VERBOSE, "another disable() has completed\n"); 1843 pthread_mutex_unlock(&m_disable_lock); 1844 return true; 1845 } 1846 have_lock = 1; 1847 } 1798 1848 1799 1849 // check state 1800 1850 if(m_State != eHS_Running) { 1801 1851 debugError("Incorrect state, expected eHS_Running, got %d\n",(int)m_State); 1852 if (have_lock) 1853 pthread_mutex_unlock(&m_disable_lock); 1802 1854 return false; 1803 1855 } … … 1819 1871 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) stop...\n", 1820 1872 this, (m_type==eHT_Receive?"Receive":"Transmit")); 1873 1821 1874 // stop iso traffic 1822 1875 raw1394_iso_stop(m_handle); … … 1828 1881 raw1394_iso_shutdown(m_handle); 1829 1882 1883 // When running on the new kernel firewire stack, this call can take of 1884 // the order of 20 milliseconds to return, in which time other threads 1885 // may wish to test the state of the handler and call this function 1886 // themselves. The m_disable_lock mutex is used to work around this. 1830 1887 raw1394_destroy_handle(m_handle); 1831 1888 m_handle = NULL; … … 1833 1890 m_State = eHS_Stopped; 1834 1891 m_NextState = eHS_Stopped; 1892 1893 if (have_lock) 1894 pthread_mutex_unlock(&m_disable_lock); 1835 1895 return true; 1836 1896 } trunk/libffado/src/libieee1394/IsoHandlerManager.h
r1943 r1985 225 225 int m_switch_on_cycle; 226 226 227 pthread_mutex_t m_disable_lock; 228 227 229 public: 228 230 unsigned int m_packets;