| 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 | 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 | 145 | const page_size = std.heap.pageSize(); |
| 145 | 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 | 154 | // For shrinking that is not releasing, we will only decommit |
| 154 | 155 | // the pages not needed anymore. |
| 155 | 156 | windows.VirtualFree( |
| 156 | @as(*anyopaque, @ptrFromInt(new_addr_end)), | |
| 157 | @ptrFromInt(new_addr_end), | |
| 157 | 158 | old_addr_end - new_addr_end, |
| 158 | 159 | windows.MEM_DECOMMIT, |
| 159 | 160 | ); |
| ... | ... | @@ -171,10 +172,11 @@ fn realloc(memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { |
| 171 | 172 | if (new_size_aligned == page_aligned_len) |
| 172 | 173 | return memory.ptr; |
| 173 | 174 | |
| 174 | const mremap_available = false; // native_os == .linux; | |
| 175 | const mremap_available = native_os == .linux; | |
| 175 | 176 | if (mremap_available) { |
| 176 | 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 | 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 | 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 | 315 | pub const O = switch (native_arch) { |
| 309 | 316 | .x86_64 => packed struct(u32) { |
| 310 | 317 | ACCMODE: ACCMODE = .RDONLY, |
| ... | ... | @@ -934,6 +941,17 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { |
| 934 | 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 | 955 | pub const MSF = struct { |
| 938 | 956 | pub const ASYNC = 1; |
| 939 | 957 | pub const INVALIDATE = 2; |
lib/std/posix.zig+35| ... | ... | @@ -83,6 +83,7 @@ pub const MAP = system.MAP; |
| 83 | 83 | pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; |
| 84 | 84 | pub const MFD = system.MFD; |
| 85 | 85 | pub const MMAP2_UNIT = system.MMAP2_UNIT; |
| 86 | pub const MREMAP = system.MREMAP; | |
| 86 | 87 | pub const MSF = system.MSF; |
| 87 | 88 | pub const MSG = system.MSG; |
| 88 | 89 | pub const NAME_MAX = system.NAME_MAX; |
| ... | ... | @@ -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 | 4847 | pub const MSyncError = error{ |
| 4813 | 4848 | UnmappedMemory, |
| 4814 | 4849 | PermissionDenied, |