authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-03 20:40:57-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
loga4d4e086c59b702c34218105764d4ec491ecc566
tree165cd9428e064ede06408a792cbdfdfff6f39996
parenta0b2a18648ec4c465f3e19c05338b554c0742dfb

introduce std.posix.mremap and use it

in std.heap.page_allocator

3 files changed, 59 insertions(+), 4 deletions(-)

lib/std/heap/PageAllocator.zig+6-4
......@@ -140,7 +140,8 @@ fn free(context: *anyopaque, slice: []u8, alignment: mem.Alignment, return_addre
140140 }
141141}
142142
143fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
143fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
144 const memory: []align(std.heap.page_size_min) u8 = @alignCast(uncasted_memory);
144145 const page_size = std.heap.pageSize();
145146 const new_size_aligned = mem.alignForward(usize, new_len, page_size);
146147
......@@ -153,7 +154,7 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
153154 // For shrinking that is not releasing, we will only decommit
154155 // the pages not needed anymore.
155156 windows.VirtualFree(
156 @as(*anyopaque, @ptrFromInt(new_addr_end)),
157 @ptrFromInt(new_addr_end),
157158 old_addr_end - new_addr_end,
158159 windows.MEM_DECOMMIT,
159160 );
......@@ -171,10 +172,11 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
171172 if (new_size_aligned == page_aligned_len)
172173 return memory.ptr;
173174
174 const mremap_available = false; // native_os == .linux;
175 const mremap_available = native_os == .linux;
175176 if (mremap_available) {
176177 // TODO: if the next_mmap_addr_hint is within the remapped range, update it
177 return posix.mremap(memory, new_len, .{ .MAYMOVE = may_move }, null) catch return null;
178 const new_memory = posix.mremap(memory.ptr, memory.len, new_len, .{ .MAYMOVE = may_move }, null) catch return null;
179 return new_memory.ptr;
178180 }
179181
180182 if (new_size_aligned < page_aligned_len) {
lib/std/os/linux.zig+18
......@@ -305,6 +305,13 @@ pub const MAP = switch (native_arch) {
305305 else => @compileError("missing std.os.linux.MAP constants for this architecture"),
306306};
307307
308pub const MREMAP = packed struct(u32) {
309 MAYMOVE: bool = false,
310 FIXED: bool = false,
311 DONTUNMAP: bool = false,
312 _: u29 = 0,
313};
314
308315pub const O = switch (native_arch) {
309316 .x86_64 => packed struct(u32) {
310317 ACCMODE: ACCMODE = .RDONLY,
......@@ -934,6 +941,17 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
934941 return syscall3(.mprotect, @intFromPtr(address), length, protection);
935942}
936943
944pub fn mremap(old_addr: ?[*]const u8, old_len: usize, new_len: usize, flags: MREMAP, new_addr: ?[*]const u8) usize {
945 return syscall5(
946 .mremap,
947 @intFromPtr(old_addr),
948 old_len,
949 new_len,
950 @as(u32, @bitCast(flags)),
951 @intFromPtr(new_addr),
952 );
953}
954
937955pub const MSF = struct {
938956 pub const ASYNC = 1;
939957 pub const INVALIDATE = 2;
lib/std/posix.zig+35
......@@ -83,6 +83,7 @@ pub const MAP = system.MAP;
8383pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN;
8484pub const MFD = system.MFD;
8585pub const MMAP2_UNIT = system.MMAP2_UNIT;
86pub const MREMAP = system.MREMAP;
8687pub const MSF = system.MSF;
8788pub const MSG = system.MSG;
8889pub const NAME_MAX = system.NAME_MAX;
......@@ -4809,6 +4810,40 @@ pub fn munmap(memory: []align(page_size_min) const u8) void {
48094810 }
48104811}
48114812
4813pub const MRemapError = error{
4814 LockedMemoryLimitExceeded,
4815 /// Either a bug in the calling code, or the operating system abused the
4816 /// EINVAL error code.
4817 InvalidSyscallParameters,
4818 OutOfMemory,
4819} || UnexpectedError;
4820
4821pub fn mremap(
4822 old_address: ?[*]align(page_size_min) u8,
4823 old_len: usize,
4824 new_len: usize,
4825 flags: system.MREMAP,
4826 new_address: ?[*]align(page_size_min) u8,
4827) MRemapError![]align(page_size_min) u8 {
4828 const rc = system.mremap(old_address, old_len, new_len, flags, new_address);
4829 const err: E = if (builtin.link_libc) blk: {
4830 if (rc != std.c.MAP_FAILED) return @as([*]align(page_size_min) u8, @ptrCast(@alignCast(rc)))[0..new_len];
4831 break :blk @enumFromInt(system._errno().*);
4832 } else blk: {
4833 const err = errno(rc);
4834 if (err == .SUCCESS) return @as([*]align(page_size_min) u8, @ptrFromInt(rc))[0..new_len];
4835 break :blk err;
4836 };
4837 switch (err) {
4838 .SUCCESS => unreachable,
4839 .AGAIN => return error.LockedMemoryLimitExceeded,
4840 .INVAL => return error.InvalidSyscallParameters,
4841 .NOMEM => return error.OutOfMemory,
4842 .FAULT => unreachable,
4843 else => return unexpectedErrno(err),
4844 }
4845}
4846
48124847pub const MSyncError = error{
48134848 UnmappedMemory,
48144849 PermissionDenied,