2 * PROJECT: ReactOS API Tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Stress Test for virtual memory allocation
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
10 #define WIN32_NO_STATUS
11 #include <ndk/rtlfuncs.h>
12 #include <ndk/mmfuncs.h>
14 static PVOID Allocations
[4096] = { NULL
};
15 static ULONG CurrentAllocation
= 0;
19 ValidateAllocations(VOID
)
23 ASSERT(CurrentAllocation
< sizeof(Allocations
) / sizeof(Allocations
[0]));
24 for (i
= 0; i
< CurrentAllocation
; ++i
)
26 PUCHAR UserBuffer
= Allocations
[i
];
27 SIZE_T AllocationSize
;
30 if (UserBuffer
== NULL
)
33 AllocationSize
= ((PSIZE_T
)UserBuffer
)[-2];
34 DataSize
= ((PSIZE_T
)UserBuffer
)[-1];
35 ASSERT(AllocationSize
!= 0);
36 ASSERT(AllocationSize
% PAGE_SIZE
== 0);
37 ASSERT(DataSize
!= 0);
38 ASSERT(((SIZE_T
)UserBuffer
+ DataSize
) % PAGE_SIZE
== 0);
48 PVOID AllocationStart
= NULL
;
49 SIZE_T AllocationSize
= PAGE_ROUND_UP(DataSize
+ PAGE_SIZE
+ 2 * sizeof(SIZE_T
));
51 SIZE_T NumberOfPages
= AllocationSize
/ PAGE_SIZE
;
55 Status
= NtAllocateVirtualMemory(NtCurrentProcess(), &AllocationStart
, 0, &AllocationSize
, MEM_RESERVE
, PAGE_NOACCESS
);
57 if (!NT_SUCCESS(Status
))
60 FirstPageStart
= (PUCHAR
)AllocationStart
+ AllocationSize
- PAGE_SIZE
* NumberOfPages
;
61 Size
= (NumberOfPages
- 1) * PAGE_SIZE
;
62 Status
= NtAllocateVirtualMemory(NtCurrentProcess(), &FirstPageStart
, 0, &Size
, MEM_COMMIT
, PAGE_READWRITE
);
63 if (!NT_SUCCESS(Status
))
66 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &AllocationStart
, &AllocationSize
, MEM_RELEASE
);
67 ASSERT(Status
== STATUS_SUCCESS
);
70 ASSERT(Size
% sizeof(ULONG
) == 0);
71 ASSERT(RtlCompareMemoryUlong(FirstPageStart
, Size
, 0) == Size
);
73 UserBuffer
= AllocationStart
;
74 UserBuffer
+= AllocationSize
- PAGE_SIZE
- DataSize
;
75 RtlFillMemory(FirstPageStart
, UserBuffer
- (PUCHAR
)FirstPageStart
, 0xae);
76 RtlZeroMemory(UserBuffer
, DataSize
);
77 ((PSIZE_T
)UserBuffer
)[-2] = AllocationSize
;
78 ((PSIZE_T
)UserBuffer
)[-1] = DataSize
;
80 Allocations
[CurrentAllocation
++] = UserBuffer
;
81 ValidateAllocations();
91 PVOID AllocationStart
;
93 SIZE_T AllocationSize
;
97 AllocationSize
= ((PSIZE_T
)UserBuffer
)[-2];
98 DataSize
= ((PSIZE_T
)UserBuffer
)[-1];
99 ASSERT(DataSize
!= 0);
101 AllocationStart
= (PUCHAR
)UserBuffer
+ DataSize
+ PAGE_SIZE
- AllocationSize
;
102 ASSERT((SIZE_T
)AllocationStart
% PAGE_SIZE
== 0);
104 RtlFillMemory(UserBuffer
, DataSize
, 0xbe);
105 ((PSIZE_T
)UserBuffer
)[-1] = 0;
106 ((PSIZE_T
)UserBuffer
)[-2] = 0xFAFBFCFD;
108 for (i
= 0; i
< CurrentAllocation
; ++i
)
109 if (Allocations
[i
] == UserBuffer
)
111 Allocations
[i
] = NULL
;
114 ValidateAllocations();
116 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &AllocationStart
, &Zero
, MEM_RELEASE
);
117 ASSERT(Status
== STATUS_SUCCESS
);
129 OldDataSize
= ((PSIZE_T
)OldUserBuffer
)[-1];
130 ASSERT(OldDataSize
!= 0);
132 NewUserBuffer
= Allocate(NewDataSize
);
133 ASSERT(((PSIZE_T
)OldUserBuffer
)[-1] == OldDataSize
);
134 RtlCopyMemory(NewUserBuffer
, OldUserBuffer
, min(OldDataSize
, NewDataSize
));
135 ASSERT(((PSIZE_T
)OldUserBuffer
)[-1] == OldDataSize
);
137 return NewUserBuffer
;
146 PBYTE Buffer
= UserBuffer
;
149 for (i
= 0; i
< DataSize
; ++i
)
150 Buffer
[i
] = LOBYTE(i
);
159 PBYTE Buffer
= UserBuffer
;
162 for (i
= 0; i
< DataSize
; ++i
)
163 if (Buffer
[i
] != LOBYTE(i
))
165 trace("Mismatch in region %p at index %lu. Value=%02x\n", UserBuffer
, (ULONG
)i
, Buffer
[i
]);
178 PBYTE Buffer
= UserBuffer
;
181 for (i
= 0; i
< DataSize
; ++i
)
182 Buffer
[i
] = UCHAR_MAX
- LOBYTE(i
);
191 PBYTE Buffer
= UserBuffer
;
194 for (i
= 0; i
< DataSize
; ++i
)
195 if (Buffer
[i
] != UCHAR_MAX
- LOBYTE(i
))
197 trace("Mismatch in region %p at index %lu. Value=%02x\n", UserBuffer
, (ULONG
)i
, Buffer
[i
]);
205 CheckSize(ULONG_PTR Base
, SIZE_T InSize
, SIZE_T ExpectedSize
)
212 BaseAddress
= (PVOID
)Base
;
214 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
220 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
221 ok(BaseAddress
== (PVOID
)(Base
& ~((ULONG_PTR
)0xFFFF)), "Got back wrong base address: %p\n", BaseAddress
);
222 ok(Size
== ExpectedSize
, "Alloc of 0x%Ix: got back wrong size: 0x%Ix, expected 0x%Ix\n", InSize
, Size
, ExpectedSize
);
223 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
224 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
234 CheckSize(0x50000000, 0x0001, 0x1000);
235 CheckSize(0x50008000, 0x0001, 0x9000);
236 CheckSize(0x50000010, 0x1000, 0x2000);
237 CheckSize(0x50010000, 0x2000, 0x2000);
238 CheckSize(0x5000FFFF, 0x3000, 0x13000);
239 CheckSize(0x50001010, 0x7000, 0x9000);
240 CheckSize(0x50001010, 0xC000, 0xe000);
242 /* Reserve memory not aligned to allocation granularity */
243 BaseAddress
= UlongToPtr(0x50001010);
245 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
251 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
252 ok(BaseAddress
== UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress
);
253 ok(Size
== 0x3000, "Got back wrong size: 0x%Ix", Size
);
255 /* Try to reserve again in the same 64k region */
256 BaseAddress
= UlongToPtr(0x50008000);
258 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
264 ok(!NT_SUCCESS(Status
), "NtAllocateVirtualMemory should fail!\n");
267 BaseAddress
= UlongToPtr(0x50002000);
269 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
275 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
276 ok(BaseAddress
== UlongToPtr(0x50002000), "Got back wrong base address: %p", BaseAddress
);
277 ok(Size
== 0x1000, "Got back wrong size: 0x%Ix", Size
);
280 BaseAddress
= UlongToPtr(0x50003000);
282 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
288 ok(!NT_SUCCESS(Status
), "NtAllocateVirtualMemory should fail!\n");
290 /* Try to release memory in a different 64k region */
291 BaseAddress
= UlongToPtr(0x50010000);
293 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
294 ok(!NT_SUCCESS(Status
), "NtFreeVirtualMemory should fail!\n");
296 /* Release the memory in the same 64k region at a different address */
297 BaseAddress
= UlongToPtr(0x50008000);
299 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
300 ok(!NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
302 /* Release the memory at the correct address but with wrong size */
303 BaseAddress
= UlongToPtr(0x50000000);
305 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
306 ok(!NT_SUCCESS(Status
), "NtFreeVirtualMemory should fail!\n");
308 /* Release the memory */
309 BaseAddress
= UlongToPtr(0x50000000);
311 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
312 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
314 /* Reserve and commit at once */
315 BaseAddress
= UlongToPtr(0x50004080);
317 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
321 MEM_RESERVE
| MEM_COMMIT
,
323 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
324 ok(BaseAddress
== UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress
);
325 ok(Size
== 0x6000, "Got back wrong size: 0x%Ix", Size
);
329 *(int*)BaseAddress
= 1;
330 *(int*)UlongToPtr(0x50004080) = 1;
332 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
334 ok(0, "Got exception\n");
338 /* Release the memory */
339 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
340 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
352 /* Reserve a full 64k region */
353 BaseAddress
= UlongToPtr(0x50000000);
355 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
361 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
362 if (!NT_SUCCESS(Status
))
365 /* Reserve another 64k region, but with 64k between */
366 BaseAddress
= UlongToPtr(0x50020000);
368 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
374 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
375 if (!NT_SUCCESS(Status
))
378 /* Try to free the whole at once */
379 BaseAddress
= UlongToPtr(0x50000000);
381 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
382 ok(!NT_SUCCESS(Status
), "NtFreeVirtualMemory should fail!\n");
384 /* Reserve the part in the middle */
385 BaseAddress
= UlongToPtr(0x50010000);
387 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
393 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
395 /* Try to commit memory covering 2 allocations */
396 BaseAddress
= UlongToPtr(0x50004000);
398 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
404 ok(!NT_SUCCESS(Status
), "NtAllocateVirtualMemory should fail!\n");
407 BaseAddress
= UlongToPtr(0x50000000);
409 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
415 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
417 /* Commit another page */
418 BaseAddress
= UlongToPtr(0x50002000);
420 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
426 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
430 *(int*)UlongToPtr(0x50000000) = 1;
432 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
434 ok(0, "Got exception\n");
440 (void)*(volatile int*)UlongToPtr(0x50002000);
442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
444 Status
= _SEH2_GetExceptionCode();
447 ok(Status
= STATUS_ACCESS_VIOLATION
, "Should get an exception!\n");
449 /* Allocate 3 pages, on top of the previous 2 */
450 BaseAddress
= UlongToPtr(0x50000000);
452 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
458 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
462 *(int*)UlongToPtr(0x50000000) = 1;
464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
466 Status
= _SEH2_GetExceptionCode();
469 ok(Status
= STATUS_ACCESS_VIOLATION
, "Should get an exception!\n");
471 /* Try to free the whole region at once */
472 BaseAddress
= UlongToPtr(0x50000000);
474 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
475 ok(!NT_SUCCESS(Status
), "NtFreeVirtualMemory should fail!\n");
477 BaseAddress
= UlongToPtr(0x50000000);
479 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
480 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
482 BaseAddress
= UlongToPtr(0x50010000);
484 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
485 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
487 BaseAddress
= UlongToPtr(0x50020000);
489 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
490 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
492 /* Reserve 3 full 64k region */
493 BaseAddress
= UlongToPtr(0x50000000);
495 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
501 ok(NT_SUCCESS(Status
), "NtAllocateVirtualMemory failed!\n");
502 if (!NT_SUCCESS(Status
))
505 /* Release the 64k region in the middle */
506 BaseAddress
= UlongToPtr(0x50010000);
508 Status
= NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress
, &Size
, MEM_RELEASE
);
509 ok(NT_SUCCESS(Status
), "NtFreeVirtualMemory failed!\n");
515 START_TEST(NtAllocateVirtualMemory
)
525 Mem1
= Allocate(Size1
);
526 AccessMemory1(Mem1
, Size1
);
528 Mem2
= Allocate(Size2
);
529 AccessMemory2(Mem2
, Size2
);
530 for (i
= 0; i
< RUNS
; ++i
)
533 ok(CheckMemory1(Mem1
, Size1
) == TRUE
, "CheckMemory1 failure\n");
534 New
= ReAllocate(Mem1
, Size1
* 3 / 2);
537 skip("Realloc failure\n");
541 ok(CheckMemory1(Mem1
, Size1
) == TRUE
, "CheckMemory1 failure\n");
542 Size1
= Size1
* 3 / 2;
543 AccessMemory1(Mem1
, Size1
);
545 ok(CheckMemory2(Mem2
, Size2
) == TRUE
, "CheckMemory2 failure\n");
546 New
= ReAllocate(Mem2
, Size2
+ 128);
549 skip("Realloc failure\n");
553 ok(CheckMemory2(Mem2
, Size2
) == TRUE
, "CheckMemory2 failure\n");
555 AccessMemory2(Mem2
, Size2
);
557 ok(CheckMemory2(Mem2
, Size2
) == TRUE
, "CheckMemory2 failure\n");
559 ok(CheckMemory1(Mem1
, Size1
) == TRUE
, "CheckMemory1 failure\n");