Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
9.3 KiB

  1. #include "stdinc.h"
  2. #include "st.h"
  3. #include "stressharness.h"
  4. #define STRESSJOB_INI_SECTION_NAME (L"[StressJob]")
  5. #define STRESSJOB_INI_KEY_SLEEPTIME (L"SleepBetweenRuns")
  6. #define STRESSJOB_DEFAULT_SLEEP_TIME (50)
  7. CStressJobEntry::CStressJobEntry( CStressJobManager *pManager )
  8. {
  9. this->m_dwSleepBetweenRuns = STRESSJOB_DEFAULT_SLEEP_TIME;
  10. this->m_fStop = false;
  11. this->m_pManager = pManager;
  12. this->m_ulFailures = this->m_ulRuns = 0;
  13. }
  14. BOOL
  15. CStressJobEntry::LoadFromSettingsFile(
  16. PCWSTR pcwszFileName
  17. )
  18. {
  19. FN_PROLOG_WIN32
  20. //
  21. // Right now, we only have one setting, in the [StressJob] section, the
  22. // time to sleep between runs. If it's not present, it defaults to
  23. // 50ms.
  24. //
  25. INT ulSleepTime = 0;
  26. IFW32FALSE_EXIT(SxspGetPrivateProfileIntW(
  27. STRESSJOB_INI_SECTION_NAME,
  28. STRESSJOB_INI_KEY_SLEEPTIME,
  29. STRESSJOB_DEFAULT_SLEEP_TIME,
  30. ulSleepTime,
  31. pcwszFileName));
  32. this->m_dwSleepBetweenRuns = static_cast<DWORD>(ulSleepTime);
  33. FN_EPILOG
  34. }
  35. //
  36. // DNGN
  37. //
  38. CStressJobEntry::~CStressJobEntry()
  39. {
  40. FN_TRACE();
  41. ASSERT(this->m_hThread == CThread::GetInvalidValue());
  42. }
  43. BOOL
  44. CStressJobEntry::Stop( BOOL fWaitForCompletion )
  45. {
  46. FN_PROLOG_WIN32
  47. this->m_fStop = true;
  48. if ( fWaitForCompletion )
  49. IFW32FALSE_EXIT(this->WaitForCompletion());
  50. FN_EPILOG
  51. }
  52. BOOL
  53. CStressJobEntry::WaitForCompletion()
  54. {
  55. FN_PROLOG_WIN32
  56. if ( m_hThread != m_hThread.GetInvalidValue() )
  57. {
  58. IFW32FALSE_EXIT(WaitForSingleObject(m_hThread, INFINITE) == WAIT_OBJECT_0);
  59. }
  60. FN_EPILOG
  61. }
  62. BOOL
  63. CStressJobEntry::Cleanup()
  64. {
  65. FN_PROLOG_WIN32
  66. if ( m_hThread != m_hThread.GetInvalidValue() )
  67. {
  68. m_hThread.Win32Close();
  69. m_hThread = m_hThread.GetInvalidValue();
  70. }
  71. FN_EPILOG
  72. }
  73. BOOL
  74. CStressJobEntry::WaitForStartingGun()
  75. {
  76. FN_PROLOG_WIN32
  77. ASSERT( m_pManager != NULL );
  78. IFW32FALSE_EXIT(m_pManager->SignalAnotherJobReady());
  79. IFW32FALSE_EXIT(m_pManager->WaitForStartEvent());
  80. IFW32FALSE_EXIT(m_pManager->SignalThreadWorking());
  81. FN_EPILOG
  82. }
  83. DWORD
  84. CStressJobEntry::ThreadProc( PVOID pv )
  85. {
  86. FN_PROLOG_WIN32
  87. CStressJobEntry *pEntry = reinterpret_cast<CStressJobEntry*>(pv);
  88. PARAMETER_CHECK(pEntry != NULL);
  89. return pEntry->InternalThreadProc();
  90. FN_EPILOG
  91. }
  92. DWORD
  93. CStressJobEntry::InternalThreadProc()
  94. {
  95. if (!this->WaitForStartingGun())
  96. {
  97. const DWORD dwError = ::FusionpGetLastWin32Error();
  98. ::ReportFailure("%ls:%ls failed waiting on starting event, error %ld",
  99. static_cast<PCWSTR>(m_pManager->GetGroupName()),
  100. static_cast<PCWSTR>(this->m_buffTestName),
  101. dwError);
  102. return 0;
  103. }
  104. if (!this->SetupSelfForRun())
  105. {
  106. const DWORD dwError = ::FusionpGetLastWin32Error();
  107. ReportFailure("%ls: test %ls failed to set itself up, error %ld",
  108. static_cast<PCWSTR>(m_pManager->GetGroupName()),
  109. static_cast<PCWSTR>(this->m_buffTestName),
  110. dwError);
  111. }
  112. else
  113. {
  114. while ( !m_fStop )
  115. {
  116. bool fResult;
  117. if ( RunTest( fResult ) )
  118. {
  119. const DWORD dwError = ::FusionpGetLastWin32Error();
  120. wprintf(L"%ls: test %ls %ls, error %ld\n",
  121. static_cast<PCWSTR>(m_pManager->GetGroupName()),
  122. static_cast<PCWSTR>(this->m_buffTestName),
  123. fResult ? L"passes" : L"fails",
  124. dwError);
  125. }
  126. else
  127. {
  128. const DWORD dwError = ::FusionpGetLastWin32Error();
  129. ReportFailure("%ls: test %ls failed to complete? Error %ld",
  130. static_cast<PCWSTR>(m_pManager->GetGroupName()),
  131. static_cast<PCWSTR>(this->m_buffTestName),
  132. dwError);
  133. }
  134. ::Sleep(this->m_dwSleepBetweenRuns);
  135. }
  136. }
  137. m_pManager->SignalThreadDone();
  138. return 1;
  139. }
  140. BOOL
  141. CStressJobManager::SignalThreadWorking()
  142. {
  143. InterlockedIncrement((PLONG)&m_ulThreadsWorking);
  144. return TRUE;
  145. }
  146. BOOL
  147. CStressJobManager::SignalThreadDone()
  148. {
  149. InterlockedDecrement((PLONG)&m_ulThreadsWorking);
  150. return TRUE;
  151. }
  152. CStressJobManager::CStressJobManager()
  153. {
  154. if (!this->m_hStartingGunEvent.Win32CreateEvent(TRUE, FALSE))
  155. {
  156. DebugBreak();
  157. }
  158. m_ulThreadsCreated = 0;
  159. m_ulThreadsReady = 0;
  160. m_ulThreadsWorking = 0;
  161. }
  162. CStressJobManager::~CStressJobManager()
  163. {
  164. }
  165. BOOL
  166. CStressJobManager::StartJobs()
  167. {
  168. FN_PROLOG_WIN32
  169. while ( m_ulThreadsReady != m_ulThreadsCreated )
  170. ::Sleep(10);
  171. ASSERT(m_hStartingGunEvent != CEvent::GetInvalidValue());
  172. IFW32FALSE_EXIT(SetEvent(m_hStartingGunEvent));
  173. FN_EPILOG
  174. }
  175. BOOL
  176. CStressJobManager::CleanupJobs()
  177. {
  178. FN_PROLOG_WIN32
  179. CStressEntryDequeIterator Iter(&this->m_JobsListed);
  180. for (Iter.Reset(); Iter.More(); Iter.Next())
  181. {
  182. CStressJobEntry *pItem = Iter.Current();
  183. pItem->Cleanup();
  184. }
  185. m_JobsListed.ClearAndDeleteAll();
  186. FN_EPILOG
  187. }
  188. BOOL
  189. CStressJobManager::StopJobs(
  190. BOOL fWithWaitForComplete
  191. )
  192. {
  193. FN_PROLOG_WIN32
  194. CStressEntryDequeIterator Iter(&this->m_JobsListed);
  195. for ( Iter.Reset(); Iter.More(); Iter.Next() )
  196. {
  197. CStressJobEntry *pItem = Iter.Current();
  198. pItem->Stop(fWithWaitForComplete);
  199. }
  200. FN_EPILOG
  201. }
  202. BOOL
  203. CStressJobManager::WaitForAllJobsComplete()
  204. {
  205. FN_PROLOG_WIN32
  206. CStressEntryDequeIterator Iter(&this->m_JobsListed);
  207. for (Iter.Reset(); Iter.More(); Iter.Next())
  208. {
  209. CStressJobEntry *pItem = Iter.Current();
  210. pItem->WaitForCompletion();
  211. }
  212. FN_EPILOG
  213. }
  214. BOOL CStressJobManager::CreateWorkerThreads( PULONG pulThreadsCreated )
  215. {
  216. FN_PROLOG_WIN32
  217. CStressEntryDequeIterator Iter(&this->m_JobsListed);
  218. INTERNAL_ERROR_CHECK( m_ulThreadsCreated == 0 );
  219. if ( pulThreadsCreated ) *pulThreadsCreated = 0;
  220. m_ulThreadsCreated = 0;
  221. for ( Iter.Reset(); Iter.More(); Iter.Next() )
  222. {
  223. CStressJobEntry *pType = Iter.Current();
  224. IFW32FALSE_EXIT(pType->m_hThread.Win32CreateThread( pType->ThreadProc, pType ));
  225. this->m_ulThreadsCreated++;
  226. }
  227. if ( pulThreadsCreated ) *pulThreadsCreated = m_ulThreadsCreated;
  228. FN_EPILOG
  229. }
  230. BOOL CStressJobManager::SignalAnotherJobReady()
  231. {
  232. ::InterlockedIncrement((PLONG)&m_ulThreadsReady);
  233. return TRUE;
  234. }
  235. BOOL CStressJobManager::WaitForStartEvent()
  236. {
  237. return WaitForSingleObject( this->m_hStartingGunEvent, INFINITE ) == WAIT_OBJECT_0;
  238. }
  239. BOOL CStressJobManager::LoadFromDirectory(
  240. PCWSTR pcwszDirectoryName,
  241. PULONG pulJobsFound
  242. )
  243. {
  244. FN_PROLOG_WIN32
  245. CStringBuffer buffSearchString;
  246. CFindFile Finder;
  247. WIN32_FIND_DATAW FindData;
  248. PARAMETER_CHECK(pcwszDirectoryName);
  249. if ( pulJobsFound ) *pulJobsFound = 0;
  250. IFW32FALSE_EXIT(buffSearchString.Win32Assign(pcwszDirectoryName, ::wcslen(pcwszDirectoryName)));
  251. IFW32FALSE_EXIT(buffSearchString.Win32AppendPathElement(L"*", 1));
  252. Finder = ::FindFirstFileW(buffSearchString, &FindData);
  253. if (Finder == INVALID_HANDLE_VALUE)
  254. {
  255. ::ReportFailure("No tests found in directory %ls", pcwszDirectoryName);
  256. FN_SUCCESSFUL_EXIT();
  257. }
  258. IFW32FALSE_EXIT(buffSearchString.Win32RemoveLastPathElement());
  259. do
  260. {
  261. if (FusionpIsDotOrDotDot(FindData.cFileName))
  262. continue;
  263. CStringBuffer buffFoundName;
  264. CStressJobEntry *pNextEntry = NULL;
  265. IFW32FALSE_EXIT(buffFoundName.Win32Assign(buffSearchString));
  266. IFW32FALSE_EXIT(buffFoundName.Win32AppendPathElement(
  267. FindData.cFileName,
  268. ::wcslen(FindData.cFileName)));
  269. //
  270. // Let's get ourselves another job entry
  271. //
  272. IFW32FALSE_EXIT(this->CreateJobEntry(pNextEntry));
  273. INTERNAL_ERROR_CHECK(pNextEntry != NULL);
  274. //
  275. // Name and full path of test directory
  276. //
  277. IFW32FALSE_EXIT(pNextEntry->m_buffTestDirectory.Win32Assign(buffFoundName));
  278. IFW32FALSE_EXIT(pNextEntry->m_buffTestName.Win32Assign(
  279. FindData.cFileName,
  280. ::wcslen(FindData.cFileName)));
  281. //
  282. // And now have it load settings
  283. //
  284. IFW32FALSE_EXIT(buffFoundName.Win32AppendPathElement(
  285. this->GetIniFileName(),
  286. ::wcslen(this->GetIniFileName())));
  287. IFW32FALSE_EXIT(pNextEntry->LoadFromSettingsFile(buffFoundName));
  288. //
  289. // So far, so good - add it to the list of created job entries
  290. //
  291. this->m_JobsListed.AddToTail(pNextEntry);
  292. pNextEntry = NULL;
  293. }
  294. while ( ::FindNextFileW(Finder, &FindData) );
  295. if (::FusionpGetLastWin32Error() != ERROR_NO_MORE_FILES)
  296. goto Exit;
  297. //
  298. // Outward bound?
  299. //
  300. if ( pulJobsFound )
  301. *pulJobsFound = static_cast<ULONG>(this->m_JobsListed.GetEntryCount());
  302. FN_EPILOG
  303. }