/*++ Copyright (c) 1991 Microsoft Corporation Module Name: vmstress.c Abstract: Test stress program for virtual memory. Author: Lou Perazzoli (LouP) 26-Jul-91 Revision History: --*/ #include #include #include #include #include #include #include #include typedef struct _INIT_ARG { PULONG_PTR Va; SIZE_T Size; } INIT_ARG, *PINITARG; VOID VmRandom1 ( LPVOID ThreadParameter ); VOID VmRandom2 ( LPVOID ThreadParameter ); VOID VmRandom1 ( LPVOID ThreadParameter ) { PINITARG InitialArg; ULONG Seed = 8373833; SIZE_T size; PULONG_PTR startva0; PULONG_PTR Va; ULONG i,j; InitialArg = (PINITARG)ThreadParameter; startva0 = InitialArg->Va; size = InitialArg->Size; // printf("starting random references in thread1\n"); for (j = 1; j < 10; j++) { for (i = 1 ; i < 2500; i++) { RtlRandom (&Seed); Va = startva0 + (Seed % (size / sizeof(ULONG_PTR))); if (*Va == (((ULONG_PTR)Va + 1))) { *Va = (ULONG_PTR)Va; } else { if (*Va != (ULONG_PTR)Va) { printf("bad random value in cell %p was %p\n", Va, (void *)*Va); } } } Sleep (150); } // printf("terminating thread1\n"); ExitThread(0); } VOID VmRandom2 ( LPVOID ThreadParameter ) { PINITARG InitialArg; ULONG Seed = 8373839; SIZE_T size; PULONG_PTR startva0; PULONG_PTR Va; ULONG i,j; InitialArg = (PINITARG)ThreadParameter; startva0 = InitialArg->Va; size = InitialArg->Size; // printf("starting random references in thread2\n"); for (j = 1; j < 10; j++) { for (i = 1 ; i < 2500; i++) { RtlRandom (&Seed); Va = startva0 + (Seed % (size / sizeof(ULONG_PTR))); if (*Va == (((ULONG_PTR)Va + 1))) { *Va = (ULONG_PTR)Va; } else { if (*Va != (ULONG_PTR)Va) { printf("bad random value in cell %p was %lx\n", Va, *Va); } } } Sleep (150); } // printf("terminating thread2\n"); ExitThread(0); } DWORD __cdecl main( int argc, char *argv[], char *envp[] ) { HANDLE Objects[2]; MEMORYSTATUS MemStatus; INIT_ARG InitialArg; PULONG_PTR Va; PULONG_PTR EndVa; SIZE_T size; PULONG_PTR startva0; NTSTATUS status; DWORD ThreadId1, ThreadId2; ULONG count = 0; printf("Starting virtual memory stress test\n"); for (;;) { // // Create a region of private memory based on the number of // available pages on this system. // GlobalMemoryStatus(&MemStatus); size = MemStatus.dwAvailPhys; if (size == 0) { size = 4096; } else { size -= 4*4096; } while (size != 0) { startva0 = NULL; status = NtAllocateVirtualMemory (NtCurrentProcess(), (PVOID *)&startva0, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (NT_SUCCESS(status)) { break; } else { // // Try for less memory. // size -= 4096; } } printf("created vm status, startva, size, %lX %p %p\n", status, startva0, (void *)size); if (!NT_SUCCESS(status)) { ExitProcess (0); } InitialArg.Va = startva0; InitialArg.Size = size; // // Set all memory to know values (not zeroes). // printf("initializing memory\n"); EndVa = (PULONG_PTR)startva0 + (size/sizeof(ULONG_PTR)); Va = startva0; while (Va < EndVa) { *Va = (ULONG_PTR)Va + 1; Va += 1; } do { Objects[0] = CreateThread(NULL, 0L, (LPTHREAD_START_ROUTINE)VmRandom1, (LPVOID)&InitialArg, 0, &ThreadId1); // // Must have run out of memory, wait a while and then try again. // if (Objects[0] == (HANDLE)0) { Sleep (3000); } } while (Objects[0] == (HANDLE)0); do { Objects[1] = CreateThread(NULL, 0L, (LPTHREAD_START_ROUTINE)VmRandom2, (LPVOID)&InitialArg, 0, &ThreadId2); // // Must have run out of memory, wait a while and then try again. // if (Objects[1] == (HANDLE)0) { Sleep (3000); } } while (Objects[1] == (HANDLE)0); WaitForMultipleObjects (2, Objects, TRUE, -1); count += 1; printf("stress test pass number %ld complete\n",count); CloseHandle (Objects[0]); CloseHandle (Objects[1]); printf("freeing vm startva, size, %p %p\n", startva0, (void *)size); status = NtFreeVirtualMemory (NtCurrentProcess(), (PVOID *)&startva0, &size, MEM_RELEASE); if (!NT_SUCCESS(status)) { ExitProcess (0); } Sleep (1000); } return 0; }