1
0

tdesc.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. tdesc.c
  9. Abstract:
  10. This module implements the kernel memory descriptor 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_DESCRIPTOR_DEFAULT_ITERATIONS 100
  26. #define KTEST_DESCRIPTOR_DEFAULT_THREAD_COUNT 5
  27. #define KTEST_DESCRIPTOR_DEFAULT_BLOCK_SIZE 4096
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. //
  32. // ----------------------------------------------- Internal Function Prototypes
  33. //
  34. VOID
  35. KTestDescriptorStressRoutine (
  36. PVOID Parameter
  37. );
  38. //
  39. // -------------------------------------------------------------------- Globals
  40. //
  41. //
  42. // ------------------------------------------------------------------ Functions
  43. //
  44. KSTATUS
  45. KTestDescriptorStressStart (
  46. PKTEST_START_TEST Command,
  47. PKTEST_ACTIVE_TEST Test
  48. )
  49. /*++
  50. Routine Description:
  51. This routine starts a new invocation of the paged and non-paged pool stress
  52. test.
  53. Arguments:
  54. Command - Supplies a pointer to the start command.
  55. Test - Supplies a pointer to the active test structure to initialize.
  56. Return Value:
  57. Status code.
  58. --*/
  59. {
  60. PKTEST_PARAMETERS Parameters;
  61. KSTATUS Status;
  62. ULONG ThreadIndex;
  63. Parameters = &(Test->Parameters);
  64. RtlCopyMemory(Parameters, &(Command->Parameters), sizeof(KTEST_PARAMETERS));
  65. if (Parameters->Iterations == 0) {
  66. Parameters->Iterations = KTEST_DESCRIPTOR_DEFAULT_ITERATIONS;
  67. }
  68. if (Parameters->Threads == 0) {
  69. Parameters->Threads = KTEST_DESCRIPTOR_DEFAULT_THREAD_COUNT;
  70. }
  71. if (Parameters->Parameters[0] == 0) {
  72. Parameters->Parameters[0] = KTEST_DESCRIPTOR_DEFAULT_BLOCK_SIZE;
  73. }
  74. Test->Total = Test->Parameters.Iterations;
  75. Test->Results.Status = STATUS_SUCCESS;
  76. Test->Results.Failures = 0;
  77. for (ThreadIndex = 0;
  78. ThreadIndex < Test->Parameters.Threads;
  79. ThreadIndex += 1) {
  80. Status = PsCreateKernelThread(KTestDescriptorStressRoutine,
  81. Test,
  82. "KTestDescriptorStressRoutine");
  83. if (!KSUCCESS(Status)) {
  84. goto PoolStressStartEnd;
  85. }
  86. }
  87. Status = STATUS_SUCCESS;
  88. PoolStressStartEnd:
  89. return Status;
  90. }
  91. //
  92. // --------------------------------------------------------- Internal Functions
  93. //
  94. VOID
  95. KTestDescriptorStressRoutine (
  96. PVOID Parameter
  97. )
  98. /*++
  99. Routine Description:
  100. This routine implements the memory descriptor stress test.
  101. Arguments:
  102. Parameter - Supplies a pointer to the thread parameter, which in this
  103. case is a pointer to the active test structure.
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. UINTN BlockSize;
  109. ULONG Failures;
  110. ULONG Flags;
  111. UINTN Index;
  112. PKTEST_ACTIVE_TEST Information;
  113. UINTN IoBufferCount;
  114. PIO_BUFFER *IoBuffers;
  115. UINTN Iteration;
  116. PBLOCK_ALLOCATOR NonPagedAllocator;
  117. PKTEST_PARAMETERS Parameters;
  118. KSTATUS Status;
  119. ULONG ThreadNumber;
  120. Failures = 0;
  121. Information = Parameter;
  122. IoBufferCount = 0;
  123. IoBuffers = NULL;
  124. NonPagedAllocator = NULL;
  125. Parameters = &(Information->Parameters);
  126. BlockSize = Parameters->Parameters[0];
  127. ThreadNumber = RtlAtomicAdd32(&(Information->ThreadsStarted), 1);
  128. //
  129. // Create a block allocator.
  130. //
  131. Flags = BLOCK_ALLOCATOR_FLAG_NON_PAGED |
  132. BLOCK_ALLOCATOR_FLAG_PHYSICALLY_CONTIGUOUS;
  133. NonPagedAllocator = MmCreateBlockAllocator(BlockSize,
  134. 1,
  135. 1,
  136. Flags,
  137. KTEST_ALLOCATION_TAG);
  138. if (NonPagedAllocator == NULL) {
  139. Failures += 1;
  140. Status = STATUS_INSUFFICIENT_RESOURCES;
  141. goto DescriptorStressRoutineEnd;
  142. }
  143. //
  144. // Create an array to hold I/O buffers.
  145. //
  146. IoBuffers = MmAllocatePagedPool(sizeof(PIO_BUFFER) * Parameters->Iterations,
  147. KTEST_ALLOCATION_TAG);
  148. if (IoBuffers == NULL) {
  149. Failures += 1;
  150. Status = STATUS_INSUFFICIENT_RESOURCES;
  151. goto DescriptorStressRoutineEnd;
  152. }
  153. //
  154. // Loop simply alternating block allocations and I/O buffer allocations.
  155. // The goal of this is to have each allocation expand the block allocators
  156. // reserves, triggering a new allocation, and interleave those expansions
  157. // with I/O buffer allocations. This will force interleaving amongst the
  158. // virtual descriptors in the kernel's memory map, driving the descriptor
  159. // count up.
  160. //
  161. for (Iteration = 0; Iteration < Parameters->Iterations; Iteration += 1) {
  162. if (Information->Cancel != FALSE) {
  163. Status = STATUS_SUCCESS;
  164. goto DescriptorStressRoutineEnd;
  165. }
  166. if (ThreadNumber == 0) {
  167. Information->Progress += 1;
  168. }
  169. MmAllocateBlock(NonPagedAllocator, NULL);
  170. IoBuffers[Iteration] = MmAllocateNonPagedIoBuffer(0,
  171. MAX_ULONGLONG,
  172. BlockSize,
  173. BlockSize,
  174. 0);
  175. if (IoBuffers[Iteration] == NULL) {
  176. Failures += 1;
  177. Status = STATUS_INSUFFICIENT_RESOURCES;
  178. goto DescriptorStressRoutineEnd;
  179. }
  180. IoBufferCount += 1;
  181. }
  182. Status = STATUS_SUCCESS;
  183. DescriptorStressRoutineEnd:
  184. //
  185. // Destroy the block allocator.
  186. //
  187. if (NonPagedAllocator != NULL) {
  188. MmDestroyBlockAllocator(NonPagedAllocator);
  189. }
  190. //
  191. // Destroy the I/O buffers.
  192. //
  193. for (Index = 0; Index < IoBufferCount; Index += 1) {
  194. MmFreeIoBuffer(IoBuffers[Index]);
  195. }
  196. //
  197. // Save the results.
  198. //
  199. if (!KSUCCESS(Status)) {
  200. Information->Results.Status = Status;
  201. }
  202. Information->Results.Failures += Failures;
  203. RtlAtomicAdd32(&(Information->ThreadsFinished), 1);
  204. return;
  205. }