diff --git a/lib/std/heap.zig b/lib/std/heap.zig index f0ea8d0d467f..4e60fadb5841 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -35,7 +35,7 @@ pub var next_mmap_addr_hint: ?[*]align(page_size_min) u8 = null; /// comptime-known minimum page size of the target. /// -/// All pointers from `mmap` or `VirtualAlloc` are aligned to at least +/// All pointers from `mmap` or `NtAllocateVirtualMemory` are aligned to at least /// `page_size_min`, but their actual alignment may be bigger. /// /// This value can be overridden via `std.options.page_size_min`. @@ -671,7 +671,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { defer allocator.free(slice); var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator); - // On Windows, VirtualAlloc returns addresses aligned to a 64K boundary, + // On Windows, NtAllocateVirtualMemory returns addresses aligned to a 64K boundary, // which is 16 pages, hence the 32. This test may require to increase // the size of the allocations feeding the `allocator` parameter if they // fail, because of this high over-alignment we want to have. diff --git a/lib/std/heap/PageAllocator.zig b/lib/std/heap/PageAllocator.zig index 106460387abc..fe08a51006de 100644 --- a/lib/std/heap/PageAllocator.zig +++ b/lib/std/heap/PageAllocator.zig @@ -27,27 +27,29 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { const alignment_bytes = alignment.toByteUnits(); if (native_os == .windows) { - var base_addr: ?*anyopaque = null; - var size: windows.SIZE_T = n; + if (alignment_bytes < page_size_min) { + var base_addr: ?*anyopaque = null; + var size: windows.SIZE_T = n; - var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE); + const status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE); - if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) { - return @ptrCast(base_addr); - } + if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) { + return @ptrCast(base_addr); + } - if (status == SUCCESS) { - var region_size: windows.SIZE_T = 0; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, windows.MEM_RELEASE); + if (status == SUCCESS) { + var region_size: windows.SIZE_T = 0; + _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, windows.MEM_RELEASE); + } } const overalloc_len = n + alignment_bytes - page_size; const aligned_len = mem.alignForward(usize, n, page_size); - base_addr = null; - size = overalloc_len; + var base_addr: ?*anyopaque = null; + var size: windows.SIZE_T = overalloc_len; - status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS); + var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS); if (status != SUCCESS) return null; diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index c29eb0f05a14..d2ae3bd1b1f2 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1790,20 +1790,6 @@ pub fn NtFreeVirtualMemory(hProcess: HANDLE, addr: ?*PVOID, size: *SIZE_T, free_ }; } -pub const VirtualAllocError = error{Unexpected}; - -pub fn VirtualAlloc(addr: ?LPVOID, size: usize, alloc_type: DWORD, flProtect: DWORD) VirtualAllocError!LPVOID { - return kernel32.VirtualAlloc(addr, size, alloc_type, flProtect) orelse { - switch (GetLastError()) { - else => |err| return unexpectedError(err), - } - }; -} - -pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { - assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); -} - pub const VirtualProtectError = error{ InvalidAddress, Unexpected, diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index ce151279796a..b474e7b0b18b 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -557,22 +557,6 @@ pub extern "kernel32" fn HeapValidate( lpMem: ?*const anyopaque, ) callconv(.winapi) BOOL; -// TODO: Wrapper around NtAllocateVirtualMemory. -pub extern "kernel32" fn VirtualAlloc( - lpAddress: ?LPVOID, - dwSize: SIZE_T, - flAllocationType: DWORD, - flProtect: DWORD, -) callconv(.winapi) ?LPVOID; - -// TODO: Wrapper around NtFreeVirtualMemory. -// If the return value is .INVALID_PAGE_PROTECTION, calls RtlFlushSecureMemoryCache and try again. -pub extern "kernel32" fn VirtualFree( - lpAddress: ?LPVOID, - dwSize: SIZE_T, - dwFreeType: DWORD, -) callconv(.winapi) BOOL; - // TODO: Wrapper around NtQueryVirtualMemory. pub extern "kernel32" fn VirtualQuery( lpAddress: ?LPVOID, diff --git a/lib/std/posix.zig b/lib/std/posix.zig index c07d6e6f0d4f..7ea97650b77b 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -4805,7 +4805,7 @@ pub fn mmap( /// Note that while POSIX allows unmapping a region in the middle of an existing mapping, /// Zig's munmap function does not, for two reasons: /// * It violates the Zig principle that resource deallocation must succeed. -/// * The Windows function, VirtualFree, has this restriction. +/// * The Windows function, NtFreeVirtualMemory, has this restriction. pub fn munmap(memory: []align(page_size_min) const u8) void { switch (errno(system.munmap(memory.ptr, memory.len))) { .SUCCESS => return,