testsup.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. testsup.c
  9. Abstract:
  10. This module implements support infrastructure for the kernel test.
  11. Author:
  12. Evan Green 5-Nov-2013
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include "ktestdrv.h"
  21. #include "testsup.h"
  22. #include "ktests.h"
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. //
  27. // Define the maximum number of tests that can be going on simultaneously.
  28. // This can be increased if necessary.
  29. //
  30. #define KTEST_MAX_CONCURRENT_TESTS 30
  31. //
  32. // Define the number of seconds to wait for a test to cancel itself.
  33. //
  34. #define KTEST_CANCEL_TIMEOUT 30
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. //
  39. // ----------------------------------------------- Internal Function Prototypes
  40. //
  41. KSTATUS
  42. KTestCreateTest (
  43. PINT Handle,
  44. PKTEST_ACTIVE_TEST *Test
  45. );
  46. PKTEST_ACTIVE_TEST
  47. KTestLookupTest (
  48. INT Handle
  49. );
  50. VOID
  51. KTestDestroyTest (
  52. PKTEST_ACTIVE_TEST Test
  53. );
  54. //
  55. // -------------------------------------------------------------------- Globals
  56. //
  57. KSPIN_LOCK KTestHandleLock;
  58. PKTEST_ACTIVE_TEST KTestHandles[KTEST_MAX_CONCURRENT_TESTS];
  59. //
  60. // Define the global test dispatch table, indexed by the test enum.
  61. //
  62. KTEST_FUNCTION_TABLE KTestFunctionTable[KTestCount] = {
  63. {NULL},
  64. {KTestPoolStressStart},
  65. {KTestPoolStressStart},
  66. {KTestWorkStressStart},
  67. {KTestThreadStressStart},
  68. {KTestDescriptorStressStart},
  69. {KTestBlockStressStart},
  70. {KTestBlockStressStart},
  71. };
  72. //
  73. // ------------------------------------------------------------------ Functions
  74. //
  75. KSTATUS
  76. KTestInitializeTestSupport (
  77. VOID
  78. )
  79. /*++
  80. Routine Description:
  81. This routine initializes the kernel test support structures.
  82. Arguments:
  83. None.
  84. Return Value:
  85. Status code.
  86. --*/
  87. {
  88. KeInitializeSpinLock(&KTestHandleLock);
  89. RtlZeroMemory(KTestHandles, sizeof(KTestHandles));
  90. return STATUS_SUCCESS;
  91. }
  92. KSTATUS
  93. KTestStartTest (
  94. PVOID Buffer,
  95. ULONG BufferSize
  96. )
  97. /*++
  98. Routine Description:
  99. This routine starts a new test invocation.
  100. Arguments:
  101. Buffer - Supplies a pointer to the user mode buffer.
  102. BufferSize - Supplies the size of the buffer in bytes.
  103. Return Value:
  104. Status code.
  105. --*/
  106. {
  107. PKTEST_ACTIVE_TEST ActiveTest;
  108. INT Handle;
  109. KSTATUS OverallStatus;
  110. PKTEST_START StartRoutine;
  111. KTEST_START_TEST StartTest;
  112. KSTATUS Status;
  113. Status = STATUS_UNSUCCESSFUL;
  114. //
  115. // Copy the parameters from user mode.
  116. //
  117. if (BufferSize < sizeof(KTEST_START_TEST)) {
  118. OverallStatus = STATUS_DATA_LENGTH_MISMATCH;
  119. goto StartTestEnd;
  120. }
  121. OverallStatus = MmCopyFromUserMode(&StartTest,
  122. Buffer,
  123. sizeof(KTEST_START_TEST));
  124. if (!KSUCCESS(OverallStatus)) {
  125. goto StartTestEnd;
  126. }
  127. //
  128. // Create a handle table entry.
  129. //
  130. Status = KTestCreateTest(&Handle, &ActiveTest);
  131. if (!KSUCCESS(Status)) {
  132. goto StartTestEnd;
  133. }
  134. OverallStatus = STATUS_SUCCESS;
  135. if ((StartTest.Parameters.TestType == KTestAll) ||
  136. (StartTest.Parameters.TestType >= KTestCount)) {
  137. Status = STATUS_INVALID_PARAMETER;
  138. goto StartTestEnd;
  139. }
  140. //
  141. // Call the corresponding start routine.
  142. //
  143. StartRoutine = KTestFunctionTable[StartTest.Parameters.TestType].Start;
  144. StartTest.Status = StartRoutine(&StartTest, ActiveTest);
  145. if (!KSUCCESS(Status)) {
  146. KTestDestroyTest(ActiveTest);
  147. goto StartTestEnd;
  148. }
  149. StartTest.Handle = Handle;
  150. StartTestEnd:
  151. StartTest.Status = Status;
  152. if (KSUCCESS(OverallStatus)) {
  153. OverallStatus = MmCopyToUserMode(Buffer,
  154. &StartTest,
  155. sizeof(KTEST_START_TEST));
  156. }
  157. return OverallStatus;
  158. }
  159. KSTATUS
  160. KTestRequestCancellation (
  161. PVOID Buffer,
  162. ULONG BufferSize
  163. )
  164. /*++
  165. Routine Description:
  166. This routine sends a cancel request to an active test.
  167. Arguments:
  168. Buffer - Supplies a pointer to the user mode buffer.
  169. BufferSize - Supplies the size of the buffer in bytes.
  170. Return Value:
  171. Status code.
  172. --*/
  173. {
  174. PKTEST_ACTIVE_TEST ActiveTest;
  175. KSTATUS OverallStatus;
  176. KTEST_CANCEL_TEST Request;
  177. KSTATUS Status;
  178. Status = STATUS_UNSUCCESSFUL;
  179. //
  180. // Copy the parameters from user mode.
  181. //
  182. if (BufferSize < sizeof(KTEST_CANCEL_TEST)) {
  183. OverallStatus = STATUS_DATA_LENGTH_MISMATCH;
  184. goto RequestCancellationEnd;
  185. }
  186. OverallStatus = MmCopyFromUserMode(&Request,
  187. Buffer,
  188. sizeof(KTEST_CANCEL_TEST));
  189. if (!KSUCCESS(OverallStatus)) {
  190. goto RequestCancellationEnd;
  191. }
  192. ActiveTest = KTestLookupTest(Request.Handle);
  193. if (ActiveTest == NULL) {
  194. Status = STATUS_INVALID_HANDLE;
  195. goto RequestCancellationEnd;
  196. }
  197. ActiveTest->Cancel = TRUE;
  198. RtlMemoryBarrier();
  199. Status = STATUS_SUCCESS;
  200. RequestCancellationEnd:
  201. Request.Status = Status;
  202. if (KSUCCESS(OverallStatus)) {
  203. OverallStatus = MmCopyToUserMode(Buffer,
  204. &Request,
  205. sizeof(KTEST_CANCEL_TEST));
  206. }
  207. return OverallStatus;
  208. }
  209. KSTATUS
  210. KTestPoll (
  211. PVOID Buffer,
  212. ULONG BufferSize
  213. )
  214. /*++
  215. Routine Description:
  216. This routine sends a status request to an active test.
  217. Arguments:
  218. Buffer - Supplies a pointer to the user mode buffer.
  219. BufferSize - Supplies the size of the buffer in bytes.
  220. Return Value:
  221. Status code.
  222. --*/
  223. {
  224. PKTEST_ACTIVE_TEST ActiveTest;
  225. KSTATUS OverallStatus;
  226. KTEST_POLL Request;
  227. KSTATUS Status;
  228. Status = STATUS_UNSUCCESSFUL;
  229. //
  230. // Copy the parameters from user mode.
  231. //
  232. if (BufferSize < sizeof(KTEST_POLL)) {
  233. OverallStatus = STATUS_DATA_LENGTH_MISMATCH;
  234. goto PollEnd;
  235. }
  236. OverallStatus = MmCopyFromUserMode(&Request, Buffer, sizeof(KTEST_POLL));
  237. if (!KSUCCESS(OverallStatus)) {
  238. goto PollEnd;
  239. }
  240. ActiveTest = KTestLookupTest(Request.Handle);
  241. if (ActiveTest == NULL) {
  242. Status = STATUS_INVALID_HANDLE;
  243. goto PollEnd;
  244. }
  245. Request.Progress = ActiveTest->Progress;
  246. Request.Total = ActiveTest->Total;
  247. Request.TestFinished = FALSE;
  248. if ((ActiveTest->ThreadsStarted == ActiveTest->Parameters.Threads) &&
  249. (ActiveTest->ThreadsFinished != 0) &&
  250. (ActiveTest->ThreadsFinished == ActiveTest->ThreadsStarted)) {
  251. Request.TestFinished = TRUE;
  252. RtlCopyMemory(&(Request.Parameters),
  253. &(ActiveTest->Parameters),
  254. sizeof(KTEST_PARAMETERS));
  255. RtlCopyMemory(&(Request.Results),
  256. &(ActiveTest->Results),
  257. sizeof(KTEST_RESULTS));
  258. //
  259. // Reap the test structure.
  260. //
  261. KTestDestroyTest(ActiveTest);
  262. }
  263. Status = STATUS_SUCCESS;
  264. PollEnd:
  265. Request.Status = Status;
  266. if (KSUCCESS(OverallStatus)) {
  267. OverallStatus = MmCopyToUserMode(Buffer,
  268. &Request,
  269. sizeof(KTEST_POLL));
  270. }
  271. return OverallStatus;
  272. }
  273. VOID
  274. KTestFlushAllTests (
  275. VOID
  276. )
  277. /*++
  278. Routine Description:
  279. This routine does not return until all tests have been cancelled or
  280. completed.
  281. Arguments:
  282. None.
  283. Return Value:
  284. None.
  285. --*/
  286. {
  287. PKTEST_ACTIVE_TEST ActiveTest;
  288. ULONG HandleIndex;
  289. ULONGLONG Timeout;
  290. for (HandleIndex = 0;
  291. HandleIndex < KTEST_MAX_CONCURRENT_TESTS;
  292. HandleIndex += 1) {
  293. ActiveTest = KTestHandles[HandleIndex];
  294. if (ActiveTest == NULL) {
  295. continue;
  296. }
  297. Timeout = KeGetRecentTimeCounter() +
  298. (HlQueryTimeCounterFrequency() * KTEST_CANCEL_TIMEOUT);
  299. ActiveTest->Cancel = TRUE;
  300. while ((ActiveTest->ThreadsStarted != ActiveTest->Parameters.Threads) ||
  301. (ActiveTest->ThreadsFinished == 0) ||
  302. (ActiveTest->ThreadsFinished != ActiveTest->ThreadsStarted)) {
  303. KeYield();
  304. if (KeGetRecentTimeCounter() > Timeout) {
  305. RtlDebugPrint("KTest: KTEST_ACTIVE_TEST 0x%x hung.\n",
  306. ActiveTest);
  307. ASSERT(FALSE);
  308. break;
  309. }
  310. }
  311. KTestDestroyTest(ActiveTest);
  312. }
  313. return;
  314. }
  315. ULONG
  316. KTestGetRandomValue (
  317. VOID
  318. )
  319. /*++
  320. Routine Description:
  321. This routine returns a random value.
  322. Arguments:
  323. None.
  324. Return Value:
  325. Returns a random 32-bit value.
  326. --*/
  327. {
  328. ULONGLONG Value;
  329. Value = HlQueryTimeCounter();
  330. Value ^= Value >> 32;
  331. return (ULONG)Value * 1103515245;
  332. }
  333. //
  334. // --------------------------------------------------------- Internal Functions
  335. //
  336. KSTATUS
  337. KTestCreateTest (
  338. PINT Handle,
  339. PKTEST_ACTIVE_TEST *Test
  340. )
  341. /*++
  342. Routine Description:
  343. This routine creates a new active test structure and handle.
  344. Arguments:
  345. Handle - Supplies a pointer where the handle will be returned.
  346. Test - Supplies a pointer where a pointer to the new test will be returned.
  347. Return Value:
  348. Status code.
  349. --*/
  350. {
  351. ULONG Index;
  352. PKTEST_ACTIVE_TEST NewTest;
  353. KSTATUS Status;
  354. ASSERT(KeGetRunLevel() == RunLevelLow);
  355. Index = -1;
  356. NewTest = MmAllocatePagedPool(sizeof(KTEST_ACTIVE_TEST),
  357. KTEST_ALLOCATION_TAG);
  358. if (NewTest == NULL) {
  359. Status = STATUS_INSUFFICIENT_RESOURCES;
  360. goto CreateActiveTestEnd;
  361. }
  362. Status = STATUS_TOO_MANY_HANDLES;
  363. RtlZeroMemory(NewTest, sizeof(KTEST_ACTIVE_TEST));
  364. KeAcquireSpinLock(&KTestHandleLock);
  365. for (Index = 0; Index < KTEST_MAX_CONCURRENT_TESTS; Index += 1) {
  366. if (KTestHandles[Index] == NULL) {
  367. KTestHandles[Index] = NewTest;
  368. Status = STATUS_SUCCESS;
  369. break;
  370. }
  371. }
  372. KeReleaseSpinLock(&KTestHandleLock);
  373. CreateActiveTestEnd:
  374. if (!KSUCCESS(Status)) {
  375. if (NewTest != NULL) {
  376. MmFreePagedPool(NewTest);
  377. NewTest = NULL;
  378. }
  379. }
  380. *Handle = Index;
  381. *Test = NewTest;
  382. return Status;
  383. }
  384. PKTEST_ACTIVE_TEST
  385. KTestLookupTest (
  386. INT Handle
  387. )
  388. /*++
  389. Routine Description:
  390. This routine looks up the test structure given a handle.
  391. Arguments:
  392. Handle - Supplies the handle returned when the test was created.
  393. Return Value:
  394. Returns a pointer to the test structure on success.
  395. NULL on failure.
  396. --*/
  397. {
  398. PKTEST_ACTIVE_TEST Test;
  399. ASSERT(KeGetRunLevel() == RunLevelLow);
  400. if (Handle >= KTEST_MAX_CONCURRENT_TESTS) {
  401. return NULL;
  402. }
  403. Test = KTestHandles[Handle];
  404. return Test;
  405. }
  406. VOID
  407. KTestDestroyTest (
  408. PKTEST_ACTIVE_TEST Test
  409. )
  410. /*++
  411. Routine Description:
  412. This routine destroys an active test and removes it from the handle table.
  413. Arguments:
  414. Test - Supplies a pointer to the test structure.
  415. Return Value:
  416. None.
  417. --*/
  418. {
  419. ULONG Index;
  420. KeAcquireSpinLock(&KTestHandleLock);
  421. for (Index = 0; Index < KTEST_MAX_CONCURRENT_TESTS; Index += 1) {
  422. if (KTestHandles[Index] == Test) {
  423. KTestHandles[Index] = NULL;
  424. break;
  425. }
  426. }
  427. KeReleaseSpinLock(&KTestHandleLock);
  428. ASSERT(Index != KTEST_MAX_CONCURRENT_TESTS);
  429. MmFreePagedPool(Test);
  430. return;
  431. }