|
|
#include "stdinc.h"
#include "st.h"
#include "stressharness.h"
#define STRESSJOB_INI_SECTION_NAME (L"[StressJob]")
#define STRESSJOB_INI_KEY_SLEEPTIME (L"SleepBetweenRuns")
#define STRESSJOB_DEFAULT_SLEEP_TIME (50)
CStressJobEntry::CStressJobEntry( CStressJobManager *pManager ) { this->m_dwSleepBetweenRuns = STRESSJOB_DEFAULT_SLEEP_TIME; this->m_fStop = false; this->m_pManager = pManager; this->m_ulFailures = this->m_ulRuns = 0; }
BOOL CStressJobEntry::LoadFromSettingsFile( PCWSTR pcwszFileName ) { FN_PROLOG_WIN32
//
// Right now, we only have one setting, in the [StressJob] section, the
// time to sleep between runs. If it's not present, it defaults to
// 50ms.
//
INT ulSleepTime = 0; IFW32FALSE_EXIT(SxspGetPrivateProfileIntW( STRESSJOB_INI_SECTION_NAME, STRESSJOB_INI_KEY_SLEEPTIME, STRESSJOB_DEFAULT_SLEEP_TIME, ulSleepTime, pcwszFileName)); this->m_dwSleepBetweenRuns = static_cast<DWORD>(ulSleepTime); FN_EPILOG }
//
// DNGN
//
CStressJobEntry::~CStressJobEntry() { FN_TRACE(); ASSERT(this->m_hThread == CThread::GetInvalidValue()); }
BOOL CStressJobEntry::Stop( BOOL fWaitForCompletion ) { FN_PROLOG_WIN32 this->m_fStop = true; if ( fWaitForCompletion ) IFW32FALSE_EXIT(this->WaitForCompletion()); FN_EPILOG }
BOOL CStressJobEntry::WaitForCompletion() { FN_PROLOG_WIN32 if ( m_hThread != m_hThread.GetInvalidValue() ) { IFW32FALSE_EXIT(WaitForSingleObject(m_hThread, INFINITE) == WAIT_OBJECT_0); } FN_EPILOG }
BOOL CStressJobEntry::Cleanup() { FN_PROLOG_WIN32 if ( m_hThread != m_hThread.GetInvalidValue() ) { m_hThread.Win32Close(); m_hThread = m_hThread.GetInvalidValue(); } FN_EPILOG }
BOOL CStressJobEntry::WaitForStartingGun() { FN_PROLOG_WIN32 ASSERT( m_pManager != NULL ); IFW32FALSE_EXIT(m_pManager->SignalAnotherJobReady()); IFW32FALSE_EXIT(m_pManager->WaitForStartEvent()); IFW32FALSE_EXIT(m_pManager->SignalThreadWorking()); FN_EPILOG }
DWORD CStressJobEntry::ThreadProc( PVOID pv ) { FN_PROLOG_WIN32 CStressJobEntry *pEntry = reinterpret_cast<CStressJobEntry*>(pv); PARAMETER_CHECK(pEntry != NULL); return pEntry->InternalThreadProc(); FN_EPILOG }
DWORD CStressJobEntry::InternalThreadProc() { if (!this->WaitForStartingGun()) { const DWORD dwError = ::FusionpGetLastWin32Error(); ::ReportFailure("%ls:%ls failed waiting on starting event, error %ld", static_cast<PCWSTR>(m_pManager->GetGroupName()), static_cast<PCWSTR>(this->m_buffTestName), dwError); return 0; }
if (!this->SetupSelfForRun()) { const DWORD dwError = ::FusionpGetLastWin32Error(); ReportFailure("%ls: test %ls failed to set itself up, error %ld", static_cast<PCWSTR>(m_pManager->GetGroupName()), static_cast<PCWSTR>(this->m_buffTestName), dwError); } else {
while ( !m_fStop ) { bool fResult; if ( RunTest( fResult ) ) { const DWORD dwError = ::FusionpGetLastWin32Error(); wprintf(L"%ls: test %ls %ls, error %ld\n", static_cast<PCWSTR>(m_pManager->GetGroupName()), static_cast<PCWSTR>(this->m_buffTestName), fResult ? L"passes" : L"fails", dwError); } else { const DWORD dwError = ::FusionpGetLastWin32Error(); ReportFailure("%ls: test %ls failed to complete? Error %ld", static_cast<PCWSTR>(m_pManager->GetGroupName()), static_cast<PCWSTR>(this->m_buffTestName), dwError); }
::Sleep(this->m_dwSleepBetweenRuns); } } m_pManager->SignalThreadDone();
return 1; }
BOOL CStressJobManager::SignalThreadWorking() { InterlockedIncrement((PLONG)&m_ulThreadsWorking); return TRUE; }
BOOL CStressJobManager::SignalThreadDone() { InterlockedDecrement((PLONG)&m_ulThreadsWorking); return TRUE; }
CStressJobManager::CStressJobManager() { if (!this->m_hStartingGunEvent.Win32CreateEvent(TRUE, FALSE)) { DebugBreak(); }
m_ulThreadsCreated = 0; m_ulThreadsReady = 0; m_ulThreadsWorking = 0; }
CStressJobManager::~CStressJobManager() { }
BOOL CStressJobManager::StartJobs() { FN_PROLOG_WIN32 while ( m_ulThreadsReady != m_ulThreadsCreated ) ::Sleep(10);
ASSERT(m_hStartingGunEvent != CEvent::GetInvalidValue()); IFW32FALSE_EXIT(SetEvent(m_hStartingGunEvent));
FN_EPILOG }
BOOL CStressJobManager::CleanupJobs() { FN_PROLOG_WIN32 CStressEntryDequeIterator Iter(&this->m_JobsListed); for (Iter.Reset(); Iter.More(); Iter.Next()) { CStressJobEntry *pItem = Iter.Current(); pItem->Cleanup(); } m_JobsListed.ClearAndDeleteAll(); FN_EPILOG }
BOOL CStressJobManager::StopJobs( BOOL fWithWaitForComplete ) { FN_PROLOG_WIN32 CStressEntryDequeIterator Iter(&this->m_JobsListed); for ( Iter.Reset(); Iter.More(); Iter.Next() ) { CStressJobEntry *pItem = Iter.Current(); pItem->Stop(fWithWaitForComplete); }
FN_EPILOG }
BOOL CStressJobManager::WaitForAllJobsComplete() { FN_PROLOG_WIN32 CStressEntryDequeIterator Iter(&this->m_JobsListed); for (Iter.Reset(); Iter.More(); Iter.Next()) { CStressJobEntry *pItem = Iter.Current(); pItem->WaitForCompletion(); } FN_EPILOG }
BOOL CStressJobManager::CreateWorkerThreads( PULONG pulThreadsCreated ) { FN_PROLOG_WIN32
CStressEntryDequeIterator Iter(&this->m_JobsListed);
INTERNAL_ERROR_CHECK( m_ulThreadsCreated == 0 );
if ( pulThreadsCreated ) *pulThreadsCreated = 0; m_ulThreadsCreated = 0;
for ( Iter.Reset(); Iter.More(); Iter.Next() ) { CStressJobEntry *pType = Iter.Current(); IFW32FALSE_EXIT(pType->m_hThread.Win32CreateThread( pType->ThreadProc, pType )); this->m_ulThreadsCreated++; }
if ( pulThreadsCreated ) *pulThreadsCreated = m_ulThreadsCreated;
FN_EPILOG }
BOOL CStressJobManager::SignalAnotherJobReady() { ::InterlockedIncrement((PLONG)&m_ulThreadsReady); return TRUE; }
BOOL CStressJobManager::WaitForStartEvent() { return WaitForSingleObject( this->m_hStartingGunEvent, INFINITE ) == WAIT_OBJECT_0; }
BOOL CStressJobManager::LoadFromDirectory( PCWSTR pcwszDirectoryName, PULONG pulJobsFound ) { FN_PROLOG_WIN32
CStringBuffer buffSearchString; CFindFile Finder; WIN32_FIND_DATAW FindData;
PARAMETER_CHECK(pcwszDirectoryName); if ( pulJobsFound ) *pulJobsFound = 0;
IFW32FALSE_EXIT(buffSearchString.Win32Assign(pcwszDirectoryName, ::wcslen(pcwszDirectoryName))); IFW32FALSE_EXIT(buffSearchString.Win32AppendPathElement(L"*", 1));
Finder = ::FindFirstFileW(buffSearchString, &FindData); if (Finder == INVALID_HANDLE_VALUE) { ::ReportFailure("No tests found in directory %ls", pcwszDirectoryName); FN_SUCCESSFUL_EXIT(); }
IFW32FALSE_EXIT(buffSearchString.Win32RemoveLastPathElement());
do { if (FusionpIsDotOrDotDot(FindData.cFileName)) continue;
CStringBuffer buffFoundName; CStressJobEntry *pNextEntry = NULL;
IFW32FALSE_EXIT(buffFoundName.Win32Assign(buffSearchString)); IFW32FALSE_EXIT(buffFoundName.Win32AppendPathElement( FindData.cFileName, ::wcslen(FindData.cFileName)));
//
// Let's get ourselves another job entry
//
IFW32FALSE_EXIT(this->CreateJobEntry(pNextEntry)); INTERNAL_ERROR_CHECK(pNextEntry != NULL);
//
// Name and full path of test directory
//
IFW32FALSE_EXIT(pNextEntry->m_buffTestDirectory.Win32Assign(buffFoundName)); IFW32FALSE_EXIT(pNextEntry->m_buffTestName.Win32Assign( FindData.cFileName, ::wcslen(FindData.cFileName)));
//
// And now have it load settings
//
IFW32FALSE_EXIT(buffFoundName.Win32AppendPathElement( this->GetIniFileName(), ::wcslen(this->GetIniFileName()))); IFW32FALSE_EXIT(pNextEntry->LoadFromSettingsFile(buffFoundName));
//
// So far, so good - add it to the list of created job entries
//
this->m_JobsListed.AddToTail(pNextEntry); pNextEntry = NULL; } while ( ::FindNextFileW(Finder, &FindData) );
if (::FusionpGetLastWin32Error() != ERROR_NO_MORE_FILES) goto Exit;
//
// Outward bound?
//
if ( pulJobsFound ) *pulJobsFound = static_cast<ULONG>(this->m_JobsListed.GetEntryCount());
FN_EPILOG }
|