synchronize access to memory cards between mounting thread and main thread Profile Load/Save

This commit is contained in:
Chris Danford
2004-06-06 02:41:16 +00:00
parent 5c7dd115ad
commit 110ec3d331
11 changed files with 190 additions and 143 deletions
+9
View File
@@ -295,6 +295,15 @@ CString MemoryCardManager::GetName( PlayerNumber pn ) const
return m_Device[pn].sName; return m_Device[pn].sName;
} }
void MemoryCardManager::PauseMountingThread()
{
m_pDriver->PauseMountingThread();
}
void MemoryCardManager::UnPauseMountingThread()
{
m_pDriver->UnPauseMountingThread();
}
bool IsAnyPlayerUsingMemoryCard() bool IsAnyPlayerUsingMemoryCard()
{ {
+3
View File
@@ -37,6 +37,9 @@ public:
void LockCards( bool bLock ); // prevent removing or changing of memory cards 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 void FlushAndReset(); // force all files to be written to mounted memory cards
bool PathIsMemCard( CString sDir ) const; bool PathIsMemCard( CString sDir ) const;
+14 -1
View File
@@ -84,6 +84,9 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs
ASSERT( !sProfileDir.empty() ); ASSERT( !sProfileDir.empty() );
ASSERT( sProfileDir.Right(1) == "/" ); ASSERT( sProfileDir.Right(1) == "/" );
if( bIsMemCard )
MEMCARDMAN->PauseMountingThread();
m_sProfileDir[pn] = sProfileDir; m_sProfileDir[pn] = sProfileDir;
m_bWasLoadedFromMemoryCard[pn] = bIsMemCard; m_bWasLoadedFromMemoryCard[pn] = bIsMemCard;
@@ -92,6 +95,8 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs
else else
m_Profile[pn].LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); m_Profile[pn].LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData );
MEMCARDMAN->UnPauseMountingThread();
LOG->Trace( "Done loading profile." ); LOG->Trace( "Done loading profile." );
return true; return true;
@@ -200,7 +205,15 @@ bool ProfileManager::SaveProfile( PlayerNumber pn ) const
if( m_sProfileDir[pn].empty() ) if( m_sProfileDir[pn].empty() )
return false; 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 ) void ProfileManager::UnloadProfile( PlayerNumber pn )
@@ -57,6 +57,8 @@ public:
virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0; virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0;
virtual void Flush( UsbStorageDevice* pDevice ) = 0; virtual void Flush( UsbStorageDevice* pDevice ) = 0;
virtual void ResetUsbStorage() = 0; virtual void ResetUsbStorage() = 0;
virtual void PauseMountingThread() = 0;
virtual void UnPauseMountingThread() = 0;
}; };
#endif #endif
@@ -5,12 +5,6 @@
#include "RageFileManager.h" #include "RageFileManager.h"
int MemoryCardDriverThreaded::MountThread_Start( void *p )
{
((MemoryCardDriverThreaded*)p)->MountThreadMain();
return 0;
}
template<class T> template<class T>
bool VectorsAreEqual( const T &a, const T &b ) bool VectorsAreEqual( const T &a, const T &b )
{ {
@@ -27,9 +21,11 @@ bool VectorsAreEqual( const T &a, const T &b )
} }
MemoryCardDriverThreaded::MemoryCardDriverThreaded() : MemoryCardDriverThreaded::MemoryCardDriverThreaded() :
m_mutexStorageDevices("StorageDevices") m_mutexPause("Pause"),
m_mutexStorageDevices("StorageDevices")
{ {
m_bShutdown = false; m_bShutdownNextUpdate = false;
m_bResetNextUpdate = false;
m_bStorageDevicesChanged = false; m_bStorageDevicesChanged = false;
} }
@@ -41,12 +37,42 @@ void MemoryCardDriverThreaded::StartThread()
MemoryCardDriverThreaded::~MemoryCardDriverThreaded() MemoryCardDriverThreaded::~MemoryCardDriverThreaded()
{ {
m_bShutdown = true; m_bShutdownNextUpdate = true;
LOG->Trace( "Shutting down Mount thread..." ); LOG->Trace( "Shutting down Mount thread..." );
m_threadMemoryCardMount.Wait(); m_threadMemoryCardMount.Wait();
LOG->Trace( "Mount thread shut down." ); 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() bool MemoryCardDriverThreaded::StorageDevicesChanged()
{ {
LockMut( m_mutexStorageDevices ); LockMut( m_mutexStorageDevices );
@@ -86,6 +112,11 @@ bool MemoryCardDriverThreaded::MountAndTestWrite( UsbStorageDevice* pDevice, CSt
return true; return true;
} }
void MemoryCardDriverThreaded::ResetUsbStorage()
{
m_bResetNextUpdate = true;
}
/* /*
* (c) 2003-2004 Chris Danford * (c) 2003-2004 Chris Danford
* All rights reserved. * All rights reserved.
@@ -21,18 +21,32 @@ class MemoryCardDriverThreaded : public MemoryCardDriver
public: public:
MemoryCardDriverThreaded(); MemoryCardDriverThreaded();
~MemoryCardDriverThreaded(); ~MemoryCardDriverThreaded();
void StartThread(); // call this in the derived constructor to start the mounting thread
virtual bool StorageDevicesChanged(); virtual bool StorageDevicesChanged();
virtual void GetStorageDevices( vector<UsbStorageDevice>& vStorageDevicesOut ); virtual void GetStorageDevices( vector<UsbStorageDevice>& vStorageDevicesOut );
virtual bool MountAndTestWrite( UsbStorageDevice* pDevice, CString sMountPoint ); virtual bool MountAndTestWrite( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void ResetUsbStorage();
virtual void PauseMountingThread();
virtual void UnPauseMountingThread();
private:
static int MountThread_Start( void *p ); static int MountThread_Start( void *p );
protected: void MountThreadMain();
virtual void MountThreadMain() = 0;
virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0;
RageThread m_threadMemoryCardMount; 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<UsbStorageDeviceEx> m_vStorageDevices; vector<UsbStorageDeviceEx> m_vStorageDevices;
bool m_bStorageDevicesChanged; bool m_bStorageDevicesChanged;
@@ -124,28 +124,44 @@ static bool ExecuteCommand( CCStringRef sCommand )
return ret == 0; return ret == 0;
} }
void MemoryCardDriverThreaded_Linux::MountThreadMain() MemoryCardDriverThreaded_Linux::MemoryCardDriverThreaded_Linux()
{ {
int fd = open(USB_DEVICE_LIST_FILE, O_RDONLY); m_fd = open(USB_DEVICE_LIST_FILE, O_RDONLY);
if( fd == -1 ) if( m_fd == -1 )
{ {
LOG->Warn( "Failed to open \"%s\": %s", USB_DEVICE_LIST_FILE, strerror(errno) ); LOG->Warn( "Failed to open \"%s\": %s", USB_DEVICE_LIST_FILE, strerror(errno) );
}
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<m_vStorageDevices.size(); i++ )
{
UsbStorageDeviceEx &d = m_vStorageDevices[i];
CString sCommand = "umount " + d.sOsMountDir;
ExecuteCommand( sCommand );
}
ExecuteCommand( "rmmod usb-storage" );
ExecuteCommand( "modprobe usb-storage" );
m_vDevicesLastSeen.clear(); // redetect all devices
}
void MemoryCardDriverThreaded_Linux::MountThreadDoOneUpdate()
{
if( m_fd == -1 )
return; return;
}
vector<UsbStorageDeviceEx> vDevicesLastSeen; pollfd pfd = { m_fd, POLLIN, 0 };
while( !m_bShutdown )
{
if( m_bReset )
{
// force all to be re-detected
vDevicesLastSeen.clear();
m_bReset = false;
}
else
{
pollfd pfd = { fd, POLLIN, 0 };
int ret = poll( &pfd, 1, 100 ); int ret = poll( &pfd, 1, 100 );
switch( ret ) switch( ret )
{ {
@@ -153,12 +169,11 @@ void MemoryCardDriverThreaded_Linux::MountThreadMain()
// file changed. Fall through. // file changed. Fall through.
break; break;
case 0: // no change. Poll again. case 0: // no change. Poll again.
continue; return;
case -1: case -1:
if( errno != EINTR ) if( errno != EINTR )
LOG->Warn( "Error polling: %s", strerror(errno) ); LOG->Warn( "Error polling: %s", strerror(errno) );
continue; return;
}
} }
// TRICKY: We're waiting for a change in the USB device list, but // TRICKY: We're waiting for a change in the USB device list, but
@@ -172,7 +187,7 @@ void MemoryCardDriverThreaded_Linux::MountThreadMain()
GetNewStorageDevices( vDevicesNow ); GetNewStorageDevices( vDevicesNow );
vector<UsbStorageDeviceEx> &vNew = vDevicesNow; vector<UsbStorageDeviceEx> &vNew = vDevicesNow;
vector<UsbStorageDeviceEx> &vOld = vDevicesLastSeen; vector<UsbStorageDeviceEx> &vOld = m_vDevicesLastSeen;
// check for disconnects // check for disconnects
vector<UsbStorageDeviceEx*> vDisconnects; vector<UsbStorageDeviceEx*> vDisconnects;
@@ -246,18 +261,11 @@ void MemoryCardDriverThreaded_Linux::MountThreadMain()
} }
} }
vDevicesLastSeen = vDevicesNow; m_vDevicesLastSeen = vDevicesNow;
}
CHECKPOINT; CHECKPOINT;
} }
MemoryCardDriverThreaded_Linux::MemoryCardDriverThreaded_Linux()
{
m_bReset = false;
this->StartThread();
}
bool ReadUsbStorageDescriptor( CString fn, int iScsiIndex, vector<UsbStorageDeviceEx>& vDevicesOut ) bool ReadUsbStorageDescriptor( CString fn, int iScsiIndex, vector<UsbStorageDeviceEx>& vDevicesOut )
{ {
LOG->Trace( "ReadUsbStorageDescriptor %s", fn.c_str() ); LOG->Trace( "ReadUsbStorageDescriptor %s", fn.c_str() );
@@ -631,30 +639,6 @@ void MemoryCardDriverThreaded_Linux::Flush( UsbStorageDevice* pDevice )
ExecuteCommand( "mount -o remount " + pDevice->sOsMountDir ); 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_vStorageDevices.size(); i++ )
{
UsbStorageDeviceEx &d = m_vStorageDevices[i];
CString sCommand = "umount " + d.sOsMountDir;
ExecuteCommand( sCommand );
}
ExecuteCommand( "rmmod usb-storage" );
ExecuteCommand( "modprobe usb-storage" );
m_bReset = true;
// let the mounting thread re-mount everything
}
/* /*
* (c) 2003-2004 Chris Danford * (c) 2003-2004 Chris Danford
* All rights reserved. * All rights reserved.
@@ -10,12 +10,13 @@ public:
virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ); virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void Flush( UsbStorageDevice* pDevice ); virtual void Flush( UsbStorageDevice* pDevice );
virtual void ResetUsbStorage();
protected: protected:
virtual void MountThreadMain();
virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ); virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void MountThreadReset();
virtual void MountThreadDoOneUpdate();
bool m_bReset; int m_fd;
vector<UsbStorageDeviceEx> m_vDevicesLastSeen;
}; };
#endif #endif
@@ -7,14 +7,13 @@
#include "RageLog.h" #include "RageLog.h"
#include "Profile.h" #include "Profile.h"
#include "PrefsManager.h" #include "PrefsManager.h"
#include <windows.h>
const CString TEMP_MOUNT_POINT = "@mctemp/"; const CString TEMP_MOUNT_POINT = "@mctemp/";
MemoryCardDriverThreaded_Windows::MemoryCardDriverThreaded_Windows() MemoryCardDriverThreaded_Windows::MemoryCardDriverThreaded_Windows()
{ {
m_bReset = false; m_dwLastLogicalDrives = 0;
StartThread(); StartThread();
} }
@@ -55,20 +54,15 @@ static bool TestWrite( CCStringRef sDrive )
return true; return true;
} }
void MemoryCardDriverThreaded_Windows::MountThreadMain() void MemoryCardDriverThreaded_Windows::MountThreadReset()
{ {
DWORD dwLastLogicalDrives = 0; m_dwLastLogicalDrives = 0;
}
while( !m_bShutdown )
{
if( m_bReset )
{
dwLastLogicalDrives = 0;
m_bReset = false;
}
void MemoryCardDriverThreaded_Windows::MountThreadDoOneUpdate()
{
DWORD dwNewLogicalDrives = ::GetLogicalDrives(); DWORD dwNewLogicalDrives = ::GetLogicalDrives();
if( dwNewLogicalDrives != dwLastLogicalDrives ) if( dwNewLogicalDrives != m_dwLastLogicalDrives )
{ {
vector<UsbStorageDeviceEx> vNewStorageDevices; vector<UsbStorageDeviceEx> vNewStorageDevices;
@@ -110,10 +104,9 @@ void MemoryCardDriverThreaded_Windows::MountThreadMain()
m_vStorageDevices = vNewStorageDevices; m_vStorageDevices = vNewStorageDevices;
} }
} }
dwLastLogicalDrives = dwNewLogicalDrives; m_dwLastLogicalDrives = dwNewLogicalDrives;
::Sleep( 100 ); ::Sleep( 100 );
}
} }
void MemoryCardDriverThreaded_Windows::Mount( UsbStorageDevice* pDevice, CString sMountPoint ) 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 // Windows flushes automatically every ~2 seconds. -Chris
} }
void MemoryCardDriverThreaded_Windows::ResetUsbStorage()
{
m_bReset = true;
}
/* /*
* (c) 2003-2004 Chris Danford * (c) 2003-2004 Chris Danford
* All rights reserved. * All rights reserved.
@@ -2,6 +2,7 @@
#define MemoryCardDriverThreaded_Windows_H 1 #define MemoryCardDriverThreaded_Windows_H 1
#include "MemoryCardDriverThreaded.h" #include "MemoryCardDriverThreaded.h"
#include <windows.h>
class MemoryCardDriverThreaded_Windows : public MemoryCardDriverThreaded class MemoryCardDriverThreaded_Windows : public MemoryCardDriverThreaded
{ {
@@ -10,12 +11,12 @@ public:
virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ); virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void Flush( UsbStorageDevice* pDevice ); virtual void Flush( UsbStorageDevice* pDevice );
virtual void ResetUsbStorage();
protected: protected:
virtual void MountThreadMain();
virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ); virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void MountThreadReset();
virtual void MountThreadDoOneUpdate();
bool m_bReset; DWORD m_dwLastLogicalDrives;
}; };
#endif #endif
@@ -13,7 +13,8 @@ public:
virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) {} virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint ) {}
virtual void Flush( UsbStorageDevice* pDevice ) {} virtual void Flush( UsbStorageDevice* pDevice ) {}
virtual void ResetUsbStorage() {} virtual void ResetUsbStorage() {}
virtual void PauseMountingThread() {}
virtual void UnPauseMountingThread() {}
}; };
#endif #endif