mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
There's no need to call `alignForward` before `VirtualAlloc`. From [MSDN](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc): ``` If the lpAddress parameter is NULL, this value is rounded up to the next page boundary ```
113 lines
3.8 KiB
Zig
113 lines
3.8 KiB
Zig
const std = @import("../std.zig");
|
|
const builtin = @import("builtin");
|
|
const Allocator = std.mem.Allocator;
|
|
const mem = std.mem;
|
|
const maxInt = std.math.maxInt;
|
|
const assert = std.debug.assert;
|
|
const native_os = builtin.os.tag;
|
|
const windows = std.os.windows;
|
|
const posix = std.posix;
|
|
|
|
pub const vtable = Allocator.VTable{
|
|
.alloc = alloc,
|
|
.resize = resize,
|
|
.free = free,
|
|
};
|
|
|
|
fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 {
|
|
_ = ra;
|
|
_ = log2_align;
|
|
assert(n > 0);
|
|
if (n > maxInt(usize) - (mem.page_size - 1)) return null;
|
|
|
|
if (native_os == .windows) {
|
|
const addr = windows.VirtualAlloc(
|
|
null,
|
|
|
|
// VirtualAlloc will round the length to a multiple of page size.
|
|
// VirtualAlloc docs: If the lpAddress parameter is NULL, this value is rounded up to the next page boundary
|
|
n,
|
|
|
|
windows.MEM_COMMIT | windows.MEM_RESERVE,
|
|
windows.PAGE_READWRITE,
|
|
) catch return null;
|
|
return @ptrCast(addr);
|
|
}
|
|
|
|
const aligned_len = mem.alignForward(usize, n, mem.page_size);
|
|
const hint = @atomicLoad(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, .unordered);
|
|
const slice = posix.mmap(
|
|
hint,
|
|
aligned_len,
|
|
posix.PROT.READ | posix.PROT.WRITE,
|
|
.{ .TYPE = .PRIVATE, .ANONYMOUS = true },
|
|
-1,
|
|
0,
|
|
) catch return null;
|
|
assert(mem.isAligned(@intFromPtr(slice.ptr), mem.page_size));
|
|
const new_hint: [*]align(mem.page_size) u8 = @alignCast(slice.ptr + aligned_len);
|
|
_ = @cmpxchgStrong(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, hint, new_hint, .monotonic, .monotonic);
|
|
return slice.ptr;
|
|
}
|
|
|
|
fn resize(
|
|
_: *anyopaque,
|
|
buf_unaligned: []u8,
|
|
log2_buf_align: u8,
|
|
new_size: usize,
|
|
return_address: usize,
|
|
) bool {
|
|
_ = log2_buf_align;
|
|
_ = return_address;
|
|
const new_size_aligned = mem.alignForward(usize, new_size, mem.page_size);
|
|
|
|
if (native_os == .windows) {
|
|
if (new_size <= buf_unaligned.len) {
|
|
const base_addr = @intFromPtr(buf_unaligned.ptr);
|
|
const old_addr_end = base_addr + buf_unaligned.len;
|
|
const new_addr_end = mem.alignForward(usize, base_addr + new_size, mem.page_size);
|
|
if (old_addr_end > new_addr_end) {
|
|
// For shrinking that is not releasing, we will only
|
|
// decommit the pages not needed anymore.
|
|
windows.VirtualFree(
|
|
@as(*anyopaque, @ptrFromInt(new_addr_end)),
|
|
old_addr_end - new_addr_end,
|
|
windows.MEM_DECOMMIT,
|
|
);
|
|
}
|
|
return true;
|
|
}
|
|
const old_size_aligned = mem.alignForward(usize, buf_unaligned.len, mem.page_size);
|
|
if (new_size_aligned <= old_size_aligned) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const buf_aligned_len = mem.alignForward(usize, buf_unaligned.len, mem.page_size);
|
|
if (new_size_aligned == buf_aligned_len)
|
|
return true;
|
|
|
|
if (new_size_aligned < buf_aligned_len) {
|
|
const ptr = buf_unaligned.ptr + new_size_aligned;
|
|
// TODO: if the next_mmap_addr_hint is within the unmapped range, update it
|
|
posix.munmap(@alignCast(ptr[0 .. buf_aligned_len - new_size_aligned]));
|
|
return true;
|
|
}
|
|
|
|
// TODO: call mremap
|
|
// TODO: if the next_mmap_addr_hint is within the remapped range, update it
|
|
return false;
|
|
}
|
|
|
|
fn free(_: *anyopaque, slice: []u8, log2_buf_align: u8, return_address: usize) void {
|
|
_ = log2_buf_align;
|
|
_ = return_address;
|
|
|
|
if (native_os == .windows) {
|
|
windows.VirtualFree(slice.ptr, 0, windows.MEM_RELEASE);
|
|
} else {
|
|
const buf_aligned_len = mem.alignForward(usize, slice.len, mem.page_size);
|
|
posix.munmap(@alignCast(slice.ptr[0..buf_aligned_len]));
|
|
}
|
|
}
|