tpool.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. tpool.c
  9. Abstract:
  10. This module implements the kernel pool tests.
  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. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. #define KTEST_POOL_DEFAULT_ITERATIONS 500000
  26. #define KTEST_POOL_DEFAULT_THREAD_COUNT 5
  27. #define KTEST_POOL_DEFAULT_ALLOCATION_COUNT 500
  28. #define KTEST_POOL_DEFAULT_ALLOCATION_SIZE 4096
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. VOID
  36. KTestPoolStressRoutine (
  37. PVOID Parameter
  38. );
  39. //
  40. // -------------------------------------------------------------------- Globals
  41. //
  42. //
  43. // ------------------------------------------------------------------ Functions
  44. //
  45. KSTATUS
  46. KTestPoolStressStart (
  47. PKTEST_START_TEST Command,
  48. PKTEST_ACTIVE_TEST Test
  49. )
  50. /*++
  51. Routine Description:
  52. This routine starts a new invocation of the paged and non-paged pool stress
  53. test.
  54. Arguments:
  55. Command - Supplies a pointer to the start command.
  56. Test - Supplies a pointer to the active test structure to initialize.
  57. Return Value:
  58. Status code.
  59. --*/
  60. {
  61. PKTEST_PARAMETERS Parameters;
  62. KSTATUS Status;
  63. ULONG ThreadIndex;
  64. Parameters = &(Test->Parameters);
  65. RtlCopyMemory(Parameters, &(Command->Parameters), sizeof(KTEST_PARAMETERS));
  66. if (Parameters->Iterations == 0) {
  67. Parameters->Iterations = KTEST_POOL_DEFAULT_ITERATIONS;
  68. }
  69. if (Parameters->Threads == 0) {
  70. Parameters->Threads = KTEST_POOL_DEFAULT_THREAD_COUNT;
  71. }
  72. if (Parameters->Parameters[0] == 0) {
  73. Parameters->Parameters[0] = KTEST_POOL_DEFAULT_ALLOCATION_COUNT;
  74. }
  75. if (Parameters->Parameters[1] == 0) {
  76. Parameters->Parameters[1] = KTEST_POOL_DEFAULT_ALLOCATION_SIZE;
  77. }
  78. Test->Total = Test->Parameters.Iterations;
  79. Test->Results.Status = STATUS_SUCCESS;
  80. Test->Results.Failures = 0;
  81. for (ThreadIndex = 0;
  82. ThreadIndex < Test->Parameters.Threads;
  83. ThreadIndex += 1) {
  84. Status = PsCreateKernelThread(KTestPoolStressRoutine,
  85. Test,
  86. "KTestPoolStressRoutine");
  87. if (!KSUCCESS(Status)) {
  88. goto PoolStressStartEnd;
  89. }
  90. }
  91. Status = STATUS_SUCCESS;
  92. PoolStressStartEnd:
  93. return Status;
  94. }
  95. //
  96. // --------------------------------------------------------- Internal Functions
  97. //
  98. VOID
  99. KTestPoolStressRoutine (
  100. PVOID Parameter
  101. )
  102. /*++
  103. Routine Description:
  104. This routine implements the paged pool stress test.
  105. Arguments:
  106. Parameter - Supplies a pointer to the thread parameter, which in this
  107. case is a pointer to the active test structure.
  108. Return Value:
  109. None.
  110. --*/
  111. {
  112. UINTN AllocatedMemory;
  113. PUCHAR Allocation;
  114. UINTN AllocationCount;
  115. PVOID *Array;
  116. UINTN ArraySize;
  117. ULONG Failures;
  118. UINTN Index;
  119. PKTEST_ACTIVE_TEST Information;
  120. UINTN Iteration;
  121. UINTN MaxAllocatedMemory;
  122. UINTN MaxAllocationCount;
  123. UINTN MaxAllocationSize;
  124. UINTN MaxAllocationSizeSeen;
  125. PKTEST_PARAMETERS Parameters;
  126. POOL_TYPE PoolType;
  127. ULONG Random;
  128. KSTATUS Status;
  129. ULONG ThreadNumber;
  130. UINTN WriteIndex;
  131. AllocationCount = 0;
  132. Failures = 0;
  133. MaxAllocatedMemory = 0;
  134. MaxAllocationCount = 0;
  135. MaxAllocationSizeSeen = 0;
  136. Information = Parameter;
  137. Parameters = &(Information->Parameters);
  138. ArraySize = Parameters->Parameters[0];
  139. MaxAllocationSize = Parameters->Parameters[1];
  140. ThreadNumber = RtlAtomicAdd32(&(Information->ThreadsStarted), 1);
  141. if (Parameters->TestType == KTestPagedPoolStress) {
  142. PoolType = PoolTypePaged;
  143. } else {
  144. ASSERT(Parameters->TestType == KTestNonPagedPoolStress);
  145. PoolType = PoolTypeNonPaged;
  146. }
  147. //
  148. // Create the array that holds the other allocations.
  149. //
  150. Array = MmAllocatePool(PoolType,
  151. ArraySize * sizeof(PVOID),
  152. KTEST_ALLOCATION_TAG);
  153. if (Array == NULL) {
  154. Status = STATUS_INSUFFICIENT_RESOURCES;
  155. goto PoolStressRoutineEnd;
  156. }
  157. RtlZeroMemory(Array, ArraySize * sizeof(PVOID));
  158. AllocatedMemory = ArraySize * sizeof(PVOID);
  159. MaxAllocatedMemory = AllocatedMemory;
  160. //
  161. // Loop simply making and freeing allocations randomly.
  162. //
  163. for (Iteration = 0; Iteration < Parameters->Iterations; Iteration += 1) {
  164. if (Information->Cancel != FALSE) {
  165. Status = STATUS_SUCCESS;
  166. goto PoolStressRoutineEnd;
  167. }
  168. Random = (KTestGetRandomValue() % MaxAllocationSize) + sizeof(UINTN);
  169. Index = KTestGetRandomValue() % ArraySize;
  170. if (ThreadNumber == 0) {
  171. Information->Progress += 1;
  172. }
  173. //
  174. // If the lowest bit is set, attempt to allocate. Otherwise, attempt to
  175. // free. If there's nothing to free, allocate.
  176. //
  177. if (Array[Index] == NULL) {
  178. Random |= 1;
  179. }
  180. if ((Random & 1) != 0) {
  181. Allocation = MmAllocatePool(PoolType, Random, KTEST_ALLOCATION_TAG);
  182. if (Allocation == NULL) {
  183. Failures += 1;
  184. continue;
  185. }
  186. AllocatedMemory += Random;
  187. //
  188. // Initialize the memory to something. Put the size at the
  189. // beginning.
  190. //
  191. *((PUINTN)Allocation) = Random;
  192. for (WriteIndex = sizeof(UINTN);
  193. WriteIndex < Random;
  194. WriteIndex += 1) {
  195. Allocation[WriteIndex] = WriteIndex + 0x80;
  196. }
  197. //
  198. // Free the old array.
  199. //
  200. if (Array[Index] != NULL) {
  201. AllocatedMemory -= *((PUINTN)(Array[Index]));
  202. MmFreePool(PoolType, Array[Index]);
  203. AllocationCount -= 1;
  204. }
  205. Array[Index] = Allocation;
  206. AllocationCount += 1;
  207. if (AllocationCount > MaxAllocationCount) {
  208. MaxAllocationCount = AllocationCount;
  209. }
  210. if (Random > MaxAllocationSizeSeen) {
  211. MaxAllocationSizeSeen = Random;
  212. }
  213. if (AllocatedMemory > MaxAllocatedMemory) {
  214. MaxAllocatedMemory = AllocatedMemory;
  215. }
  216. } else {
  217. AllocatedMemory -= *((PUINTN)(Array[Index]));
  218. AllocationCount -= 1;
  219. MmFreePool(PoolType, Array[Index]);
  220. Array[Index] = NULL;
  221. }
  222. }
  223. Status = STATUS_SUCCESS;
  224. PoolStressRoutineEnd:
  225. //
  226. // Clean up the array.
  227. //
  228. if (Array != NULL) {
  229. for (Index = 0; Index < ArraySize; Index += 1) {
  230. if (Array[Index] != NULL) {
  231. MmFreePool(PoolType, Array[Index]);
  232. }
  233. }
  234. MmFreePool(PoolType, Array);
  235. }
  236. //
  237. // Save the results.
  238. //
  239. if (!KSUCCESS(Status)) {
  240. Information->Results.Status = Status;
  241. }
  242. Information->Results.Failures += Failures;
  243. if (ThreadNumber == 0) {
  244. Information->Results.Results[0] = MaxAllocationCount;
  245. Information->Results.Results[1] = MaxAllocationSizeSeen;
  246. Information->Results.Results[2] = MaxAllocatedMemory;
  247. }
  248. RtlAtomicAdd32(&(Information->ThreadsFinished), 1);
  249. return;
  250. }