From 110ec3d331a47dcf1b4bfff58a180702fc64384d Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 6 Jun 2004 02:41:16 +0000 Subject: [PATCH] synchronize access to memory cards between mounting thread and main thread Profile Load/Save --- stepmania/src/MemoryCardManager.cpp | 9 ++ stepmania/src/MemoryCardManager.h | 3 + stepmania/src/ProfileManager.cpp | 15 ++- .../src/arch/MemoryCard/MemoryCardDriver.h | 2 + .../MemoryCard/MemoryCardDriverThreaded.cpp | 49 ++++++-- .../MemoryCard/MemoryCardDriverThreaded.h | 24 +++- .../MemoryCardDriverThreaded_Linux.cpp | 108 ++++++++---------- .../MemoryCardDriverThreaded_Linux.h | 7 +- .../MemoryCardDriverThreaded_Windows.cpp | 106 ++++++++--------- .../MemoryCardDriverThreaded_Windows.h | 7 +- .../arch/MemoryCard/MemoryCardDriver_Null.h | 3 +- 11 files changed, 190 insertions(+), 143 deletions(-) diff --git a/stepmania/src/MemoryCardManager.cpp b/stepmania/src/MemoryCardManager.cpp index 3352651ec7..5771b5d0a6 100644 --- a/stepmania/src/MemoryCardManager.cpp +++ b/stepmania/src/MemoryCardManager.cpp @@ -295,6 +295,15 @@ CString MemoryCardManager::GetName( PlayerNumber pn ) const return m_Device[pn].sName; } +void MemoryCardManager::PauseMountingThread() +{ + m_pDriver->PauseMountingThread(); +} + +void MemoryCardManager::UnPauseMountingThread() +{ + m_pDriver->UnPauseMountingThread(); +} bool IsAnyPlayerUsingMemoryCard() { diff --git a/stepmania/src/MemoryCardManager.h b/stepmania/src/MemoryCardManager.h index 0e1113cf40..f32e1fcbe1 100644 --- a/stepmania/src/MemoryCardManager.h +++ b/stepmania/src/MemoryCardManager.h @@ -37,6 +37,9 @@ public: void LockCards( bool bLock ); // prevent removing or changing of memory cards + void PauseMountingThread(); // call this before reading or writing to memory card + void UnPauseMountingThread(); // call this when done reading or writing to memory card + void FlushAndReset(); // force all files to be written to mounted memory cards bool PathIsMemCard( CString sDir ) const; diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 260a28cd98..2779431b4a 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -84,6 +84,9 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs ASSERT( !sProfileDir.empty() ); ASSERT( sProfileDir.Right(1) == "/" ); + if( bIsMemCard ) + MEMCARDMAN->PauseMountingThread(); + m_sProfileDir[pn] = sProfileDir; m_bWasLoadedFromMemoryCard[pn] = bIsMemCard; @@ -92,6 +95,8 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs else m_Profile[pn].LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); + MEMCARDMAN->UnPauseMountingThread(); + LOG->Trace( "Done loading profile." ); return true; @@ -200,7 +205,15 @@ bool ProfileManager::SaveProfile( PlayerNumber pn ) const if( m_sProfileDir[pn].empty() ) return false; - return m_Profile[pn].SaveAllToDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); + if( ProfileWasLoadedFromMemoryCard(pn) ) + MEMCARDMAN->PauseMountingThread(); + + bool b = m_Profile[pn].SaveAllToDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); + + if( ProfileWasLoadedFromMemoryCard(pn) ) + MEMCARDMAN->UnPauseMountingThread(); + + return b; } void ProfileManager::UnloadProfile( PlayerNumber pn ) diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriver.h b/stepmania/src/arch/MemoryCard/MemoryCardDriver.h index fec8eeef74..0b116db8a6 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriver.h +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriver.h @@ -57,6 +57,8 @@ public: virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0; virtual void Flush( UsbStorageDevice* pDevice ) = 0; virtual void ResetUsbStorage() = 0; + virtual void PauseMountingThread() = 0; + virtual void UnPauseMountingThread() = 0; }; #endif diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.cpp b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.cpp index 5b4070d433..da0335d710 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.cpp +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.cpp @@ -5,12 +5,6 @@ #include "RageFileManager.h" -int MemoryCardDriverThreaded::MountThread_Start( void *p ) -{ - ((MemoryCardDriverThreaded*)p)->MountThreadMain(); - return 0; -} - template bool VectorsAreEqual( const T &a, const T &b ) { @@ -27,9 +21,11 @@ bool VectorsAreEqual( const T &a, const T &b ) } MemoryCardDriverThreaded::MemoryCardDriverThreaded() : -m_mutexStorageDevices("StorageDevices") + m_mutexPause("Pause"), + m_mutexStorageDevices("StorageDevices") { - m_bShutdown = false; + m_bShutdownNextUpdate = false; + m_bResetNextUpdate = false; m_bStorageDevicesChanged = false; } @@ -41,12 +37,42 @@ void MemoryCardDriverThreaded::StartThread() MemoryCardDriverThreaded::~MemoryCardDriverThreaded() { - m_bShutdown = true; + m_bShutdownNextUpdate = true; LOG->Trace( "Shutting down Mount thread..." ); m_threadMemoryCardMount.Wait(); LOG->Trace( "Mount thread shut down." ); } +void MemoryCardDriverThreaded::PauseMountingThread() +{ + m_mutexPause.Lock(); +} + +void MemoryCardDriverThreaded::UnPauseMountingThread() +{ + m_mutexPause.Unlock(); +} + +int MemoryCardDriverThreaded::MountThread_Start( void *p ) +{ + ((MemoryCardDriverThreaded*)p)->MountThreadMain(); + return 0; +} + +void MemoryCardDriverThreaded::MountThreadMain() +{ + while( !m_bShutdownNextUpdate ) + { + LockMut( m_mutexPause ); // wait until we're unpaused + if( m_bResetNextUpdate ) + { + this->MountThreadReset(); + m_bResetNextUpdate = false; + } + this->MountThreadDoOneUpdate(); + } +} + bool MemoryCardDriverThreaded::StorageDevicesChanged() { LockMut( m_mutexStorageDevices ); @@ -86,6 +112,11 @@ bool MemoryCardDriverThreaded::MountAndTestWrite( UsbStorageDevice* pDevice, CSt return true; } +void MemoryCardDriverThreaded::ResetUsbStorage() +{ + m_bResetNextUpdate = true; +} + /* * (c) 2003-2004 Chris Danford * All rights reserved. diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.h b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.h index 1bb8cb2452..551712aca3 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.h +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded.h @@ -21,18 +21,32 @@ class MemoryCardDriverThreaded : public MemoryCardDriver public: MemoryCardDriverThreaded(); ~MemoryCardDriverThreaded(); - void StartThread(); // call this in the derived constructor to start the mounting thread virtual bool StorageDevicesChanged(); virtual void GetStorageDevices( vector& vStorageDevicesOut ); virtual bool MountAndTestWrite( UsbStorageDevice* pDevice, CString sMountPoint ); + virtual void ResetUsbStorage(); + virtual void PauseMountingThread(); + virtual void UnPauseMountingThread(); + +private: static int MountThread_Start( void *p ); -protected: - virtual void MountThreadMain() = 0; - virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0; + void MountThreadMain(); RageThread m_threadMemoryCardMount; - bool m_bShutdown; + bool m_bShutdownNextUpdate; + bool m_bResetNextUpdate; + + // Aquire this before detecting devices or reading/writing devices. + // Calling Pause() and Unpause will lock/unlock this so that the mounting thread + // will temporarily halt. + RageMutex m_mutexPause; + +protected: + void StartThread(); // call this in the derived constructor to start the mounting thread + virtual void MountThreadReset() = 0; + virtual void MountThreadDoOneUpdate() = 0; // this will get called as fast as possible + virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0; vector m_vStorageDevices; bool m_bStorageDevicesChanged; diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Linux.cpp b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Linux.cpp index 930c569420..6149d4809a 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Linux.cpp +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Linux.cpp @@ -124,41 +124,56 @@ static bool ExecuteCommand( CCStringRef sCommand ) return ret == 0; } -void MemoryCardDriverThreaded_Linux::MountThreadMain() +MemoryCardDriverThreaded_Linux::MemoryCardDriverThreaded_Linux() { - int fd = open(USB_DEVICE_LIST_FILE, O_RDONLY); - if( fd == -1 ) + m_fd = open(USB_DEVICE_LIST_FILE, O_RDONLY); + if( m_fd == -1 ) { LOG->Warn( "Failed to open \"%s\": %s", USB_DEVICE_LIST_FILE, strerror(errno) ); - return; + } + this->StartThread(); +} + +void MemoryCardDriverThreaded_Linux::MountThreadReset() +{ + // + // if usb-storage gets in a bad state, resetting usb-storage will sometimes fix it. + // + + LockMut( m_mutexStorageDevices ); + + // unmount all devices before trying to remove the module + for( unsigned i=0; i vDevicesLastSeen; - - while( !m_bShutdown ) - { - if( m_bReset ) + ExecuteCommand( "rmmod usb-storage" ); + ExecuteCommand( "modprobe usb-storage" ); + + m_vDevicesLastSeen.clear(); // redetect all devices +} + +void MemoryCardDriverThreaded_Linux::MountThreadDoOneUpdate() +{ + if( m_fd == -1 ) + return; + + pollfd pfd = { m_fd, POLLIN, 0 }; + int ret = poll( &pfd, 1, 100 ); + switch( ret ) { - // force all to be re-detected - vDevicesLastSeen.clear(); - m_bReset = false; - } - else - { - pollfd pfd = { fd, POLLIN, 0 }; - int ret = poll( &pfd, 1, 100 ); - switch( ret ) - { - case 1: - // file changed. Fall through. - break; - case 0: // no change. Poll again. - continue; - case -1: - if( errno != EINTR ) - LOG->Warn( "Error polling: %s", strerror(errno) ); - continue; - } + case 1: + // file changed. Fall through. + break; + case 0: // no change. Poll again. + return; + case -1: + if( errno != EINTR ) + LOG->Warn( "Error polling: %s", strerror(errno) ); + return; } // TRICKY: We're waiting for a change in the USB device list, but @@ -172,7 +187,7 @@ void MemoryCardDriverThreaded_Linux::MountThreadMain() GetNewStorageDevices( vDevicesNow ); vector &vNew = vDevicesNow; - vector &vOld = vDevicesLastSeen; + vector &vOld = m_vDevicesLastSeen; // check for disconnects vector vDisconnects; @@ -246,18 +261,11 @@ void MemoryCardDriverThreaded_Linux::MountThreadMain() } } - vDevicesLastSeen = vDevicesNow; - } + m_vDevicesLastSeen = vDevicesNow; CHECKPOINT; } -MemoryCardDriverThreaded_Linux::MemoryCardDriverThreaded_Linux() -{ - m_bReset = false; - this->StartThread(); -} - bool ReadUsbStorageDescriptor( CString fn, int iScsiIndex, vector& vDevicesOut ) { LOG->Trace( "ReadUsbStorageDescriptor %s", fn.c_str() ); @@ -631,30 +639,6 @@ void MemoryCardDriverThreaded_Linux::Flush( UsbStorageDevice* pDevice ) ExecuteCommand( "mount -o remount " + pDevice->sOsMountDir ); } -void MemoryCardDriverThreaded_Linux::ResetUsbStorage() -{ - // - // if usb-storage gets in a bad state, resetting usb-storage will sometimes fix it. - // - - LockMut( m_mutexStorageDevices ); - - // unmount all devices before trying to remove the module - for( unsigned i=0; i m_vDevicesLastSeen; }; #endif diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.cpp b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.cpp index c4b706ba80..2be08af6af 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.cpp +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.cpp @@ -7,14 +7,13 @@ #include "RageLog.h" #include "Profile.h" #include "PrefsManager.h" -#include const CString TEMP_MOUNT_POINT = "@mctemp/"; MemoryCardDriverThreaded_Windows::MemoryCardDriverThreaded_Windows() { - m_bReset = false; + m_dwLastLogicalDrives = 0; StartThread(); } @@ -55,65 +54,59 @@ static bool TestWrite( CCStringRef sDrive ) return true; } -void MemoryCardDriverThreaded_Windows::MountThreadMain() +void MemoryCardDriverThreaded_Windows::MountThreadReset() { - DWORD dwLastLogicalDrives = 0; - - while( !m_bShutdown ) + m_dwLastLogicalDrives = 0; +} + +void MemoryCardDriverThreaded_Windows::MountThreadDoOneUpdate() +{ + DWORD dwNewLogicalDrives = ::GetLogicalDrives(); + if( dwNewLogicalDrives != m_dwLastLogicalDrives ) { - if( m_bReset ) + vector vNewStorageDevices; + + const int MAX_DRIVES = 26; + for( int i=2; iTrace( "Found drive %s", sDrive.c_str() ); + + if( GetDriveType(sDrive) != DRIVE_REMOVABLE ) // is a removable drive + continue; + + if( !TestReady(sDrive) ) + continue; + + UsbStorageDeviceEx usbd; + usbd.sOsMountDir = sDrive; + usbd.bWriteTestSucceeded = TestWrite( sDrive ); + + // read name + this->Mount( &usbd, TEMP_MOUNT_POINT ); + FILEMAN->FlushDirCache( TEMP_MOUNT_POINT ); + Profile profile; + CString sProfileDir = TEMP_MOUNT_POINT + PREFSMAN->m_sMemoryCardProfileSubdir + '/'; + profile.LoadEditableDataFromDir( sProfileDir ); + usbd.sName = profile.GetDisplayName(); + + vNewStorageDevices.push_back( usbd ); + } } - DWORD dwNewLogicalDrives = ::GetLogicalDrives(); - if( dwNewLogicalDrives != dwLastLogicalDrives ) { - vector vNewStorageDevices; - - const int MAX_DRIVES = 26; - for( int i=2; iTrace( "Found drive %s", sDrive.c_str() ); - - if( GetDriveType(sDrive) != DRIVE_REMOVABLE ) // is a removable drive - continue; - - if( !TestReady(sDrive) ) - continue; - - UsbStorageDeviceEx usbd; - usbd.sOsMountDir = sDrive; - usbd.bWriteTestSucceeded = TestWrite( sDrive ); - - // read name - this->Mount( &usbd, TEMP_MOUNT_POINT ); - FILEMAN->FlushDirCache( TEMP_MOUNT_POINT ); - Profile profile; - CString sProfileDir = TEMP_MOUNT_POINT + PREFSMAN->m_sMemoryCardProfileSubdir + '/'; - profile.LoadEditableDataFromDir( sProfileDir ); - usbd.sName = profile.GetDisplayName(); - - vNewStorageDevices.push_back( usbd ); - } - } - - { - LockMut( m_mutexStorageDevices ); - m_bStorageDevicesChanged = true; - m_vStorageDevices = vNewStorageDevices; - } - } - dwLastLogicalDrives = dwNewLogicalDrives; - - ::Sleep( 100 ); + LockMut( m_mutexStorageDevices ); + m_bStorageDevicesChanged = true; + m_vStorageDevices = vNewStorageDevices; + } } + m_dwLastLogicalDrives = dwNewLogicalDrives; + + ::Sleep( 100 ); } void MemoryCardDriverThreaded_Windows::Mount( UsbStorageDevice* pDevice, CString sMountPoint ) @@ -149,11 +142,6 @@ void MemoryCardDriverThreaded_Windows::Flush( UsbStorageDevice* pDevice ) // Windows flushes automatically every ~2 seconds. -Chris } -void MemoryCardDriverThreaded_Windows::ResetUsbStorage() -{ - m_bReset = true; -} - /* * (c) 2003-2004 Chris Danford * All rights reserved. diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.h b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.h index 4200fad3a6..4ac398f714 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.h +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriverThreaded_Windows.h @@ -2,6 +2,7 @@ #define MemoryCardDriverThreaded_Windows_H 1 #include "MemoryCardDriverThreaded.h" +#include class MemoryCardDriverThreaded_Windows : public MemoryCardDriverThreaded { @@ -10,12 +11,12 @@ public: virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ); virtual void Flush( UsbStorageDevice* pDevice ); - virtual void ResetUsbStorage(); protected: - virtual void MountThreadMain(); virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ); + virtual void MountThreadReset(); + virtual void MountThreadDoOneUpdate(); - bool m_bReset; + DWORD m_dwLastLogicalDrives; }; #endif diff --git a/stepmania/src/arch/MemoryCard/MemoryCardDriver_Null.h b/stepmania/src/arch/MemoryCard/MemoryCardDriver_Null.h index d8c9b16c00..6159ed1c13 100644 --- a/stepmania/src/arch/MemoryCard/MemoryCardDriver_Null.h +++ b/stepmania/src/arch/MemoryCard/MemoryCardDriver_Null.h @@ -13,7 +13,8 @@ public: virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) {} virtual void Flush( UsbStorageDevice* pDevice ) {} virtual void ResetUsbStorage() {} - + virtual void PauseMountingThread() {} + virtual void UnPauseMountingThread() {} }; #endif