| author | |
| committer | |
| log | a4d4e086c59b702c34218105764d4ec491ecc566 |
| tree | 165cd9428e064ede06408a792cbdfdfff6f39996 |
| parent | a0b2a18648ec4c465f3e19c05338b554c0742dfb |
in std.heap.page_allocator3 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 | ... | @@ -140,7 +140,8 @@ fn free(context: *anyopaque, slice: []u8, alignment: mem.Alignment, return_addre |
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { | 143 | fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { |
| 144 | const memory: []align(std.heap.page_size_min) u8 = @alignCast(uncasted_memory); | ||
| 144 | const page_size = std.heap.pageSize(); | 145 | const page_size = std.heap.pageSize(); |
| 145 | const new_size_aligned = mem.alignForward(usize, new_len, page_size); | 146 | const new_size_aligned = mem.alignForward(usize, new_len, page_size); |
| 146 | 147 | ||
| ... | @@ -153,7 +154,7 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { | ... | @@ -153,7 +154,7 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { |
| 153 | // For shrinking that is not releasing, we will only decommit | 154 | // For shrinking that is not releasing, we will only decommit |
| 154 | // the pages not needed anymore. | 155 | // the pages not needed anymore. |
| 155 | windows.VirtualFree( | 156 | windows.VirtualFree( |
| 156 | @as(*anyopaque, @ptrFromInt(new_addr_end)), | 157 | @ptrFromInt(new_addr_end), |
| 157 | old_addr_end - new_addr_end, | 158 | old_addr_end - new_addr_end, |
| 158 | windows.MEM_DECOMMIT, | 159 | windows.MEM_DECOMMIT, |
| 159 | ); | 160 | ); |
| ... | @@ -171,10 +172,11 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { | ... | @@ -171,10 +172,11 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { |
| 171 | if (new_size_aligned == page_aligned_len) | 172 | if (new_size_aligned == page_aligned_len) |
| 172 | return memory.ptr; | 173 | return memory.ptr; |
| 173 | 174 | ||
| 174 | const mremap_available = false; // native_os == .linux; | 175 | const mremap_available = native_os == .linux; |
| 175 | if (mremap_available) { | 176 | if (mremap_available) { |
| 176 | // TODO: if the next_mmap_addr_hint is within the remapped range, update it | 177 | // 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; | ||
| 178 | } | 180 | } |
| 179 | 181 | ||
| 180 | if (new_size_aligned < page_aligned_len) { | 182 | if (new_size_aligned < page_aligned_len) { |
lib/std/os/linux.zig+18| ... | @@ -305,6 +305,13 @@ pub const MAP = switch (native_arch) { | ... | @@ -305,6 +305,13 @@ pub const MAP = switch (native_arch) { |
| 305 | else => @compileError("missing std.os.linux.MAP constants for this architecture"), | 305 | else => @compileError("missing std.os.linux.MAP constants for this architecture"), |
| 306 | }; | 306 | }; |
| 307 | 307 | ||
| 308 | pub const MREMAP = packed struct(u32) { | ||
| 309 | MAYMOVE: bool = false, | ||
| 310 | FIXED: bool = false, | ||
| 311 | DONTUNMAP: bool = false, | ||
| 312 | _: u29 = 0, | ||
| 313 | }; | ||
| 314 | |||
| 308 | pub const O = switch (native_arch) { | 315 | pub const O = switch (native_arch) { |
| 309 | .x86_64 => packed struct(u32) { | 316 | .x86_64 => packed struct(u32) { |
| 310 | ACCMODE: ACCMODE = .RDONLY, | 317 | ACCMODE: ACCMODE = .RDONLY, |
| ... | @@ -934,6 +941,17 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { | ... | @@ -934,6 +941,17 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { |
| 934 | return syscall3(.mprotect, @intFromPtr(address), length, protection); | 941 | return syscall3(.mprotect, @intFromPtr(address), length, protection); |
| 935 | } | 942 | } |
| 936 | 943 | ||
| 944 | pub 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 | |||
| 937 | pub const MSF = struct { | 955 | pub const MSF = struct { |
| 938 | pub const ASYNC = 1; | 956 | pub const ASYNC = 1; |
| 939 | pub const INVALIDATE = 2; | 957 | pub const INVALIDATE = 2; |
lib/std/posix.zig+35| ... | @@ -83,6 +83,7 @@ pub const MAP = system.MAP; | ... | @@ -83,6 +83,7 @@ pub const MAP = system.MAP; |
| 83 | pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; | 83 | pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; |
| 84 | pub const MFD = system.MFD; | 84 | pub const MFD = system.MFD; |
| 85 | pub const MMAP2_UNIT = system.MMAP2_UNIT; | 85 | pub const MMAP2_UNIT = system.MMAP2_UNIT; |
| 86 | pub const MREMAP = system.MREMAP; | ||
| 86 | pub const MSF = system.MSF; | 87 | pub const MSF = system.MSF; |
| 87 | pub const MSG = system.MSG; | 88 | pub const MSG = system.MSG; |
| 88 | pub const NAME_MAX = system.NAME_MAX; | 89 | pub const NAME_MAX = system.NAME_MAX; |
| ... | @@ -4809,6 +4810,40 @@ pub fn munmap(memory: []align(page_size_min) const u8) void { | ... | @@ -4809,6 +4810,40 @@ pub fn munmap(memory: []align(page_size_min) const u8) void { |
| 4809 | } | 4810 | } |
| 4810 | } | 4811 | } |
| 4811 | 4812 | ||
| 4813 | pub 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 | |||
| 4821 | pub 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 | |||
| 4812 | pub const MSyncError = error{ | 4847 | pub const MSyncError = error{ |
| 4813 | UnmappedMemory, | 4848 | UnmappedMemory, |
| 4814 | PermissionDenied, | 4849 | PermissionDenied, |