| author | |
| committer | |
| log | 439667be0476f5bf60f3efbb82a3c4d5aae96ee4 |
| tree | 982fdb5d9260c1c30dee76f89319848e0371b4e2 |
| parent | b0ed602d5d9358128471588f00a073f2545809fa |
heap.zig: define new default page sizes
heap.zig: add min/max_page_size and their options
lib/std/c: add miscellaneous declarations
heap.zig: add pageSize() and its options
switch to new page sizes, especially in GPA/stdlib
mem.zig: remove page_size29 files changed, 614 insertions(+), 176 deletions(-)
lib/fuzzer.zig+1-1| ... | ... | @@ -480,7 +480,7 @@ pub const MemoryMappedList = struct { |
| 480 | 480 | /// of this ArrayList in accordance with the respective documentation. In |
| 481 | 481 | /// all cases, "invalidated" means that the memory has been passed to this |
| 482 | 482 | /// allocator's resize or free function. |
| 483 | items: []align(std.mem.page_size) volatile u8, | |
| 483 | items: []align(std.heap.min_page_size) volatile u8, | |
| 484 | 484 | /// How many bytes this list can hold without allocating additional memory. |
| 485 | 485 | capacity: usize, |
| 486 | 486 |
lib/std/Build/Fuzz/WebServer.zig+1-1| ... | ... | @@ -41,7 +41,7 @@ const fuzzer_arch_os_abi = "wasm32-freestanding"; |
| 41 | 41 | const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; |
| 42 | 42 | |
| 43 | 43 | const CoverageMap = struct { |
| 44 | mapped_memory: []align(std.mem.page_size) const u8, | |
| 44 | mapped_memory: []align(std.heap.min_page_size) const u8, | |
| 45 | 45 | coverage: Coverage, |
| 46 | 46 | source_locations: []Coverage.SourceLocation, |
| 47 | 47 | /// Elements are indexes into `source_locations` pointing to the unit tests that are being fuzz tested. |
lib/std/Thread.zig+3-3| ... | ... | @@ -769,7 +769,7 @@ const PosixThreadImpl = struct { |
| 769 | 769 | // Use the same set of parameters used by the libc-less impl. |
| 770 | 770 | const stack_size = @max(config.stack_size, 16 * 1024); |
| 771 | 771 | assert(c.pthread_attr_setstacksize(&attr, stack_size) == .SUCCESS); |
| 772 | assert(c.pthread_attr_setguardsize(&attr, std.mem.page_size) == .SUCCESS); | |
| 772 | assert(c.pthread_attr_setguardsize(&attr, std.heap.pageSize()) == .SUCCESS); | |
| 773 | 773 | |
| 774 | 774 | var handle: c.pthread_t = undefined; |
| 775 | 775 | switch (c.pthread_create( |
| ... | ... | @@ -1155,7 +1155,7 @@ const LinuxThreadImpl = struct { |
| 1155 | 1155 | completion: Completion = Completion.init(.running), |
| 1156 | 1156 | child_tid: std.atomic.Value(i32) = std.atomic.Value(i32).init(1), |
| 1157 | 1157 | parent_tid: i32 = undefined, |
| 1158 | mapped: []align(std.mem.page_size) u8, | |
| 1158 | mapped: []align(std.heap.min_page_size) u8, | |
| 1159 | 1159 | |
| 1160 | 1160 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). |
| 1161 | 1161 | /// Ported over from musl libc's pthread detached implementation: |
| ... | ... | @@ -1362,7 +1362,7 @@ const LinuxThreadImpl = struct { |
| 1362 | 1362 | }; |
| 1363 | 1363 | |
| 1364 | 1364 | fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl { |
| 1365 | const page_size = std.mem.page_size; | |
| 1365 | const page_size = std.heap.pageSize(); | |
| 1366 | 1366 | const Args = @TypeOf(args); |
| 1367 | 1367 | const Instance = struct { |
| 1368 | 1368 | fn_args: Args, |
lib/std/c.zig+48-11| ... | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const c = @This(); |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | const assert = std.debug.assert; |
| 6 | const page_size = std.mem.page_size; | |
| 6 | const min_page_size = std.heap.min_page_size; | |
| 7 | 7 | const native_abi = builtin.abi; |
| 8 | 8 | const native_arch = builtin.cpu.arch; |
| 9 | 9 | const native_os = builtin.os.tag; |
| ... | ... | @@ -2227,6 +2227,39 @@ pub const SC = switch (native_os) { |
| 2227 | 2227 | .linux => linux.SC, |
| 2228 | 2228 | else => void, |
| 2229 | 2229 | }; |
| 2230 | ||
| 2231 | pub const _SC = switch (native_os) { | |
| 2232 | .bridgeos, .driverkit, .ios, .macos, .tvos, .visionos, .watchos => enum(c_int) { | |
| 2233 | PAGESIZE = 29, | |
| 2234 | }, | |
| 2235 | .dragonfly => enum(c_int) { | |
| 2236 | PAGESIZE = 47, | |
| 2237 | }, | |
| 2238 | .freebsd => enum(c_int) { | |
| 2239 | PAGESIZE = 47, | |
| 2240 | }, | |
| 2241 | .fuchsia => enum(c_int) { | |
| 2242 | PAGESIZE = 30, | |
| 2243 | }, | |
| 2244 | .haiku => enum(c_int) { | |
| 2245 | PAGESIZE = 27, | |
| 2246 | }, | |
| 2247 | .linux => enum(c_int) { | |
| 2248 | PAGESIZE = 30, | |
| 2249 | }, | |
| 2250 | .netbsd => enum(c_int) { | |
| 2251 | PAGESIZE = 28, | |
| 2252 | }, | |
| 2253 | .openbsd => enum(c_int) { | |
| 2254 | PAGESIZE = 28, | |
| 2255 | }, | |
| 2256 | .solaris, .illumos => enum(c_int) { | |
| 2257 | PAGESIZE = 11, | |
| 2258 | NPROCESSORS_ONLN = 15, | |
| 2259 | }, | |
| 2260 | else => void, | |
| 2261 | }; | |
| 2262 | ||
| 2230 | 2263 | pub const SEEK = switch (native_os) { |
| 2231 | 2264 | .linux => linux.SEEK, |
| 2232 | 2265 | .emscripten => emscripten.SEEK, |
| ... | ... | @@ -9232,7 +9265,7 @@ pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd; |
| 9232 | 9265 | pub extern "c" fn getpwuid(uid: uid_t) ?*passwd; |
| 9233 | 9266 | pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int; |
| 9234 | 9267 | pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64; |
| 9235 | pub extern "c" fn mmap64(addr: ?*align(std.mem.page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque; | |
| 9268 | pub extern "c" fn mmap64(addr: ?*align(min_page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque; | |
| 9236 | 9269 | pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int; |
| 9237 | 9270 | pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int; |
| 9238 | 9271 | pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize; |
| ... | ... | @@ -9324,13 +9357,13 @@ pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int; |
| 9324 | 9357 | |
| 9325 | 9358 | pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int; |
| 9326 | 9359 | pub extern "c" fn mincore( |
| 9327 | addr: *align(std.mem.page_size) anyopaque, | |
| 9360 | addr: *align(min_page_size) anyopaque, | |
| 9328 | 9361 | length: usize, |
| 9329 | 9362 | vec: [*]u8, |
| 9330 | 9363 | ) c_int; |
| 9331 | 9364 | |
| 9332 | 9365 | pub extern "c" fn madvise( |
| 9333 | addr: *align(std.mem.page_size) anyopaque, | |
| 9366 | addr: *align(min_page_size) anyopaque, | |
| 9334 | 9367 | length: usize, |
| 9335 | 9368 | advice: u32, |
| 9336 | 9369 | ) c_int; |
| ... | ... | @@ -9428,6 +9461,10 @@ pub const posix_memalign = switch (native_os) { |
| 9428 | 9461 | .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos => private.posix_memalign, |
| 9429 | 9462 | else => {}, |
| 9430 | 9463 | }; |
| 9464 | pub const sysconf = switch (native_os) { | |
| 9465 | .solaris => solaris.sysconf, | |
| 9466 | else => private.sysconf, | |
| 9467 | }; | |
| 9431 | 9468 | |
| 9432 | 9469 | pub const sf_hdtr = switch (native_os) { |
| 9433 | 9470 | .freebsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct { |
| ... | ... | @@ -9469,9 +9506,9 @@ pub extern "c" fn writev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint) i |
| 9469 | 9506 | pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: off_t) isize; |
| 9470 | 9507 | pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize; |
| 9471 | 9508 | pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize; |
| 9472 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque; | |
| 9473 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; | |
| 9474 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; | |
| 9509 | pub extern "c" fn mmap(addr: ?*align(min_page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque; | |
| 9510 | pub extern "c" fn munmap(addr: *align(min_page_size) const anyopaque, len: usize) c_int; | |
| 9511 | pub extern "c" fn mprotect(addr: *align(min_page_size) anyopaque, len: usize, prot: c_uint) c_int; | |
| 9475 | 9512 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int; |
| 9476 | 9513 | pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int; |
| 9477 | 9514 | pub extern "c" fn unlink(path: [*:0]const u8) c_int; |
| ... | ... | @@ -9823,7 +9860,6 @@ pub const SCM = solaris.SCM; |
| 9823 | 9860 | pub const SETCONTEXT = solaris.SETCONTEXT; |
| 9824 | 9861 | pub const SETUSTACK = solaris.GETUSTACK; |
| 9825 | 9862 | pub const SFD = solaris.SFD; |
| 9826 | pub const _SC = solaris._SC; | |
| 9827 | 9863 | pub const cmsghdr = solaris.cmsghdr; |
| 9828 | 9864 | pub const ctid_t = solaris.ctid_t; |
| 9829 | 9865 | pub const file_obj = solaris.file_obj; |
| ... | ... | @@ -9840,7 +9876,6 @@ pub const priority = solaris.priority; |
| 9840 | 9876 | pub const procfs = solaris.procfs; |
| 9841 | 9877 | pub const projid_t = solaris.projid_t; |
| 9842 | 9878 | pub const signalfd_siginfo = solaris.signalfd_siginfo; |
| 9843 | pub const sysconf = solaris.sysconf; | |
| 9844 | 9879 | pub const taskid_t = solaris.taskid_t; |
| 9845 | 9880 | pub const zoneid_t = solaris.zoneid_t; |
| 9846 | 9881 | |
| ... | ... | @@ -9997,6 +10032,7 @@ pub const host_t = darwin.host_t; |
| 9997 | 10032 | pub const ipc_space_t = darwin.ipc_space_t; |
| 9998 | 10033 | pub const ipc_space_port_t = darwin.ipc_space_port_t; |
| 9999 | 10034 | pub const kern_return_t = darwin.kern_return_t; |
| 10035 | pub const vm_size_t = darwin.vm_size_t; | |
| 10000 | 10036 | pub const kevent64 = darwin.kevent64; |
| 10001 | 10037 | pub const kevent64_s = darwin.kevent64_s; |
| 10002 | 10038 | pub const mach_absolute_time = darwin.mach_absolute_time; |
| ... | ... | @@ -10155,7 +10191,7 @@ const private = struct { |
| 10155 | 10191 | }; |
| 10156 | 10192 | extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; |
| 10157 | 10193 | extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 10158 | extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; | |
| 10194 | extern "c" fn msync(addr: *align(min_page_size) const anyopaque, len: usize, flags: c_int) c_int; | |
| 10159 | 10195 | extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 10160 | 10196 | extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int; |
| 10161 | 10197 | extern "c" fn readdir(dir: *DIR) ?*dirent; |
| ... | ... | @@ -10168,6 +10204,7 @@ const private = struct { |
| 10168 | 10204 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 10169 | 10205 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; |
| 10170 | 10206 | extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 10207 | extern "c" fn sysconf(sc: c_int) c_long; | |
| 10171 | 10208 | |
| 10172 | 10209 | extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8) c_int; |
| 10173 | 10210 | extern "c" fn getcontext(ucp: *ucontext_t) c_int; |
| ... | ... | @@ -10202,7 +10239,7 @@ const private = struct { |
| 10202 | 10239 | extern "c" fn __getrusage50(who: c_int, usage: *rusage) c_int; |
| 10203 | 10240 | extern "c" fn __gettimeofday50(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 10204 | 10241 | extern "c" fn __libc_thr_yield() c_int; |
| 10205 | extern "c" fn __msync13(addr: *align(std.mem.page_size) const anyopaque, len: usize, flags: c_int) c_int; | |
| 10242 | extern "c" fn __msync13(addr: *align(min_page_size) const anyopaque, len: usize, flags: c_int) c_int; | |
| 10206 | 10243 | extern "c" fn __nanosleep50(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 10207 | 10244 | extern "c" fn __sigaction14(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; |
| 10208 | 10245 | extern "c" fn __sigfillset14(set: ?*sigset_t) void; |
lib/std/c/solaris.zig-4| ... | ... | @@ -154,10 +154,6 @@ pub const AF_SUN = struct { |
| 154 | 154 | pub const NOPLM = 0x00000004; |
| 155 | 155 | }; |
| 156 | 156 | |
| 157 | pub const _SC = struct { | |
| 158 | pub const NPROCESSORS_ONLN = 15; | |
| 159 | }; | |
| 160 | ||
| 161 | 157 | pub const procfs = struct { |
| 162 | 158 | pub const misc_header = extern struct { |
| 163 | 159 | size: u32, |
lib/std/crypto/tlcsprng.zig+3-2| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | const std = @import("std"); |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const mem = std.mem; |
| 9 | const heap = std.heap; | |
| 9 | 10 | const native_os = builtin.os.tag; |
| 10 | 11 | const posix = std.posix; |
| 11 | 12 | |
| ... | ... | @@ -42,7 +43,7 @@ var install_atfork_handler = std.once(struct { |
| 42 | 43 | } |
| 43 | 44 | }.do); |
| 44 | 45 | |
| 45 | threadlocal var wipe_mem: []align(mem.page_size) u8 = &[_]u8{}; | |
| 46 | threadlocal var wipe_mem: []align(heap.min_page_size) u8 = &[_]u8{}; | |
| 46 | 47 | |
| 47 | 48 | fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 48 | 49 | if (os_has_arc4random) { |
| ... | ... | @@ -77,7 +78,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 77 | 78 | } else { |
| 78 | 79 | // Use a static thread-local buffer. |
| 79 | 80 | const S = struct { |
| 80 | threadlocal var buf: Context align(mem.page_size) = .{ | |
| 81 | threadlocal var buf: Context align(heap.min_page_size) = .{ | |
| 81 | 82 | .init_state = .uninitialized, |
| 82 | 83 | .rng = undefined, |
| 83 | 84 | }; |
lib/std/debug.zig+9-8| ... | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std.zig"); |
| 3 | 3 | const math = std.math; |
| 4 | 4 | const mem = std.mem; |
| 5 | const heap = std.heap; | |
| 5 | 6 | const io = std.io; |
| 6 | 7 | const posix = std.posix; |
| 7 | 8 | const fs = std.fs; |
| ... | ... | @@ -1134,7 +1135,7 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) |
| 1134 | 1135 | defer f.close(); |
| 1135 | 1136 | // TODO fstat and make sure that the file has the correct size |
| 1136 | 1137 | |
| 1137 | var buf: [mem.page_size]u8 = undefined; | |
| 1138 | var buf: [4096]u8 = undefined; | |
| 1138 | 1139 | var amt_read = try f.read(buf[0..]); |
| 1139 | 1140 | const line_start = seek: { |
| 1140 | 1141 | var current_line_start: usize = 0; |
| ... | ... | @@ -1237,7 +1238,7 @@ test printLineFromFileAnyOs { |
| 1237 | 1238 | |
| 1238 | 1239 | const overlap = 10; |
| 1239 | 1240 | var writer = file.writer(); |
| 1240 | try writer.writeByteNTimes('a', mem.page_size - overlap); | |
| 1241 | try writer.writeByteNTimes('a', heap.min_page_size - overlap); | |
| 1241 | 1242 | try writer.writeByte('\n'); |
| 1242 | 1243 | try writer.writeByteNTimes('a', overlap); |
| 1243 | 1244 | |
| ... | ... | @@ -1252,10 +1253,10 @@ test printLineFromFileAnyOs { |
| 1252 | 1253 | defer allocator.free(path); |
| 1253 | 1254 | |
| 1254 | 1255 | var writer = file.writer(); |
| 1255 | try writer.writeByteNTimes('a', mem.page_size); | |
| 1256 | try writer.writeByteNTimes('a', heap.max_page_size); | |
| 1256 | 1257 | |
| 1257 | 1258 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); |
| 1258 | try expectEqualStrings(("a" ** mem.page_size) ++ "\n", output.items); | |
| 1259 | try expectEqualStrings(("a" ** heap.max_page_size) ++ "\n", output.items); | |
| 1259 | 1260 | output.clearRetainingCapacity(); |
| 1260 | 1261 | } |
| 1261 | 1262 | { |
| ... | ... | @@ -1265,18 +1266,18 @@ test printLineFromFileAnyOs { |
| 1265 | 1266 | defer allocator.free(path); |
| 1266 | 1267 | |
| 1267 | 1268 | var writer = file.writer(); |
| 1268 | try writer.writeByteNTimes('a', 3 * mem.page_size); | |
| 1269 | try writer.writeByteNTimes('a', 3 * heap.max_page_size); | |
| 1269 | 1270 | |
| 1270 | 1271 | try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); |
| 1271 | 1272 | |
| 1272 | 1273 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); |
| 1273 | try expectEqualStrings(("a" ** (3 * mem.page_size)) ++ "\n", output.items); | |
| 1274 | try expectEqualStrings(("a" ** (3 * heap.max_page_size)) ++ "\n", output.items); | |
| 1274 | 1275 | output.clearRetainingCapacity(); |
| 1275 | 1276 | |
| 1276 | 1277 | try writer.writeAll("a\na"); |
| 1277 | 1278 | |
| 1278 | 1279 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); |
| 1279 | try expectEqualStrings(("a" ** (3 * mem.page_size)) ++ "a\n", output.items); | |
| 1280 | try expectEqualStrings(("a" ** (3 * heap.max_page_size)) ++ "a\n", output.items); | |
| 1280 | 1281 | output.clearRetainingCapacity(); |
| 1281 | 1282 | |
| 1282 | 1283 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); |
| ... | ... | @@ -1290,7 +1291,7 @@ test printLineFromFileAnyOs { |
| 1290 | 1291 | defer allocator.free(path); |
| 1291 | 1292 | |
| 1292 | 1293 | var writer = file.writer(); |
| 1293 | const real_file_start = 3 * mem.page_size; | |
| 1294 | const real_file_start = 3 * heap.min_page_size; | |
| 1294 | 1295 | try writer.writeByteNTimes('\n', real_file_start); |
| 1295 | 1296 | try writer.writeAll("abc\ndef"); |
| 1296 | 1297 |
lib/std/debug/Dwarf.zig+5-5| ... | ... | @@ -2120,8 +2120,8 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize { |
| 2120 | 2120 | pub const ElfModule = struct { |
| 2121 | 2121 | base_address: usize, |
| 2122 | 2122 | dwarf: Dwarf, |
| 2123 | mapped_memory: []align(std.mem.page_size) const u8, | |
| 2124 | external_mapped_memory: ?[]align(std.mem.page_size) const u8, | |
| 2123 | mapped_memory: []align(std.heap.min_page_size) const u8, | |
| 2124 | external_mapped_memory: ?[]align(std.heap.min_page_size) const u8, | |
| 2125 | 2125 | |
| 2126 | 2126 | pub fn deinit(self: *@This(), allocator: Allocator) void { |
| 2127 | 2127 | self.dwarf.deinit(allocator); |
| ... | ... | @@ -2167,11 +2167,11 @@ pub const ElfModule = struct { |
| 2167 | 2167 | /// sections from an external file. |
| 2168 | 2168 | pub fn load( |
| 2169 | 2169 | gpa: Allocator, |
| 2170 | mapped_mem: []align(std.mem.page_size) const u8, | |
| 2170 | mapped_mem: []align(std.heap.min_page_size) const u8, | |
| 2171 | 2171 | build_id: ?[]const u8, |
| 2172 | 2172 | expected_crc: ?u32, |
| 2173 | 2173 | parent_sections: *Dwarf.SectionArray, |
| 2174 | parent_mapped_mem: ?[]align(std.mem.page_size) const u8, | |
| 2174 | parent_mapped_mem: ?[]align(std.heap.min_page_size) const u8, | |
| 2175 | 2175 | elf_filename: ?[]const u8, |
| 2176 | 2176 | ) LoadError!Dwarf.ElfModule { |
| 2177 | 2177 | if (expected_crc) |crc| if (crc != std.hash.crc.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo; |
| ... | ... | @@ -2423,7 +2423,7 @@ pub const ElfModule = struct { |
| 2423 | 2423 | build_id: ?[]const u8, |
| 2424 | 2424 | expected_crc: ?u32, |
| 2425 | 2425 | parent_sections: *Dwarf.SectionArray, |
| 2426 | parent_mapped_mem: ?[]align(std.mem.page_size) const u8, | |
| 2426 | parent_mapped_mem: ?[]align(std.heap.min_page_size) const u8, | |
| 2427 | 2427 | ) LoadError!Dwarf.ElfModule { |
| 2428 | 2428 | const elf_file = elf_file_path.root_dir.handle.openFile(elf_file_path.sub_path, .{}) catch |err| switch (err) { |
| 2429 | 2429 | error.FileNotFound => return missing(), |
lib/std/debug/Info.zig-1| ... | ... | @@ -10,7 +10,6 @@ const std = @import("../std.zig"); |
| 10 | 10 | const Allocator = std.mem.Allocator; |
| 11 | 11 | const Path = std.Build.Cache.Path; |
| 12 | 12 | const Dwarf = std.debug.Dwarf; |
| 13 | const page_size = std.mem.page_size; | |
| 14 | 13 | const assert = std.debug.assert; |
| 15 | 14 | const Coverage = std.debug.Coverage; |
| 16 | 15 | const SourceLocation = std.debug.Coverage.SourceLocation; |
lib/std/debug/MemoryAccessor.zig+5-4| ... | ... | @@ -7,7 +7,7 @@ const native_os = builtin.os.tag; |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const posix = std.posix; |
| 9 | 9 | const File = std.fs.File; |
| 10 | const page_size = std.mem.page_size; | |
| 10 | const min_page_size = std.heap.min_page_size; | |
| 11 | 11 | |
| 12 | 12 | const MemoryAccessor = @This(); |
| 13 | 13 | |
| ... | ... | @@ -93,9 +93,10 @@ pub fn isValidMemory(address: usize) bool { |
| 93 | 93 | // We are unable to determine validity of memory for freestanding targets |
| 94 | 94 | if (native_os == .freestanding or native_os == .other or native_os == .uefi) return true; |
| 95 | 95 | |
| 96 | const aligned_address = address & ~@as(usize, @intCast((page_size - 1))); | |
| 96 | const page_size = std.heap.pageSize(); | |
| 97 | const aligned_address = address & ~(page_size - 1); | |
| 97 | 98 | if (aligned_address == 0) return false; |
| 98 | const aligned_memory = @as([*]align(page_size) u8, @ptrFromInt(aligned_address))[0..page_size]; | |
| 99 | const aligned_memory = @as([*]align(min_page_size) u8, @ptrFromInt(aligned_address))[0..page_size]; | |
| 99 | 100 | |
| 100 | 101 | if (native_os == .windows) { |
| 101 | 102 | const windows = std.os.windows; |
| ... | ... | @@ -104,7 +105,7 @@ pub fn isValidMemory(address: usize) bool { |
| 104 | 105 | |
| 105 | 106 | // The only error this function can throw is ERROR_INVALID_PARAMETER. |
| 106 | 107 | // supply an address that invalid i'll be thrown. |
| 107 | const rc = windows.VirtualQuery(aligned_memory, &memory_info, aligned_memory.len) catch { | |
| 108 | const rc = windows.VirtualQuery(@ptrCast(aligned_memory), &memory_info, aligned_memory.len) catch { | |
| 108 | 109 | return false; |
| 109 | 110 | }; |
| 110 | 111 |
lib/std/debug/SelfInfo.zig+3-3| ... | ... | @@ -504,7 +504,7 @@ pub const Module = switch (native_os) { |
| 504 | 504 | .macos, .ios, .watchos, .tvos, .visionos => struct { |
| 505 | 505 | base_address: usize, |
| 506 | 506 | vmaddr_slide: usize, |
| 507 | mapped_memory: []align(mem.page_size) const u8, | |
| 507 | mapped_memory: []align(std.heap.min_page_size) const u8, | |
| 508 | 508 | symbols: []const MachoSymbol, |
| 509 | 509 | strings: [:0]const u8, |
| 510 | 510 | ofiles: OFileTable, |
| ... | ... | @@ -1046,7 +1046,7 @@ pub fn readElfDebugInfo( |
| 1046 | 1046 | build_id: ?[]const u8, |
| 1047 | 1047 | expected_crc: ?u32, |
| 1048 | 1048 | parent_sections: *Dwarf.SectionArray, |
| 1049 | parent_mapped_mem: ?[]align(mem.page_size) const u8, | |
| 1049 | parent_mapped_mem: ?[]align(std.heap.min_page_size) const u8, | |
| 1050 | 1050 | ) !Dwarf.ElfModule { |
| 1051 | 1051 | nosuspend { |
| 1052 | 1052 | const elf_file = (if (elf_filename) |filename| blk: { |
| ... | ... | @@ -1088,7 +1088,7 @@ const MachoSymbol = struct { |
| 1088 | 1088 | |
| 1089 | 1089 | /// Takes ownership of file, even on error. |
| 1090 | 1090 | /// TODO it's weird to take ownership even on error, rework this code. |
| 1091 | fn mapWholeFile(file: File) ![]align(mem.page_size) const u8 { | |
| 1091 | fn mapWholeFile(file: File) ![]align(std.heap.min_page_size) const u8 { | |
| 1092 | 1092 | nosuspend { |
| 1093 | 1093 | defer file.close(); |
| 1094 | 1094 |
lib/std/dynamic_library.zig+6-5| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const mem = std.mem; |
| 4 | const heap = std.heap; | |
| 4 | 5 | const testing = std.testing; |
| 5 | 6 | const elf = std.elf; |
| 6 | 7 | const windows = std.os.windows; |
| ... | ... | @@ -143,7 +144,7 @@ pub const ElfDynLib = struct { |
| 143 | 144 | hashtab: [*]posix.Elf_Symndx, |
| 144 | 145 | versym: ?[*]elf.Versym, |
| 145 | 146 | verdef: ?*elf.Verdef, |
| 146 | memory: []align(mem.page_size) u8, | |
| 147 | memory: []align(heap.min_page_size) u8, | |
| 147 | 148 | |
| 148 | 149 | pub const Error = ElfDynLibError; |
| 149 | 150 | |
| ... | ... | @@ -223,7 +224,7 @@ pub const ElfDynLib = struct { |
| 223 | 224 | // corresponding to the actual LOAD sections. |
| 224 | 225 | const file_bytes = try posix.mmap( |
| 225 | 226 | null, |
| 226 | mem.alignForward(usize, size, mem.page_size), | |
| 227 | mem.alignForward(usize, size, heap.pageSize()), | |
| 227 | 228 | posix.PROT.READ, |
| 228 | 229 | .{ .TYPE = .PRIVATE }, |
| 229 | 230 | fd, |
| ... | ... | @@ -284,10 +285,10 @@ pub const ElfDynLib = struct { |
| 284 | 285 | elf.PT_LOAD => { |
| 285 | 286 | // The VirtAddr may not be page-aligned; in such case there will be |
| 286 | 287 | // extra nonsense mapped before/after the VirtAddr,MemSiz |
| 287 | const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, mem.page_size) - 1); | |
| 288 | const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, heap.pageSize()) - 1); | |
| 288 | 289 | const extra_bytes = (base + ph.p_vaddr) - aligned_addr; |
| 289 | const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, mem.page_size); | |
| 290 | const ptr = @as([*]align(mem.page_size) u8, @ptrFromInt(aligned_addr)); | |
| 290 | const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, heap.pageSize()); | |
| 291 | const ptr = @as([*]align(heap.min_page_size) u8, @ptrFromInt(aligned_addr)); | |
| 291 | 292 | const prot = elfToMmapProt(ph.p_flags); |
| 292 | 293 | if ((ph.p_flags & elf.PF_W) == 0) { |
| 293 | 294 | // If it does not need write access, it can be mapped from the fd. |
lib/std/fifo.zig+1-1| ... | ... | @@ -91,7 +91,7 @@ pub fn LinearFifo( |
| 91 | 91 | mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]); |
| 92 | 92 | self.head = 0; |
| 93 | 93 | } else { |
| 94 | var tmp: [mem.page_size / 2 / @sizeOf(T)]T = undefined; | |
| 94 | var tmp: [4096 / 2 / @sizeOf(T)]T = undefined; | |
| 95 | 95 | |
| 96 | 96 | while (self.head != 0) { |
| 97 | 97 | const n = @min(self.head, tmp.len); |
lib/std/heap.zig+391-7| ... | ... | @@ -8,6 +8,376 @@ const c = std.c; |
| 8 | 8 | const Allocator = std.mem.Allocator; |
| 9 | 9 | const windows = std.os.windows; |
| 10 | 10 | |
| 11 | const default_min_page_size: ?usize = switch (builtin.os.tag) { | |
| 12 | .bridgeos, .driverkit, .ios, .macos, .tvos, .visionos, .watchos => switch (builtin.cpu.arch) { | |
| 13 | .x86_64 => 4 << 10, | |
| 14 | .aarch64 => 16 << 10, | |
| 15 | else => null, | |
| 16 | }, | |
| 17 | .windows => switch (builtin.cpu.arch) { | |
| 18 | // -- <https://devblogs.microsoft.com/oldnewthing/20210510-00/?p=105200> | |
| 19 | .x86, .x86_64 => 4 << 10, | |
| 20 | // SuperH => 4 << 10, | |
| 21 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 22 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => 4 << 10, | |
| 23 | // DEC Alpha => 8 << 10, | |
| 24 | // Itanium => 8 << 10, | |
| 25 | .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, | |
| 26 | else => null, | |
| 27 | }, | |
| 28 | .wasi => switch (builtin.cpu.arch) { | |
| 29 | .wasm32, .wasm64 => 64 << 10, | |
| 30 | else => null, | |
| 31 | }, | |
| 32 | // https://github.com/tianocore/edk2/blob/b158dad150bf02879668f72ce306445250838201/MdePkg/Include/Uefi/UefiBaseType.h#L180-L187 | |
| 33 | .uefi => 4 << 10, | |
| 34 | .freebsd => switch (builtin.cpu.arch) { | |
| 35 | // FreeBSD/sys/* | |
| 36 | .x86, .x86_64 => 4 << 10, | |
| 37 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 38 | .aarch64, .aarch64_be => 4 << 10, | |
| 39 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 40 | .riscv32, .riscv64 => 4 << 10, | |
| 41 | else => null, | |
| 42 | }, | |
| 43 | .netbsd => switch (builtin.cpu.arch) { | |
| 44 | // NetBSD/sys/arch/* | |
| 45 | .x86, .x86_64 => 4 << 10, | |
| 46 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 47 | .aarch64, .aarch64_be => 4 << 10, | |
| 48 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 49 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 50 | .sparc => 4 << 10, | |
| 51 | .sparc64 => 8 << 10, | |
| 52 | .riscv32, .riscv64 => 4 << 10, | |
| 53 | // Sun-2 | |
| 54 | .m68k => 2 << 10, | |
| 55 | else => null, | |
| 56 | }, | |
| 57 | .dragonfly => switch (builtin.cpu.arch) { | |
| 58 | .x86, .x86_64 => 4 << 10, | |
| 59 | else => null, | |
| 60 | }, | |
| 61 | .openbsd => switch (builtin.cpu.arch) { | |
| 62 | // OpenBSD/sys/arch/* | |
| 63 | .x86, .x86_64 => 4 << 10, | |
| 64 | .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, | |
| 65 | .mips64, .mips64el => 4 << 10, | |
| 66 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 67 | .riscv64 => 4 << 10, | |
| 68 | .sparc64 => 8 << 10, | |
| 69 | else => null, | |
| 70 | }, | |
| 71 | .solaris, .illumos => switch (builtin.cpu.arch) { | |
| 72 | // src/uts/*/sys/machparam.h | |
| 73 | .x86, .x86_64 => 4 << 10, | |
| 74 | .sparc, .sparc64 => 8 << 10, | |
| 75 | else => null, | |
| 76 | }, | |
| 77 | .fuchsia => switch (builtin.cpu.arch) { | |
| 78 | // fuchsia/kernel/arch/*/include/arch/defines.h | |
| 79 | .x86_64 => 4 << 10, | |
| 80 | .aarch64, .aarch64_be => 4 << 10, | |
| 81 | .riscv64 => 4 << 10, | |
| 82 | else => null, | |
| 83 | }, | |
| 84 | // https://github.com/SerenityOS/serenity/blob/62b938b798dc009605b5df8a71145942fc53808b/Kernel/API/POSIX/sys/limits.h#L11-L13 | |
| 85 | .serenity => 4 << 10, | |
| 86 | .haiku => switch (builtin.cpu.arch) { | |
| 87 | // haiku/headers/posix/arch/*/limits.h | |
| 88 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 89 | .aarch64, .aarch64_be => 4 << 10, | |
| 90 | .m68k => 4 << 10, | |
| 91 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 92 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 93 | .riscv64 => 4 << 10, | |
| 94 | .sparc64 => 8 << 10, | |
| 95 | .x86, .x86_64 => 4 << 10, | |
| 96 | else => null, | |
| 97 | }, | |
| 98 | .hurd => switch (builtin.cpu.arch) { | |
| 99 | // gnumach/*/include/mach/*/vm_param.h | |
| 100 | .x86, .x86_64 => 4 << 10, | |
| 101 | .aarch64 => null, | |
| 102 | else => null, | |
| 103 | }, | |
| 104 | .plan9 => switch (builtin.cpu.arch) { | |
| 105 | // 9front/sys/src/9/*/mem.h | |
| 106 | .x86, .x86_64 => 4 << 10, | |
| 107 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 108 | .aarch64, .aarch64_be => 4 << 10, | |
| 109 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 110 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => 4 << 10, | |
| 111 | .sparc => 4 << 10, | |
| 112 | else => null, | |
| 113 | }, | |
| 114 | .ps3 => switch (builtin.cpu.arch) { | |
| 115 | // cell/SDK_doc/en/html/C_and_C++_standard_libraries/stdlib.html | |
| 116 | .powerpc64 => 1 << 20, // 1 MiB | |
| 117 | else => null, | |
| 118 | }, | |
| 119 | .ps4 => switch (builtin.cpu.arch) { | |
| 120 | // https://github.com/ps4dev/ps4sdk/blob/4df9d001b66ae4ec07d9a51b62d1e4c5e270eecc/include/machine/param.h#L95 | |
| 121 | .x86, .x86_64 => 4 << 10, | |
| 122 | else => null, | |
| 123 | }, | |
| 124 | .ps5 => switch (builtin.cpu.arch) { | |
| 125 | // https://github.com/PS5Dev/PS5SDK/blob/a2e03a2a0231a3a3397fa6cd087a01ca6d04f273/include/machine/param.h#L95 | |
| 126 | .x86, .x86_64 => 16 << 10, | |
| 127 | else => null, | |
| 128 | }, | |
| 129 | // system/lib/libc/musl/arch/emscripten/bits/limits.h | |
| 130 | .emscripten => 64 << 10, | |
| 131 | .linux => switch (builtin.cpu.arch) { | |
| 132 | // Linux/arch/*/Kconfig | |
| 133 | .arc => 4 << 10, | |
| 134 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 135 | .aarch64, .aarch64_be => 4 << 10, | |
| 136 | .csky => 4 << 10, | |
| 137 | .hexagon => 4 << 10, | |
| 138 | .loongarch32, .loongarch64 => 4 << 10, | |
| 139 | .m68k => 4 << 10, | |
| 140 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 141 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 142 | .riscv32, .riscv64 => 4 << 10, | |
| 143 | .s390x => 4 << 10, | |
| 144 | .sparc => 4 << 10, | |
| 145 | .sparc64 => 8 << 10, | |
| 146 | .x86, .x86_64 => 4 << 10, | |
| 147 | .xtensa => 4 << 10, | |
| 148 | else => null, | |
| 149 | }, | |
| 150 | .freestanding => switch (builtin.cpu.arch) { | |
| 151 | .wasm32, .wasm64 => 64 << 10, | |
| 152 | else => null, | |
| 153 | }, | |
| 154 | else => null, | |
| 155 | }; | |
| 156 | ||
| 157 | const default_max_page_size: ?usize = switch (builtin.os.tag) { | |
| 158 | .bridgeos, .driverkit, .ios, .macos, .tvos, .visionos, .watchos => switch (builtin.cpu.arch) { | |
| 159 | .x86_64 => 4 << 10, | |
| 160 | .aarch64 => 16 << 10, | |
| 161 | else => null, | |
| 162 | }, | |
| 163 | .windows => switch (builtin.cpu.arch) { | |
| 164 | // -- <https://devblogs.microsoft.com/oldnewthing/20210510-00/?p=105200> | |
| 165 | .x86, .x86_64 => 4 << 10, | |
| 166 | // SuperH => 4 << 10, | |
| 167 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 168 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => 4 << 10, | |
| 169 | // DEC Alpha => 8 << 10, | |
| 170 | // Itanium => 8 << 10, | |
| 171 | .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, | |
| 172 | else => null, | |
| 173 | }, | |
| 174 | .wasi => switch (builtin.cpu.arch) { | |
| 175 | .wasm32, .wasm64 => 64 << 10, | |
| 176 | else => null, | |
| 177 | }, | |
| 178 | // https://github.com/tianocore/edk2/blob/b158dad150bf02879668f72ce306445250838201/MdePkg/Include/Uefi/UefiBaseType.h#L180-L187 | |
| 179 | .uefi => 4 << 10, | |
| 180 | .freebsd => switch (builtin.cpu.arch) { | |
| 181 | // FreeBSD/sys/* | |
| 182 | .x86, .x86_64 => 4 << 10, | |
| 183 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 184 | .aarch64, .aarch64_be => 4 << 10, | |
| 185 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 186 | .riscv32, .riscv64 => 4 << 10, | |
| 187 | else => null, | |
| 188 | }, | |
| 189 | .netbsd => switch (builtin.cpu.arch) { | |
| 190 | // NetBSD/sys/arch/* | |
| 191 | .x86, .x86_64 => 4 << 10, | |
| 192 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 193 | .aarch64, .aarch64_be => 64 << 10, | |
| 194 | .mips, .mipsel, .mips64, .mips64el => 16 << 10, | |
| 195 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 16 << 10, | |
| 196 | .sparc => 8 << 10, | |
| 197 | .sparc64 => 8 << 10, | |
| 198 | .riscv32, .riscv64 => 4 << 10, | |
| 199 | .m68k => 8 << 10, | |
| 200 | else => null, | |
| 201 | }, | |
| 202 | .dragonfly => switch (builtin.cpu.arch) { | |
| 203 | .x86, .x86_64 => 4 << 10, | |
| 204 | else => null, | |
| 205 | }, | |
| 206 | .openbsd => switch (builtin.cpu.arch) { | |
| 207 | // OpenBSD/sys/arch/* | |
| 208 | .x86, .x86_64 => 4 << 10, | |
| 209 | .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, | |
| 210 | .mips64, .mips64el => 16 << 10, | |
| 211 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 212 | .riscv64 => 4 << 10, | |
| 213 | .sparc64 => 8 << 10, | |
| 214 | else => null, | |
| 215 | }, | |
| 216 | .solaris, .illumos => switch (builtin.cpu.arch) { | |
| 217 | // src/uts/*/sys/machparam.h | |
| 218 | .x86, .x86_64 => 4 << 10, | |
| 219 | .sparc, .sparc64 => 8 << 10, | |
| 220 | else => null, | |
| 221 | }, | |
| 222 | .fuchsia => switch (builtin.cpu.arch) { | |
| 223 | // fuchsia/kernel/arch/*/include/arch/defines.h | |
| 224 | .x86_64 => 4 << 10, | |
| 225 | .aarch64, .aarch64_be => 4 << 10, | |
| 226 | .riscv64 => 4 << 10, | |
| 227 | else => null, | |
| 228 | }, | |
| 229 | // https://github.com/SerenityOS/serenity/blob/62b938b798dc009605b5df8a71145942fc53808b/Kernel/API/POSIX/sys/limits.h#L11-L13 | |
| 230 | .serenity => 4 << 10, | |
| 231 | .haiku => switch (builtin.cpu.arch) { | |
| 232 | // haiku/headers/posix/arch/*/limits.h | |
| 233 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 234 | .aarch64, .aarch64_be => 4 << 10, | |
| 235 | .m68k => 4 << 10, | |
| 236 | .mips, .mipsel, .mips64, .mips64el => 4 << 10, | |
| 237 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, | |
| 238 | .riscv64 => 4 << 10, | |
| 239 | .sparc64 => 8 << 10, | |
| 240 | .x86, .x86_64 => 4 << 10, | |
| 241 | else => null, | |
| 242 | }, | |
| 243 | .hurd => switch (builtin.cpu.arch) { | |
| 244 | // gnumach/*/include/mach/*/vm_param.h | |
| 245 | .x86, .x86_64 => 4 << 10, | |
| 246 | .aarch64 => null, | |
| 247 | else => null, | |
| 248 | }, | |
| 249 | .plan9 => switch (builtin.cpu.arch) { | |
| 250 | // 9front/sys/src/9/*/mem.h | |
| 251 | .x86, .x86_64 => 4 << 10, | |
| 252 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 253 | .aarch64, .aarch64_be => 64 << 10, | |
| 254 | .mips, .mipsel, .mips64, .mips64el => 16 << 10, | |
| 255 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => 4 << 10, | |
| 256 | .sparc => 4 << 10, | |
| 257 | else => null, | |
| 258 | }, | |
| 259 | .ps3 => switch (builtin.cpu.arch) { | |
| 260 | // cell/SDK_doc/en/html/C_and_C++_standard_libraries/stdlib.html | |
| 261 | .powerpc64 => 1 << 20, // 1 MiB | |
| 262 | else => null, | |
| 263 | }, | |
| 264 | .ps4 => switch (builtin.cpu.arch) { | |
| 265 | // https://github.com/ps4dev/ps4sdk/blob/4df9d001b66ae4ec07d9a51b62d1e4c5e270eecc/include/machine/param.h#L95 | |
| 266 | .x86, .x86_64 => 4 << 10, | |
| 267 | else => null, | |
| 268 | }, | |
| 269 | .ps5 => switch (builtin.cpu.arch) { | |
| 270 | // https://github.com/PS5Dev/PS5SDK/blob/a2e03a2a0231a3a3397fa6cd087a01ca6d04f273/include/machine/param.h#L95 | |
| 271 | .x86, .x86_64 => 16 << 10, | |
| 272 | else => null, | |
| 273 | }, | |
| 274 | // system/lib/libc/musl/arch/emscripten/bits/limits.h | |
| 275 | .emscripten => 64 << 10, | |
| 276 | .linux => switch (builtin.cpu.arch) { | |
| 277 | // Linux/arch/*/Kconfig | |
| 278 | .arc => 16 << 10, | |
| 279 | .thumb, .thumbeb, .arm, .armeb => 4 << 10, | |
| 280 | .aarch64, .aarch64_be => 64 << 10, | |
| 281 | .csky => 4 << 10, | |
| 282 | .hexagon => 256 << 10, | |
| 283 | .loongarch32, .loongarch64 => 64 << 10, | |
| 284 | .m68k => 8 << 10, | |
| 285 | .mips, .mipsel, .mips64, .mips64el => 64 << 10, | |
| 286 | .powerpc, .powerpc64, .powerpc64le, .powerpcle => 256 << 10, | |
| 287 | .riscv32, .riscv64 => 4 << 10, | |
| 288 | .s390x => 4 << 10, | |
| 289 | .sparc => 4 << 10, | |
| 290 | .sparc64 => 8 << 10, | |
| 291 | .x86, .x86_64 => 4 << 10, | |
| 292 | .xtensa => 4 << 10, | |
| 293 | else => null, | |
| 294 | }, | |
| 295 | .freestanding => switch (builtin.cpu.arch) { | |
| 296 | .wasm32, .wasm64 => 64 << 10, | |
| 297 | else => null, | |
| 298 | }, | |
| 299 | else => null, | |
| 300 | }; | |
| 301 | ||
| 302 | /// The compile-time minimum page size that the target might have. | |
| 303 | /// All pointers from `mmap` or `VirtualAlloc` are aligned to at least `min_page_size`, but their | |
| 304 | /// actual alignment may be much bigger. | |
| 305 | /// This value can be overridden via `std.options.min_page_size`. | |
| 306 | /// On many systems, the actual page size can only be determined at runtime with `pageSize()`. | |
| 307 | pub const min_page_size: usize = std.options.min_page_size orelse (default_min_page_size orelse if (builtin.os.tag == .freestanding or builtin.os.tag == .other) | |
| 308 | @compileError("freestanding/other explicitly has no min_page_size. One can be provided with std.options.min_page_size") | |
| 309 | else | |
| 310 | @compileError(@tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " has no min_page_size. One can be provided with std.options.min_page_size")); | |
| 311 | ||
| 312 | /// The compile-time maximum page size that the target might have. | |
| 313 | /// Targeting a system with a larger page size may require overriding `std.options.max_page_size`, | |
| 314 | /// as well as using the linker arugment `-z max-page-size=`. | |
| 315 | /// The actual page size can only be determined at runtime with `pageSize()`. | |
| 316 | pub const max_page_size: usize = std.options.max_page_size orelse (default_max_page_size orelse if (builtin.os.tag == .freestanding or builtin.os.tag == .other) | |
| 317 | @compileError("freestanding/other explicitly has no max_page_size. One can be provided with std.options.max_page_size") | |
| 318 | else | |
| 319 | @compileError(@tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " has no max_page_size. One can be provided with std.options.max_page_size")); | |
| 320 | ||
| 321 | /// Returns the system page size. | |
| 322 | /// If the page size is comptime-known, `pageSize()` returns it directly. | |
| 323 | /// Otherwise, `pageSize()` defers to `std.options.queryPageSizeFn()`. | |
| 324 | pub fn pageSize() usize { | |
| 325 | if (min_page_size == max_page_size) { | |
| 326 | return min_page_size; | |
| 327 | } | |
| 328 | return std.options.queryPageSizeFn(); | |
| 329 | } | |
| 330 | ||
| 331 | // A cache used by `defaultQueryPageSize()` to avoid repeating syscalls. | |
| 332 | var page_size_cache = std.atomic.Value(usize).init(0); | |
| 333 | ||
| 334 | // The default implementation in `std.options.queryPageSizeFn`. | |
| 335 | // The first time it is called, it asserts that the page size is within the comptime bounds. | |
| 336 | pub fn defaultQueryPageSize() usize { | |
| 337 | var size = page_size_cache.load(.unordered); | |
| 338 | if (size > 0) return size; | |
| 339 | size = switch (builtin.os.tag) { | |
| 340 | .linux => if (builtin.link_libc) @intCast(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE))) else std.os.linux.getauxval(std.elf.AT_PAGESZ), | |
| 341 | .bridgeos, .driverkit, .ios, .macos, .tvos, .visionos, .watchos => blk: { | |
| 342 | const task_port = std.c.mach_task_self(); | |
| 343 | // mach_task_self may fail "if there are any resource failures or other errors". | |
| 344 | if (task_port == std.c.TASK_NULL) | |
| 345 | break :blk 0; | |
| 346 | var info_count = std.c.TASK_VM_INFO_COUNT; | |
| 347 | var vm_info: std.c.task_vm_info_data_t = undefined; | |
| 348 | vm_info.page_size = 0; | |
| 349 | _ = std.c.task_info( | |
| 350 | task_port, | |
| 351 | std.c.TASK_VM_INFO, | |
| 352 | @as(std.c.task_info_t, @ptrCast(&vm_info)), | |
| 353 | &info_count, | |
| 354 | ); | |
| 355 | assert(vm_info.page_size != 0); | |
| 356 | break :blk @as(usize, @intCast(vm_info.page_size)); | |
| 357 | }, | |
| 358 | .windows => blk: { | |
| 359 | var info: std.os.windows.SYSTEM_INFO = undefined; | |
| 360 | std.os.windows.kernel32.GetSystemInfo(&info); | |
| 361 | break :blk info.dwPageSize; | |
| 362 | }, | |
| 363 | else => if (builtin.link_libc) | |
| 364 | if (std.c._SC != void and @hasDecl(std.c._SC, "PAGESIZE")) | |
| 365 | @intCast(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE))) | |
| 366 | else | |
| 367 | @compileError("missing _SC.PAGESIZE declaration for " ++ @tagName(builtin.os.tag) ++ "-" ++ @tagName(builtin.os.tag)) | |
| 368 | else if (builtin.os.tag == .freestanding or builtin.os.tag == .other) | |
| 369 | @compileError("pageSize on freestanding/other is not supported with the default std.options.queryPageSizeFn") | |
| 370 | else | |
| 371 | @compileError("pageSize on " ++ @tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " is not supported without linking libc, using the default implementation"), | |
| 372 | }; | |
| 373 | ||
| 374 | assert(size >= min_page_size); | |
| 375 | assert(size <= max_page_size); | |
| 376 | page_size_cache.store(size, .unordered); | |
| 377 | ||
| 378 | return size; | |
| 379 | } | |
| 380 | ||
| 11 | 381 | pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator; |
| 12 | 382 | pub const loggingAllocator = @import("heap/logging_allocator.zig").loggingAllocator; |
| 13 | 383 | pub const ScopedLoggingAllocator = @import("heap/logging_allocator.zig").ScopedLoggingAllocator; |
| ... | ... | @@ -29,7 +399,7 @@ pub const MemoryPoolExtra = memory_pool.MemoryPoolExtra; |
| 29 | 399 | pub const MemoryPoolOptions = memory_pool.Options; |
| 30 | 400 | |
| 31 | 401 | /// TODO Utilize this on Windows. |
| 32 | pub var next_mmap_addr_hint: ?[*]align(mem.page_size) u8 = null; | |
| 402 | pub var next_mmap_addr_hint: ?[*]align(min_page_size) u8 = null; | |
| 33 | 403 | |
| 34 | 404 | const CAllocator = struct { |
| 35 | 405 | comptime { |
| ... | ... | @@ -256,7 +626,7 @@ pub const wasm_allocator: Allocator = .{ |
| 256 | 626 | /// Verifies that the adjusted length will still map to the full length |
| 257 | 627 | pub fn alignPageAllocLen(full_len: usize, len: usize) usize { |
| 258 | 628 | const aligned_len = mem.alignAllocLen(full_len, len); |
| 259 | assert(mem.alignForward(usize, aligned_len, mem.page_size) == full_len); | |
| 629 | assert(mem.alignForward(usize, aligned_len, pageSize()) == full_len); | |
| 260 | 630 | return aligned_len; |
| 261 | 631 | } |
| 262 | 632 | |
| ... | ... | @@ -615,13 +985,13 @@ test "PageAllocator" { |
| 615 | 985 | } |
| 616 | 986 | |
| 617 | 987 | if (builtin.os.tag == .windows) { |
| 618 | const slice = try allocator.alignedAlloc(u8, mem.page_size, 128); | |
| 988 | const slice = try allocator.alignedAlloc(u8, min_page_size, 128); | |
| 619 | 989 | slice[0] = 0x12; |
| 620 | 990 | slice[127] = 0x34; |
| 621 | 991 | allocator.free(slice); |
| 622 | 992 | } |
| 623 | 993 | { |
| 624 | var buf = try allocator.alloc(u8, mem.page_size + 1); | |
| 994 | var buf = try allocator.alloc(u8, pageSize() + 1); | |
| 625 | 995 | defer allocator.free(buf); |
| 626 | 996 | buf = try allocator.realloc(buf, 1); // shrink past the page boundary |
| 627 | 997 | } |
| ... | ... | @@ -824,7 +1194,7 @@ pub fn testAllocatorLargeAlignment(base_allocator: mem.Allocator) !void { |
| 824 | 1194 | var validationAllocator = mem.validationWrap(base_allocator); |
| 825 | 1195 | const allocator = validationAllocator.allocator(); |
| 826 | 1196 | |
| 827 | const large_align: usize = mem.page_size / 2; | |
| 1197 | const large_align: usize = min_page_size / 2; | |
| 828 | 1198 | |
| 829 | 1199 | var align_mask: usize = undefined; |
| 830 | 1200 | align_mask = @shlWithOverflow(~@as(usize, 0), @as(Allocator.Log2Align, @ctz(large_align)))[0]; |
| ... | ... | @@ -857,7 +1227,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 857 | 1227 | var fib = FixedBufferAllocator.init(&debug_buffer); |
| 858 | 1228 | const debug_allocator = fib.allocator(); |
| 859 | 1229 | |
| 860 | const alloc_size = mem.page_size * 2 + 50; | |
| 1230 | const alloc_size = pageSize() * 2 + 50; | |
| 861 | 1231 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 862 | 1232 | defer allocator.free(slice); |
| 863 | 1233 | |
| ... | ... | @@ -866,7 +1236,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 866 | 1236 | // which is 16 pages, hence the 32. This test may require to increase |
| 867 | 1237 | // the size of the allocations feeding the `allocator` parameter if they |
| 868 | 1238 | // fail, because of this high over-alignment we want to have. |
| 869 | while (@intFromPtr(slice.ptr) == mem.alignForward(usize, @intFromPtr(slice.ptr), mem.page_size * 32)) { | |
| 1239 | while (@intFromPtr(slice.ptr) == mem.alignForward(usize, @intFromPtr(slice.ptr), pageSize() * 32)) { | |
| 870 | 1240 | try stuff_to_free.append(slice); |
| 871 | 1241 | slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 872 | 1242 | } |
| ... | ... | @@ -881,6 +1251,20 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 881 | 1251 | try testing.expect(slice[60] == 0x34); |
| 882 | 1252 | } |
| 883 | 1253 | |
| 1254 | test "pageSize() smoke test" { | |
| 1255 | const size = std.heap.pageSize(); | |
| 1256 | // Check that pageSize is a power of 2. | |
| 1257 | std.debug.assert(size & (size - 1) == 0); | |
| 1258 | } | |
| 1259 | ||
| 1260 | test "defaultQueryPageSize() smoke test" { | |
| 1261 | // queryPageSize() does not always get called by pageSize() | |
| 1262 | if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; | |
| 1263 | const size = defaultQueryPageSize(); | |
| 1264 | // Check that pageSize is a power of 2. | |
| 1265 | std.debug.assert(size & (size - 1) == 0); | |
| 1266 | } | |
| 1267 | ||
| 884 | 1268 | test { |
| 885 | 1269 | _ = LoggingAllocator; |
| 886 | 1270 | _ = LogToWriterAllocator; |
lib/std/heap/PageAllocator.zig+10-9| ... | ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const Allocator = std.mem.Allocator; |
| 4 | 4 | const mem = std.mem; |
| 5 | const heap = std.heap; | |
| 5 | 6 | const maxInt = std.math.maxInt; |
| 6 | 7 | const assert = std.debug.assert; |
| 7 | 8 | const native_os = builtin.os.tag; |
| ... | ... | @@ -18,7 +19,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 18 | 19 | _ = ra; |
| 19 | 20 | _ = log2_align; |
| 20 | 21 | assert(n > 0); |
| 21 | if (n > maxInt(usize) - (mem.page_size - 1)) return null; | |
| 22 | if (n > maxInt(usize) - (heap.pageSize() - 1)) return null; | |
| 22 | 23 | |
| 23 | 24 | if (native_os == .windows) { |
| 24 | 25 | const addr = windows.VirtualAlloc( |
| ... | ... | @@ -34,7 +35,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 34 | 35 | return @ptrCast(addr); |
| 35 | 36 | } |
| 36 | 37 | |
| 37 | const aligned_len = mem.alignForward(usize, n, mem.page_size); | |
| 38 | const aligned_len = mem.alignForward(usize, n, heap.pageSize()); | |
| 38 | 39 | const hint = @atomicLoad(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, .unordered); |
| 39 | 40 | const slice = posix.mmap( |
| 40 | 41 | hint, |
| ... | ... | @@ -44,8 +45,8 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 44 | 45 | -1, |
| 45 | 46 | 0, |
| 46 | 47 | ) catch return null; |
| 47 | assert(mem.isAligned(@intFromPtr(slice.ptr), mem.page_size)); | |
| 48 | const new_hint: [*]align(mem.page_size) u8 = @alignCast(slice.ptr + aligned_len); | |
| 48 | assert(mem.isAligned(@intFromPtr(slice.ptr), heap.pageSize())); | |
| 49 | const new_hint: [*]align(heap.min_page_size) u8 = @alignCast(slice.ptr + aligned_len); | |
| 49 | 50 | _ = @cmpxchgStrong(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, hint, new_hint, .monotonic, .monotonic); |
| 50 | 51 | return slice.ptr; |
| 51 | 52 | } |
| ... | ... | @@ -59,13 +60,13 @@ fn resize( |
| 59 | 60 | ) bool { |
| 60 | 61 | _ = log2_buf_align; |
| 61 | 62 | _ = return_address; |
| 62 | const new_size_aligned = mem.alignForward(usize, new_size, mem.page_size); | |
| 63 | const new_size_aligned = mem.alignForward(usize, new_size, heap.pageSize()); | |
| 63 | 64 | |
| 64 | 65 | if (native_os == .windows) { |
| 65 | 66 | if (new_size <= buf_unaligned.len) { |
| 66 | 67 | const base_addr = @intFromPtr(buf_unaligned.ptr); |
| 67 | 68 | const old_addr_end = base_addr + buf_unaligned.len; |
| 68 | const new_addr_end = mem.alignForward(usize, base_addr + new_size, mem.page_size); | |
| 69 | const new_addr_end = mem.alignForward(usize, base_addr + new_size, heap.pageSize()); | |
| 69 | 70 | if (old_addr_end > new_addr_end) { |
| 70 | 71 | // For shrinking that is not releasing, we will only |
| 71 | 72 | // decommit the pages not needed anymore. |
| ... | ... | @@ -77,14 +78,14 @@ fn resize( |
| 77 | 78 | } |
| 78 | 79 | return true; |
| 79 | 80 | } |
| 80 | const old_size_aligned = mem.alignForward(usize, buf_unaligned.len, mem.page_size); | |
| 81 | const old_size_aligned = mem.alignForward(usize, buf_unaligned.len, heap.pageSize()); | |
| 81 | 82 | if (new_size_aligned <= old_size_aligned) { |
| 82 | 83 | return true; |
| 83 | 84 | } |
| 84 | 85 | return false; |
| 85 | 86 | } |
| 86 | 87 | |
| 87 | const buf_aligned_len = mem.alignForward(usize, buf_unaligned.len, mem.page_size); | |
| 88 | const buf_aligned_len = mem.alignForward(usize, buf_unaligned.len, heap.pageSize()); | |
| 88 | 89 | if (new_size_aligned == buf_aligned_len) |
| 89 | 90 | return true; |
| 90 | 91 | |
| ... | ... | @@ -107,7 +108,7 @@ fn free(_: *anyopaque, slice: []u8, log2_buf_align: u8, return_address: usize) v |
| 107 | 108 | if (native_os == .windows) { |
| 108 | 109 | windows.VirtualFree(slice.ptr, 0, windows.MEM_RELEASE); |
| 109 | 110 | } else { |
| 110 | const buf_aligned_len = mem.alignForward(usize, slice.len, mem.page_size); | |
| 111 | const buf_aligned_len = mem.alignForward(usize, slice.len, heap.pageSize()); | |
| 111 | 112 | posix.munmap(@alignCast(slice.ptr[0..buf_aligned_len])); |
| 112 | 113 | } |
| 113 | 114 | } |
lib/std/heap/general_purpose_allocator.zig+78-51| ... | ... | @@ -48,7 +48,7 @@ |
| 48 | 48 | //! |
| 49 | 49 | //! ## Basic Design: |
| 50 | 50 | //! |
| 51 | //! Small allocations are divided into buckets: | |
| 51 | //! Small allocations are divided into buckets. For a max page size of 4K: | |
| 52 | 52 | //! |
| 53 | 53 | //! ``` |
| 54 | 54 | //! index obj_size |
| ... | ... | @@ -75,6 +75,9 @@ |
| 75 | 75 | //! BucketHeader, followed by "used bits", and two stack traces for each slot |
| 76 | 76 | //! (allocation trace and free trace). |
| 77 | 77 | //! |
| 78 | //! The buckets array contains buckets for every size class below `max_page_size`. | |
| 79 | //! At runtime, only size classes below `pageSize()` will actually be used for allocations. | |
| 80 | //! | |
| 78 | 81 | //! The "used bits" are 1 bit per slot representing whether the slot is used. |
| 79 | 82 | //! Allocations use the data to iterate to find a free slot. Frees assert that the |
| 80 | 83 | //! corresponding bit is 1 and set it to 0. |
| ... | ... | @@ -99,11 +102,13 @@ const math = std.math; |
| 99 | 102 | const assert = std.debug.assert; |
| 100 | 103 | const mem = std.mem; |
| 101 | 104 | const Allocator = std.mem.Allocator; |
| 102 | const page_size = std.mem.page_size; | |
| 105 | const min_page_size = std.heap.min_page_size; | |
| 106 | const max_page_size = std.heap.max_page_size; | |
| 107 | const pageSize = std.heap.pageSize; | |
| 103 | 108 | const StackTrace = std.builtin.StackTrace; |
| 104 | 109 | |
| 105 | 110 | /// Integer type for pointing to slots in a small allocation |
| 106 | const SlotIndex = std.meta.Int(.unsigned, math.log2(page_size) + 1); | |
| 111 | const SlotIndex = std.meta.Int(.unsigned, math.log2(max_page_size) + 1); | |
| 107 | 112 | |
| 108 | 113 | const default_test_stack_trace_frames: usize = if (builtin.is_test) 10 else 6; |
| 109 | 114 | const default_sys_stack_trace_frames: usize = if (std.debug.sys_can_stack_trace) default_test_stack_trace_frames else 0; |
| ... | ... | @@ -157,6 +162,9 @@ pub const Config = struct { |
| 157 | 162 | |
| 158 | 163 | pub const Check = enum { ok, leak }; |
| 159 | 164 | |
| 165 | var used_small_bucket_count_cache = std.atomic.Value(usize).init(0); | |
| 166 | var largest_used_bucket_object_size_cache = std.atomic.Value(usize).init(0); | |
| 167 | ||
| 160 | 168 | /// Default initialization of this struct is deprecated; use `.init` instead. |
| 161 | 169 | pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 162 | 170 | return struct { |
| ... | ... | @@ -206,9 +214,27 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 206 | 214 | |
| 207 | 215 | pub const Error = mem.Allocator.Error; |
| 208 | 216 | |
| 209 | const small_bucket_count = math.log2(page_size); | |
| 217 | const small_bucket_count = math.log2(max_page_size); | |
| 210 | 218 | const largest_bucket_object_size = 1 << (small_bucket_count - 1); |
| 211 | 219 | const LargestSizeClassInt = std.math.IntFittingRange(0, largest_bucket_object_size); |
| 220 | fn used_small_bucket_count() usize { | |
| 221 | const cached = used_small_bucket_count_cache.load(.monotonic); | |
| 222 | if (cached != 0) { | |
| 223 | return cached; | |
| 224 | } | |
| 225 | const val = math.log2(pageSize()); | |
| 226 | used_small_bucket_count_cache.store(val, .monotonic); | |
| 227 | return val; | |
| 228 | } | |
| 229 | fn largest_used_bucket_object_size() usize { | |
| 230 | const cached = largest_used_bucket_object_size_cache.load(.monotonic); | |
| 231 | if (cached != 0) { | |
| 232 | return cached; | |
| 233 | } | |
| 234 | const val = @as(usize, 1) << @truncate(used_small_bucket_count() - 1); | |
| 235 | largest_used_bucket_object_size_cache.store(val, .monotonic); | |
| 236 | return val; | |
| 237 | } | |
| 212 | 238 | |
| 213 | 239 | const bucketCompare = struct { |
| 214 | 240 | fn compare(a: *BucketHeader, b: *BucketHeader) std.math.Order { |
| ... | ... | @@ -261,7 +287,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 261 | 287 | // * stack_trace_addresses: [N]usize, // traces_per_slot for every allocation |
| 262 | 288 | |
| 263 | 289 | const BucketHeader = struct { |
| 264 | page: [*]align(page_size) u8, | |
| 290 | page: [*]align(min_page_size) u8, | |
| 265 | 291 | alloc_cursor: SlotIndex, |
| 266 | 292 | used_count: SlotIndex, |
| 267 | 293 | |
| ... | ... | @@ -273,14 +299,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 273 | 299 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); |
| 274 | 300 | const start_ptr = @as([*]u8, @ptrCast(bucket)) + bucketRequestedSizesStart(size_class); |
| 275 | 301 | const sizes = @as([*]LargestSizeClassInt, @ptrCast(@alignCast(start_ptr))); |
| 276 | const slot_count = @divExact(page_size, size_class); | |
| 302 | const slot_count = @divExact(pageSize(), size_class); | |
| 277 | 303 | return sizes[0..slot_count]; |
| 278 | 304 | } |
| 279 | 305 | |
| 280 | 306 | fn log2PtrAligns(bucket: *BucketHeader, size_class: usize) []u8 { |
| 281 | 307 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); |
| 282 | 308 | const aligns_ptr = @as([*]u8, @ptrCast(bucket)) + bucketAlignsStart(size_class); |
| 283 | const slot_count = @divExact(page_size, size_class); | |
| 309 | const slot_count = @divExact(pageSize(), size_class); | |
| 284 | 310 | return aligns_ptr[0..slot_count]; |
| 285 | 311 | } |
| 286 | 312 | |
| ... | ... | @@ -312,7 +338,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 312 | 338 | /// Only valid for buckets within `empty_buckets`, and relies on the `alloc_cursor` |
| 313 | 339 | /// of empty buckets being set to `slot_count` when they are added to `empty_buckets` |
| 314 | 340 | fn emptyBucketSizeClass(bucket: *BucketHeader) usize { |
| 315 | return @divExact(page_size, bucket.alloc_cursor); | |
| 341 | return @divExact(pageSize(), bucket.alloc_cursor); | |
| 316 | 342 | } |
| 317 | 343 | }; |
| 318 | 344 | |
| ... | ... | @@ -355,13 +381,13 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 355 | 381 | |
| 356 | 382 | fn bucketAlignsStart(size_class: usize) usize { |
| 357 | 383 | if (!config.safety) @compileError("requested sizes are not stored unless safety is enabled"); |
| 358 | const slot_count = @divExact(page_size, size_class); | |
| 384 | const slot_count = @divExact(pageSize(), size_class); | |
| 359 | 385 | return bucketRequestedSizesStart(size_class) + (@sizeOf(LargestSizeClassInt) * slot_count); |
| 360 | 386 | } |
| 361 | 387 | |
| 362 | 388 | fn bucketStackFramesStart(size_class: usize) usize { |
| 363 | 389 | const unaligned_start = if (config.safety) blk: { |
| 364 | const slot_count = @divExact(page_size, size_class); | |
| 390 | const slot_count = @divExact(pageSize(), size_class); | |
| 365 | 391 | break :blk bucketAlignsStart(size_class) + slot_count; |
| 366 | 392 | } else @sizeOf(BucketHeader) + usedBitsCount(size_class); |
| 367 | 393 | return mem.alignForward( |
| ... | ... | @@ -372,12 +398,12 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 372 | 398 | } |
| 373 | 399 | |
| 374 | 400 | fn bucketSize(size_class: usize) usize { |
| 375 | const slot_count = @divExact(page_size, size_class); | |
| 401 | const slot_count = @divExact(pageSize(), size_class); | |
| 376 | 402 | return bucketStackFramesStart(size_class) + one_trace_size * traces_per_slot * slot_count; |
| 377 | 403 | } |
| 378 | 404 | |
| 379 | 405 | fn usedBitsCount(size_class: usize) usize { |
| 380 | const slot_count = @divExact(page_size, size_class); | |
| 406 | const slot_count = @divExact(pageSize(), size_class); | |
| 381 | 407 | if (slot_count < 8) return 1; |
| 382 | 408 | return @divExact(slot_count, 8); |
| 383 | 409 | } |
| ... | ... | @@ -416,7 +442,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 416 | 442 | pub fn detectLeaks(self: *Self) bool { |
| 417 | 443 | var leaks = false; |
| 418 | 444 | |
| 419 | for (&self.buckets, 0..) |*buckets, bucket_i| { | |
| 445 | for (0..used_small_bucket_count()) |bucket_i| { | |
| 446 | const buckets = &self.buckets[bucket_i]; | |
| 420 | 447 | if (buckets.root == null) continue; |
| 421 | 448 | const size_class = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(bucket_i)); |
| 422 | 449 | const used_bits_count = usedBitsCount(size_class); |
| ... | ... | @@ -464,7 +491,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 464 | 491 | var bucket = node.key; |
| 465 | 492 | if (config.never_unmap) { |
| 466 | 493 | // free page that was intentionally leaked by never_unmap |
| 467 | self.backing_allocator.free(bucket.page[0..page_size]); | |
| 494 | self.backing_allocator.free(bucket.page[0..pageSize()]); | |
| 468 | 495 | } |
| 469 | 496 | // alloc_cursor was set to slot count when bucket added to empty_buckets |
| 470 | 497 | self.freeBucket(bucket, bucket.emptyBucketSizeClass()); |
| ... | ... | @@ -531,7 +558,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 531 | 558 | fn allocSlot(self: *Self, size_class: usize, trace_addr: usize) Error!Slot { |
| 532 | 559 | const bucket_index = math.log2(size_class); |
| 533 | 560 | var buckets = &self.buckets[bucket_index]; |
| 534 | const slot_count = @divExact(page_size, size_class); | |
| 561 | const slot_count = @divExact(pageSize(), size_class); | |
| 535 | 562 | if (self.cur_buckets[bucket_index] == null or self.cur_buckets[bucket_index].?.alloc_cursor == slot_count) { |
| 536 | 563 | const new_bucket = try self.createBucket(size_class); |
| 537 | 564 | errdefer self.freeBucket(new_bucket, size_class); |
| ... | ... | @@ -564,7 +591,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 564 | 591 | addr: usize, |
| 565 | 592 | current_bucket: ?*BucketHeader, |
| 566 | 593 | ) ?*BucketHeader { |
| 567 | const search_page: [*]align(page_size) u8 = @ptrFromInt(mem.alignBackward(usize, addr, page_size)); | |
| 594 | const search_page: [*]align(min_page_size) u8 = @ptrFromInt(mem.alignBackward(usize, addr, pageSize())); | |
| 568 | 595 | if (current_bucket != null and current_bucket.?.page == search_page) { |
| 569 | 596 | return current_bucket; |
| 570 | 597 | } |
| ... | ... | @@ -729,14 +756,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 729 | 756 | assert(old_mem.len != 0); |
| 730 | 757 | |
| 731 | 758 | const aligned_size = @max(old_mem.len, @as(usize, 1) << log2_old_align); |
| 732 | if (aligned_size > largest_bucket_object_size) { | |
| 759 | if (aligned_size > largest_used_bucket_object_size()) { | |
| 733 | 760 | return self.resizeLarge(old_mem, log2_old_align, new_size, ret_addr); |
| 734 | 761 | } |
| 735 | 762 | const size_class_hint = math.ceilPowerOfTwoAssert(usize, aligned_size); |
| 736 | 763 | |
| 737 | 764 | var bucket_index = math.log2(size_class_hint); |
| 738 | 765 | var size_class: usize = size_class_hint; |
| 739 | const bucket = while (bucket_index < small_bucket_count) : (bucket_index += 1) { | |
| 766 | const bucket = while (bucket_index < used_small_bucket_count()) : (bucket_index += 1) { | |
| 740 | 767 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { |
| 741 | 768 | break bucket; |
| 742 | 769 | } |
| ... | ... | @@ -847,7 +874,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 847 | 874 | assert(old_mem.len != 0); |
| 848 | 875 | |
| 849 | 876 | const aligned_size = @max(old_mem.len, @as(usize, 1) << log2_old_align); |
| 850 | if (aligned_size > largest_bucket_object_size) { | |
| 877 | if (aligned_size > largest_used_bucket_object_size()) { | |
| 851 | 878 | self.freeLarge(old_mem, log2_old_align, ret_addr); |
| 852 | 879 | return; |
| 853 | 880 | } |
| ... | ... | @@ -855,7 +882,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 855 | 882 | |
| 856 | 883 | var bucket_index = math.log2(size_class_hint); |
| 857 | 884 | var size_class: usize = size_class_hint; |
| 858 | const bucket = while (bucket_index < small_bucket_count) : (bucket_index += 1) { | |
| 885 | const bucket = while (bucket_index < used_small_bucket_count()) : (bucket_index += 1) { | |
| 859 | 886 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { |
| 860 | 887 | break bucket; |
| 861 | 888 | } |
| ... | ... | @@ -944,14 +971,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 944 | 971 | self.cur_buckets[bucket_index] = null; |
| 945 | 972 | } |
| 946 | 973 | if (!config.never_unmap) { |
| 947 | self.backing_allocator.free(bucket.page[0..page_size]); | |
| 974 | self.backing_allocator.free(bucket.page[0..pageSize()]); | |
| 948 | 975 | } |
| 949 | 976 | if (!config.retain_metadata) { |
| 950 | 977 | self.freeBucket(bucket, size_class); |
| 951 | 978 | self.bucket_node_pool.destroy(node); |
| 952 | 979 | } else { |
| 953 | 980 | // move alloc_cursor to end so we can tell size_class later |
| 954 | const slot_count = @divExact(page_size, size_class); | |
| 981 | const slot_count = @divExact(pageSize(), size_class); | |
| 955 | 982 | bucket.alloc_cursor = @as(SlotIndex, @truncate(slot_count)); |
| 956 | 983 | var empty_entry = self.empty_buckets.getEntryFor(node.key); |
| 957 | 984 | empty_entry.set(node); |
| ... | ... | @@ -992,7 +1019,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 992 | 1019 | ret_addr: usize, |
| 993 | 1020 | ) Allocator.Error![*]u8 { |
| 994 | 1021 | const new_aligned_size = @max(len, @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_ptr_align))); |
| 995 | if (new_aligned_size > largest_bucket_object_size) { | |
| 1022 | if (new_aligned_size > largest_used_bucket_object_size()) { | |
| 996 | 1023 | try self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1); |
| 997 | 1024 | const ptr = self.backing_allocator.rawAlloc(len, log2_ptr_align, ret_addr) orelse |
| 998 | 1025 | return error.OutOfMemory; |
| ... | ... | @@ -1035,7 +1062,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 1035 | 1062 | } |
| 1036 | 1063 | |
| 1037 | 1064 | fn createBucket(self: *Self, size_class: usize) Error!*BucketHeader { |
| 1038 | const page = try self.backing_allocator.alignedAlloc(u8, page_size, page_size); | |
| 1065 | const page = try self.backing_allocator.alignedAlloc(u8, min_page_size, pageSize()); | |
| 1039 | 1066 | errdefer self.backing_allocator.free(page); |
| 1040 | 1067 | |
| 1041 | 1068 | const bucket_size = bucketSize(size_class); |
| ... | ... | @@ -1179,17 +1206,17 @@ test "large object - grow" { |
| 1179 | 1206 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1180 | 1207 | const allocator = gpa.allocator(); |
| 1181 | 1208 | |
| 1182 | var slice1 = try allocator.alloc(u8, page_size * 2 - 20); | |
| 1209 | var slice1 = try allocator.alloc(u8, pageSize() * 2 - 20); | |
| 1183 | 1210 | defer allocator.free(slice1); |
| 1184 | 1211 | |
| 1185 | 1212 | const old = slice1; |
| 1186 | slice1 = try allocator.realloc(slice1, page_size * 2 - 10); | |
| 1213 | slice1 = try allocator.realloc(slice1, pageSize() * 2 - 10); | |
| 1187 | 1214 | try std.testing.expect(slice1.ptr == old.ptr); |
| 1188 | 1215 | |
| 1189 | slice1 = try allocator.realloc(slice1, page_size * 2); | |
| 1216 | slice1 = try allocator.realloc(slice1, pageSize() * 2); | |
| 1190 | 1217 | try std.testing.expect(slice1.ptr == old.ptr); |
| 1191 | 1218 | |
| 1192 | slice1 = try allocator.realloc(slice1, page_size * 2 + 1); | |
| 1219 | slice1 = try allocator.realloc(slice1, pageSize() * 2 + 1); | |
| 1193 | 1220 | } |
| 1194 | 1221 | |
| 1195 | 1222 | test "realloc small object to large object" { |
| ... | ... | @@ -1203,7 +1230,7 @@ test "realloc small object to large object" { |
| 1203 | 1230 | slice[60] = 0x34; |
| 1204 | 1231 | |
| 1205 | 1232 | // This requires upgrading to a large object |
| 1206 | const large_object_size = page_size * 2 + 50; | |
| 1233 | const large_object_size = pageSize() * 2 + 50; | |
| 1207 | 1234 | slice = try allocator.realloc(slice, large_object_size); |
| 1208 | 1235 | try std.testing.expect(slice[0] == 0x12); |
| 1209 | 1236 | try std.testing.expect(slice[60] == 0x34); |
| ... | ... | @@ -1214,22 +1241,22 @@ test "shrink large object to large object" { |
| 1214 | 1241 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1215 | 1242 | const allocator = gpa.allocator(); |
| 1216 | 1243 | |
| 1217 | var slice = try allocator.alloc(u8, page_size * 2 + 50); | |
| 1244 | var slice = try allocator.alloc(u8, pageSize() * 2 + 50); | |
| 1218 | 1245 | defer allocator.free(slice); |
| 1219 | 1246 | slice[0] = 0x12; |
| 1220 | 1247 | slice[60] = 0x34; |
| 1221 | 1248 | |
| 1222 | if (!allocator.resize(slice, page_size * 2 + 1)) return; | |
| 1223 | slice = slice.ptr[0 .. page_size * 2 + 1]; | |
| 1249 | if (!allocator.resize(slice, pageSize() * 2 + 1)) return; | |
| 1250 | slice = slice.ptr[0 .. pageSize() * 2 + 1]; | |
| 1224 | 1251 | try std.testing.expect(slice[0] == 0x12); |
| 1225 | 1252 | try std.testing.expect(slice[60] == 0x34); |
| 1226 | 1253 | |
| 1227 | try std.testing.expect(allocator.resize(slice, page_size * 2 + 1)); | |
| 1228 | slice = slice[0 .. page_size * 2 + 1]; | |
| 1254 | try std.testing.expect(allocator.resize(slice, pageSize() * 2 + 1)); | |
| 1255 | slice = slice[0 .. pageSize() * 2 + 1]; | |
| 1229 | 1256 | try std.testing.expect(slice[0] == 0x12); |
| 1230 | 1257 | try std.testing.expect(slice[60] == 0x34); |
| 1231 | 1258 | |
| 1232 | slice = try allocator.realloc(slice, page_size * 2); | |
| 1259 | slice = try allocator.realloc(slice, pageSize() * 2); | |
| 1233 | 1260 | try std.testing.expect(slice[0] == 0x12); |
| 1234 | 1261 | try std.testing.expect(slice[60] == 0x34); |
| 1235 | 1262 | } |
| ... | ... | @@ -1245,13 +1272,13 @@ test "shrink large object to large object with larger alignment" { |
| 1245 | 1272 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); |
| 1246 | 1273 | const debug_allocator = fba.allocator(); |
| 1247 | 1274 | |
| 1248 | const alloc_size = page_size * 2 + 50; | |
| 1275 | const alloc_size = pageSize() * 2 + 50; | |
| 1249 | 1276 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 1250 | 1277 | defer allocator.free(slice); |
| 1251 | 1278 | |
| 1252 | 1279 | const big_alignment: usize = switch (builtin.os.tag) { |
| 1253 | .windows => page_size * 32, // Windows aligns to 64K. | |
| 1254 | else => page_size * 2, | |
| 1280 | .windows => pageSize() * 32, // Windows aligns to 64K. | |
| 1281 | else => pageSize() * 2, | |
| 1255 | 1282 | }; |
| 1256 | 1283 | // This loop allocates until we find a page that is not aligned to the big |
| 1257 | 1284 | // alignment. Then we shrink the allocation after the loop, but increase the |
| ... | ... | @@ -1277,7 +1304,7 @@ test "realloc large object to small object" { |
| 1277 | 1304 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1278 | 1305 | const allocator = gpa.allocator(); |
| 1279 | 1306 | |
| 1280 | var slice = try allocator.alloc(u8, page_size * 2 + 50); | |
| 1307 | var slice = try allocator.alloc(u8, pageSize() * 2 + 50); | |
| 1281 | 1308 | defer allocator.free(slice); |
| 1282 | 1309 | slice[0] = 0x12; |
| 1283 | 1310 | slice[16] = 0x34; |
| ... | ... | @@ -1319,18 +1346,18 @@ test "realloc large object to larger alignment" { |
| 1319 | 1346 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); |
| 1320 | 1347 | const debug_allocator = fba.allocator(); |
| 1321 | 1348 | |
| 1322 | var slice = try allocator.alignedAlloc(u8, 16, page_size * 2 + 50); | |
| 1349 | var slice = try allocator.alignedAlloc(u8, 16, pageSize() * 2 + 50); | |
| 1323 | 1350 | defer allocator.free(slice); |
| 1324 | 1351 | |
| 1325 | 1352 | const big_alignment: usize = switch (builtin.os.tag) { |
| 1326 | .windows => page_size * 32, // Windows aligns to 64K. | |
| 1327 | else => page_size * 2, | |
| 1353 | .windows => pageSize() * 32, // Windows aligns to 64K. | |
| 1354 | else => pageSize() * 2, | |
| 1328 | 1355 | }; |
| 1329 | 1356 | // This loop allocates until we find a page that is not aligned to the big alignment. |
| 1330 | 1357 | var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator); |
| 1331 | 1358 | while (mem.isAligned(@intFromPtr(slice.ptr), big_alignment)) { |
| 1332 | 1359 | try stuff_to_free.append(slice); |
| 1333 | slice = try allocator.alignedAlloc(u8, 16, page_size * 2 + 50); | |
| 1360 | slice = try allocator.alignedAlloc(u8, 16, pageSize() * 2 + 50); | |
| 1334 | 1361 | } |
| 1335 | 1362 | while (stuff_to_free.popOrNull()) |item| { |
| 1336 | 1363 | allocator.free(item); |
| ... | ... | @@ -1338,15 +1365,15 @@ test "realloc large object to larger alignment" { |
| 1338 | 1365 | slice[0] = 0x12; |
| 1339 | 1366 | slice[16] = 0x34; |
| 1340 | 1367 | |
| 1341 | slice = try allocator.reallocAdvanced(slice, 32, page_size * 2 + 100); | |
| 1368 | slice = try allocator.reallocAdvanced(slice, 32, pageSize() * 2 + 100); | |
| 1342 | 1369 | try std.testing.expect(slice[0] == 0x12); |
| 1343 | 1370 | try std.testing.expect(slice[16] == 0x34); |
| 1344 | 1371 | |
| 1345 | slice = try allocator.reallocAdvanced(slice, 32, page_size * 2 + 25); | |
| 1372 | slice = try allocator.reallocAdvanced(slice, 32, pageSize() * 2 + 25); | |
| 1346 | 1373 | try std.testing.expect(slice[0] == 0x12); |
| 1347 | 1374 | try std.testing.expect(slice[16] == 0x34); |
| 1348 | 1375 | |
| 1349 | slice = try allocator.reallocAdvanced(slice, big_alignment, page_size * 2 + 100); | |
| 1376 | slice = try allocator.reallocAdvanced(slice, big_alignment, pageSize() * 2 + 100); | |
| 1350 | 1377 | try std.testing.expect(slice[0] == 0x12); |
| 1351 | 1378 | try std.testing.expect(slice[16] == 0x34); |
| 1352 | 1379 | } |
| ... | ... | @@ -1362,7 +1389,7 @@ test "large object shrinks to small but allocation fails during shrink" { |
| 1362 | 1389 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1363 | 1390 | const allocator = gpa.allocator(); |
| 1364 | 1391 | |
| 1365 | var slice = try allocator.alloc(u8, page_size * 2 + 50); | |
| 1392 | var slice = try allocator.alloc(u8, pageSize() * 2 + 50); | |
| 1366 | 1393 | defer allocator.free(slice); |
| 1367 | 1394 | slice[0] = 0x12; |
| 1368 | 1395 | slice[3] = 0x34; |
| ... | ... | @@ -1433,7 +1460,7 @@ test "double frees" { |
| 1433 | 1460 | try std.testing.expect(GPA.searchBucket(&gpa.empty_buckets, @intFromPtr(small.ptr), null) != null); |
| 1434 | 1461 | |
| 1435 | 1462 | // detect a large allocation double free |
| 1436 | const large = try allocator.alloc(u8, 2 * page_size); | |
| 1463 | const large = try allocator.alloc(u8, 2 * pageSize()); | |
| 1437 | 1464 | try std.testing.expect(gpa.large_allocations.contains(@intFromPtr(large.ptr))); |
| 1438 | 1465 | try std.testing.expectEqual(gpa.large_allocations.getEntry(@intFromPtr(large.ptr)).?.value_ptr.bytes, large); |
| 1439 | 1466 | allocator.free(large); |
| ... | ... | @@ -1442,7 +1469,7 @@ test "double frees" { |
| 1442 | 1469 | |
| 1443 | 1470 | const normal_small = try allocator.alloc(u8, size_class); |
| 1444 | 1471 | defer allocator.free(normal_small); |
| 1445 | const normal_large = try allocator.alloc(u8, 2 * page_size); | |
| 1472 | const normal_large = try allocator.alloc(u8, 2 * pageSize()); | |
| 1446 | 1473 | defer allocator.free(normal_large); |
| 1447 | 1474 | |
| 1448 | 1475 | // check that flushing retained metadata doesn't disturb live allocations |
| ... | ... | @@ -1475,8 +1502,8 @@ test "bug 9995 fix, large allocs count requested size not backing size" { |
| 1475 | 1502 | var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){}; |
| 1476 | 1503 | const allocator = gpa.allocator(); |
| 1477 | 1504 | |
| 1478 | var buf = try allocator.alignedAlloc(u8, 1, page_size + 1); | |
| 1479 | try std.testing.expect(gpa.total_requested_bytes == page_size + 1); | |
| 1505 | var buf = try allocator.alignedAlloc(u8, 1, pageSize() + 1); | |
| 1506 | try std.testing.expect(gpa.total_requested_bytes == pageSize() + 1); | |
| 1480 | 1507 | buf = try allocator.realloc(buf, 1); |
| 1481 | 1508 | try std.testing.expect(gpa.total_requested_bytes == 1); |
| 1482 | 1509 | buf = try allocator.realloc(buf, 2); |
lib/std/heap/sbrk_allocator.zig+4-3| ... | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const math = std.math; |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | 5 | const mem = std.mem; |
| 6 | const heap = std.heap; | |
| 6 | 7 | const assert = std.debug.assert; |
| 7 | 8 | |
| 8 | 9 | pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| ... | ... | @@ -18,7 +19,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 18 | 19 | const max_usize = math.maxInt(usize); |
| 19 | 20 | const ushift = math.Log2Int(usize); |
| 20 | 21 | const bigpage_size = 64 * 1024; |
| 21 | const pages_per_bigpage = bigpage_size / mem.page_size; | |
| 22 | const pages_per_bigpage = bigpage_size / heap.pageSize(); | |
| 22 | 23 | const bigpage_count = max_usize / bigpage_size; |
| 23 | 24 | |
| 24 | 25 | /// Because of storing free list pointers, the minimum size class is 3. |
| ... | ... | @@ -58,7 +59,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 58 | 59 | } |
| 59 | 60 | |
| 60 | 61 | const next_addr = next_addrs[class]; |
| 61 | if (next_addr % mem.page_size == 0) { | |
| 62 | if (next_addr % heap.pageSize == 0) { | |
| 62 | 63 | const addr = allocBigPages(1); |
| 63 | 64 | if (addr == 0) return null; |
| 64 | 65 | //std.debug.print("allocated fresh slot_size={d} class={d} addr=0x{x}\n", .{ |
| ... | ... | @@ -153,7 +154,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 153 | 154 | big_frees[class] = node.*; |
| 154 | 155 | return top_free_ptr; |
| 155 | 156 | } |
| 156 | return sbrk(pow2_pages * pages_per_bigpage * mem.page_size); | |
| 157 | return sbrk(pow2_pages * pages_per_bigpage * heap.pageSize()); | |
| 157 | 158 | } |
| 158 | 159 | }; |
| 159 | 160 | } |
lib/std/mem.zig+9-28| ... | ... | @@ -8,26 +8,6 @@ const testing = std.testing; |
| 8 | 8 | const Endian = std.builtin.Endian; |
| 9 | 9 | const native_endian = builtin.cpu.arch.endian(); |
| 10 | 10 | |
| 11 | /// Compile time known minimum page size. | |
| 12 | /// https://github.com/ziglang/zig/issues/4082 | |
| 13 | pub const page_size = switch (builtin.cpu.arch) { | |
| 14 | .wasm32, .wasm64 => 64 * 1024, | |
| 15 | .aarch64 => switch (builtin.os.tag) { | |
| 16 | .macos, .ios, .watchos, .tvos, .visionos => 16 * 1024, | |
| 17 | else => 4 * 1024, | |
| 18 | }, | |
| 19 | .sparc64 => 8 * 1024, | |
| 20 | .loongarch32, .loongarch64 => switch (builtin.os.tag) { | |
| 21 | // Linux default KConfig value is 16KiB | |
| 22 | .linux => 16 * 1024, | |
| 23 | // FIXME: | |
| 24 | // There is no other OS supported yet. Use the same value | |
| 25 | // as Linux for now. | |
| 26 | else => 16 * 1024, | |
| 27 | }, | |
| 28 | else => 4 * 1024, | |
| 29 | }; | |
| 30 | ||
| 31 | 11 | /// The standard library currently thoroughly depends on byte size |
| 32 | 12 | /// being 8 bits. (see the use of u8 throughout allocation code as |
| 33 | 13 | /// the "byte" type.) Code which depends on this can reference this |
| ... | ... | @@ -1072,12 +1052,13 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co |
| 1072 | 1052 | const Block = @Vector(block_len, T); |
| 1073 | 1053 | const mask: Block = @splat(sentinel); |
| 1074 | 1054 | |
| 1075 | comptime std.debug.assert(std.mem.page_size % block_size == 0); | |
| 1055 | comptime std.debug.assert(std.heap.max_page_size % @sizeOf(Block) == 0); | |
| 1056 | std.debug.assert(std.heap.pageSize() % @sizeOf(Block) == 0); | |
| 1076 | 1057 | |
| 1077 | 1058 | // First block may be unaligned |
| 1078 | 1059 | const start_addr = @intFromPtr(&p[i]); |
| 1079 | const offset_in_page = start_addr & (std.mem.page_size - 1); | |
| 1080 | if (offset_in_page <= std.mem.page_size - block_size) { | |
| 1060 | const offset_in_page = start_addr & (std.heap.pageSize() - 1); | |
| 1061 | if (offset_in_page <= std.heap.pageSize() - @sizeOf(Block)) { | |
| 1081 | 1062 | // Will not read past the end of a page, full block. |
| 1082 | 1063 | const block: Block = p[i..][0..block_len].*; |
| 1083 | 1064 | const matches = block == mask; |
| ... | ... | @@ -1125,18 +1106,18 @@ test "indexOfSentinel vector paths" { |
| 1125 | 1106 | const block_len = std.simd.suggestVectorLength(T) orelse continue; |
| 1126 | 1107 | |
| 1127 | 1108 | // Allocate three pages so we guarantee a page-crossing address with a full page after |
| 1128 | const memory = try allocator.alloc(T, 3 * std.mem.page_size / @sizeOf(T)); | |
| 1109 | const memory = try allocator.alloc(T, 3 * std.heap.pageSize() / @sizeOf(T)); | |
| 1129 | 1110 | defer allocator.free(memory); |
| 1130 | 1111 | @memset(memory, 0xaa); |
| 1131 | 1112 | |
| 1132 | 1113 | // Find starting page-alignment = 0 |
| 1133 | 1114 | var start: usize = 0; |
| 1134 | 1115 | const start_addr = @intFromPtr(&memory); |
| 1135 | start += (std.mem.alignForward(usize, start_addr, std.mem.page_size) - start_addr) / @sizeOf(T); | |
| 1136 | try testing.expect(start < std.mem.page_size / @sizeOf(T)); | |
| 1116 | start += (std.mem.alignForward(usize, start_addr, std.heap.pageSize()) - start_addr) / @sizeOf(T); | |
| 1117 | try testing.expect(start < std.heap.pageSize() / @sizeOf(T)); | |
| 1137 | 1118 | |
| 1138 | 1119 | // Validate all sub-block alignments |
| 1139 | const search_len = std.mem.page_size / @sizeOf(T); | |
| 1120 | const search_len = std.heap.pageSize() / @sizeOf(T); | |
| 1140 | 1121 | memory[start + search_len] = 0; |
| 1141 | 1122 | for (0..block_len) |offset| { |
| 1142 | 1123 | try testing.expectEqual(search_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start + offset]))); |
| ... | ... | @@ -1144,7 +1125,7 @@ test "indexOfSentinel vector paths" { |
| 1144 | 1125 | memory[start + search_len] = 0xaa; |
| 1145 | 1126 | |
| 1146 | 1127 | // Validate page boundary crossing |
| 1147 | const start_page_boundary = start + (std.mem.page_size / @sizeOf(T)); | |
| 1128 | const start_page_boundary = start + (std.heap.pageSize() / @sizeOf(T)); | |
| 1148 | 1129 | memory[start_page_boundary + block_len] = 0; |
| 1149 | 1130 | for (0..block_len) |offset| { |
| 1150 | 1131 | try testing.expectEqual(2 * block_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start_page_boundary - block_len + offset]))); |
lib/std/mem/Allocator.zig+1-1| ... | ... | @@ -218,7 +218,7 @@ fn allocBytesWithAlignment(self: Allocator, comptime alignment: u29, byte_count: |
| 218 | 218 | // The Zig Allocator interface is not intended to solve alignments beyond |
| 219 | 219 | // the minimum OS page size. For these use cases, the caller must use OS |
| 220 | 220 | // APIs directly. |
| 221 | comptime assert(alignment <= mem.page_size); | |
| 221 | if (!@inComptime() and alignment > std.heap.pageSize()) @panic("Alignment must be smaller than page size."); | |
| 222 | 222 | |
| 223 | 223 | if (byte_count == 0) { |
| 224 | 224 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); |
lib/std/os/linux/IoUring.zig+8-7| ... | ... | @@ -3,6 +3,7 @@ const std = @import("std"); |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | 5 | const mem = std.mem; |
| 6 | const heap = std.heap; | |
| 6 | 7 | const net = std.net; |
| 7 | 8 | const posix = std.posix; |
| 8 | 9 | const linux = std.os.linux; |
| ... | ... | @@ -1341,8 +1342,8 @@ pub const SubmissionQueue = struct { |
| 1341 | 1342 | dropped: *u32, |
| 1342 | 1343 | array: []u32, |
| 1343 | 1344 | sqes: []linux.io_uring_sqe, |
| 1344 | mmap: []align(mem.page_size) u8, | |
| 1345 | mmap_sqes: []align(mem.page_size) u8, | |
| 1345 | mmap: []align(heap.min_page_size) u8, | |
| 1346 | mmap_sqes: []align(heap.min_page_size) u8, | |
| 1346 | 1347 | |
| 1347 | 1348 | // We use `sqe_head` and `sqe_tail` in the same way as liburing: |
| 1348 | 1349 | // We increment `sqe_tail` (but not `tail`) for each call to `get_sqe()`. |
| ... | ... | @@ -1460,7 +1461,7 @@ pub const BufferGroup = struct { |
| 1460 | 1461 | /// Pointer to the memory shared by the kernel. |
| 1461 | 1462 | /// `buffers_count` of `io_uring_buf` structures are shared by the kernel. |
| 1462 | 1463 | /// First `io_uring_buf` is overlaid by `io_uring_buf_ring` struct. |
| 1463 | br: *align(mem.page_size) linux.io_uring_buf_ring, | |
| 1464 | br: *align(heap.min_page_size) linux.io_uring_buf_ring, | |
| 1464 | 1465 | /// Contiguous block of memory of size (buffers_count * buffer_size). |
| 1465 | 1466 | buffers: []u8, |
| 1466 | 1467 | /// Size of each buffer in buffers. |
| ... | ... | @@ -1555,7 +1556,7 @@ pub const BufferGroup = struct { |
| 1555 | 1556 | /// `fd` is IO_Uring.fd for which the provided buffer ring is being registered. |
| 1556 | 1557 | /// `entries` is the number of entries requested in the buffer ring, must be power of 2. |
| 1557 | 1558 | /// `group_id` is the chosen buffer group ID, unique in IO_Uring. |
| 1558 | pub fn setup_buf_ring(fd: posix.fd_t, entries: u16, group_id: u16) !*align(mem.page_size) linux.io_uring_buf_ring { | |
| 1559 | pub fn setup_buf_ring(fd: posix.fd_t, entries: u16, group_id: u16) !*align(heap.min_page_size) linux.io_uring_buf_ring { | |
| 1559 | 1560 | if (entries == 0 or entries > 1 << 15) return error.EntriesNotInRange; |
| 1560 | 1561 | if (!std.math.isPowerOfTwo(entries)) return error.EntriesNotPowerOfTwo; |
| 1561 | 1562 | |
| ... | ... | @@ -1571,7 +1572,7 @@ pub fn setup_buf_ring(fd: posix.fd_t, entries: u16, group_id: u16) !*align(mem.p |
| 1571 | 1572 | errdefer posix.munmap(mmap); |
| 1572 | 1573 | assert(mmap.len == mmap_size); |
| 1573 | 1574 | |
| 1574 | const br: *align(mem.page_size) linux.io_uring_buf_ring = @ptrCast(mmap.ptr); | |
| 1575 | const br: *align(heap.min_page_size) linux.io_uring_buf_ring = @ptrCast(mmap.ptr); | |
| 1575 | 1576 | try register_buf_ring(fd, @intFromPtr(br), entries, group_id); |
| 1576 | 1577 | return br; |
| 1577 | 1578 | } |
| ... | ... | @@ -1613,9 +1614,9 @@ fn handle_register_buf_ring_result(res: usize) !void { |
| 1613 | 1614 | } |
| 1614 | 1615 | |
| 1615 | 1616 | // Unregisters a previously registered shared buffer ring, returned from io_uring_setup_buf_ring. |
| 1616 | pub fn free_buf_ring(fd: posix.fd_t, br: *align(mem.page_size) linux.io_uring_buf_ring, entries: u32, group_id: u16) void { | |
| 1617 | pub fn free_buf_ring(fd: posix.fd_t, br: *align(heap.min_page_size) linux.io_uring_buf_ring, entries: u32, group_id: u16) void { | |
| 1617 | 1618 | unregister_buf_ring(fd, group_id) catch {}; |
| 1618 | var mmap: []align(mem.page_size) u8 = undefined; | |
| 1619 | var mmap: []align(heap.min_page_size) u8 = undefined; | |
| 1619 | 1620 | mmap.ptr = @ptrCast(br); |
| 1620 | 1621 | mmap.len = entries * @sizeOf(linux.io_uring_buf); |
| 1621 | 1622 | posix.munmap(mmap); |
lib/std/os/linux/tls.zig+4-3| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | |
| 12 | 12 | const std = @import("std"); |
| 13 | 13 | const mem = std.mem; |
| 14 | const heap = std.heap; | |
| 14 | 15 | const elf = std.elf; |
| 15 | 16 | const math = std.math; |
| 16 | 17 | const assert = std.debug.assert; |
| ... | ... | @@ -490,7 +491,7 @@ pub fn prepareArea(area: []u8) usize { |
| 490 | 491 | // and LLVM or LLD is not smart enough to lay out the TLS data in a space-conserving way. Anyway, I |
| 491 | 492 | // think it's fine because it's less than 3 pages of memory, and putting it in the ELF like this is |
| 492 | 493 | // equivalent to moving the `mmap` call below into the kernel, avoiding syscall overhead. |
| 493 | var main_thread_area_buffer: [0x2100]u8 align(mem.page_size) = undefined; | |
| 494 | var main_thread_area_buffer: [0x2100]u8 align(heap.min_page_size) = undefined; | |
| 494 | 495 | |
| 495 | 496 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, |
| 496 | 497 | /// and assigns the architecture-specific value to the TP register. |
| ... | ... | @@ -503,7 +504,7 @@ pub fn initStatic(phdrs: []elf.Phdr) void { |
| 503 | 504 | const area = blk: { |
| 504 | 505 | // Fast path for the common case where the TLS data is really small, avoid an allocation and |
| 505 | 506 | // use our local buffer. |
| 506 | if (area_desc.alignment <= mem.page_size and area_desc.size <= main_thread_area_buffer.len) { | |
| 507 | if (area_desc.alignment <= heap.min_page_size and area_desc.size <= main_thread_area_buffer.len) { | |
| 507 | 508 | break :blk main_thread_area_buffer[0..area_desc.size]; |
| 508 | 509 | } |
| 509 | 510 | |
| ... | ... | @@ -517,7 +518,7 @@ pub fn initStatic(phdrs: []elf.Phdr) void { |
| 517 | 518 | ); |
| 518 | 519 | if (@as(isize, @bitCast(begin_addr)) < 0) @trap(); |
| 519 | 520 | |
| 520 | const area_ptr: [*]align(mem.page_size) u8 = @ptrFromInt(begin_addr); | |
| 521 | const area_ptr: [*]align(heap.min_page_size) u8 = @ptrFromInt(begin_addr); | |
| 521 | 522 | |
| 522 | 523 | // Make sure the slice is correctly aligned. |
| 523 | 524 | const begin_aligned_addr = alignForward(begin_addr, area_desc.alignment); |
lib/std/os/plan9.zig+2-2| ... | ... | @@ -367,8 +367,8 @@ pub fn sbrk(n: usize) usize { |
| 367 | 367 | bloc = @intFromPtr(&ExecData.end); |
| 368 | 368 | bloc_max = @intFromPtr(&ExecData.end); |
| 369 | 369 | } |
| 370 | const bl = std.mem.alignForward(usize, bloc, std.mem.page_size); | |
| 371 | const n_aligned = std.mem.alignForward(usize, n, std.mem.page_size); | |
| 370 | const bl = std.mem.alignForward(usize, bloc, std.heap.pageSize()); | |
| 371 | const n_aligned = std.mem.alignForward(usize, n, std.heap.pageSize()); | |
| 372 | 372 | if (bl + n_aligned > bloc_max) { |
| 373 | 373 | // we need to allocate |
| 374 | 374 | if (brk_(bl + n_aligned) < 0) return 0; |
lib/std/os/windows/kernel32.zig+4-3| ... | ... | @@ -42,6 +42,7 @@ const WCHAR = windows.WCHAR; |
| 42 | 42 | const WIN32_FIND_DATAW = windows.WIN32_FIND_DATAW; |
| 43 | 43 | const Win32Error = windows.Win32Error; |
| 44 | 44 | const WORD = windows.WORD; |
| 45 | const SYSTEM_INFO = windows.SYSTEM_INFO; | |
| 45 | 46 | |
| 46 | 47 | // I/O - Filesystem |
| 47 | 48 | |
| ... | ... | @@ -667,6 +668,6 @@ pub extern "kernel32" fn SetLastError( |
| 667 | 668 | // TODO: |
| 668 | 669 | // Wrapper around KUSER_SHARED_DATA.SystemTime. |
| 669 | 670 | // Much better to use NtQuerySystemTime or NtQuerySystemTimePrecise for guaranteed 0.1ns precision. |
| 670 | pub extern "kernel32" fn GetSystemTimeAsFileTime( | |
| 671 | lpSystemTimeAsFileTime: *FILETIME, | |
| 672 | ) callconv(.winapi) void; | |
| 671 | pub extern "kernel32" fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *FILETIME) callconv(.winapi) void; | |
| 672 | ||
| 673 | pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(.winapi) void; |
lib/std/posix.zig+10-9| ... | ... | @@ -18,6 +18,7 @@ const builtin = @import("builtin"); |
| 18 | 18 | const root = @import("root"); |
| 19 | 19 | const std = @import("std.zig"); |
| 20 | 20 | const mem = std.mem; |
| 21 | const heap = std.heap; | |
| 21 | 22 | const fs = std.fs; |
| 22 | 23 | const max_path_bytes = fs.max_path_bytes; |
| 23 | 24 | const maxInt = std.math.maxInt; |
| ... | ... | @@ -4694,7 +4695,7 @@ pub const MProtectError = error{ |
| 4694 | 4695 | OutOfMemory, |
| 4695 | 4696 | } || UnexpectedError; |
| 4696 | 4697 | |
| 4697 | pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void { | |
| 4698 | pub fn mprotect(memory: []align(heap.min_page_size) u8, protection: u32) MProtectError!void { | |
| 4698 | 4699 | if (native_os == .windows) { |
| 4699 | 4700 | const win_prot: windows.DWORD = switch (@as(u3, @truncate(protection))) { |
| 4700 | 4701 | 0b000 => windows.PAGE_NOACCESS, |
| ... | ... | @@ -4759,21 +4760,21 @@ pub const MMapError = error{ |
| 4759 | 4760 | /// * SIGSEGV - Attempted write into a region mapped as read-only. |
| 4760 | 4761 | /// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file |
| 4761 | 4762 | pub fn mmap( |
| 4762 | ptr: ?[*]align(mem.page_size) u8, | |
| 4763 | ptr: ?[*]align(heap.min_page_size) u8, | |
| 4763 | 4764 | length: usize, |
| 4764 | 4765 | prot: u32, |
| 4765 | 4766 | flags: system.MAP, |
| 4766 | 4767 | fd: fd_t, |
| 4767 | 4768 | offset: u64, |
| 4768 | ) MMapError![]align(mem.page_size) u8 { | |
| 4769 | ) MMapError![]align(heap.min_page_size) u8 { | |
| 4769 | 4770 | const mmap_sym = if (lfs64_abi) system.mmap64 else system.mmap; |
| 4770 | 4771 | const rc = mmap_sym(ptr, length, prot, @bitCast(flags), fd, @bitCast(offset)); |
| 4771 | 4772 | const err: E = if (builtin.link_libc) blk: { |
| 4772 | if (rc != std.c.MAP_FAILED) return @as([*]align(mem.page_size) u8, @ptrCast(@alignCast(rc)))[0..length]; | |
| 4773 | if (rc != std.c.MAP_FAILED) return @as([*]align(heap.min_page_size) u8, @ptrCast(@alignCast(rc)))[0..length]; | |
| 4773 | 4774 | break :blk @enumFromInt(system._errno().*); |
| 4774 | 4775 | } else blk: { |
| 4775 | 4776 | const err = errno(rc); |
| 4776 | if (err == .SUCCESS) return @as([*]align(mem.page_size) u8, @ptrFromInt(rc))[0..length]; | |
| 4777 | if (err == .SUCCESS) return @as([*]align(heap.min_page_size) u8, @ptrFromInt(rc))[0..length]; | |
| 4777 | 4778 | break :blk err; |
| 4778 | 4779 | }; |
| 4779 | 4780 | switch (err) { |
| ... | ... | @@ -4799,7 +4800,7 @@ pub fn mmap( |
| 4799 | 4800 | /// Zig's munmap function does not, for two reasons: |
| 4800 | 4801 | /// * It violates the Zig principle that resource deallocation must succeed. |
| 4801 | 4802 | /// * The Windows function, VirtualFree, has this restriction. |
| 4802 | pub fn munmap(memory: []align(mem.page_size) const u8) void { | |
| 4803 | pub fn munmap(memory: []align(heap.min_page_size) const u8) void { | |
| 4803 | 4804 | switch (errno(system.munmap(memory.ptr, memory.len))) { |
| 4804 | 4805 | .SUCCESS => return, |
| 4805 | 4806 | .INVAL => unreachable, // Invalid parameters. |
| ... | ... | @@ -4813,7 +4814,7 @@ pub const MSyncError = error{ |
| 4813 | 4814 | PermissionDenied, |
| 4814 | 4815 | } || UnexpectedError; |
| 4815 | 4816 | |
| 4816 | pub fn msync(memory: []align(mem.page_size) u8, flags: i32) MSyncError!void { | |
| 4817 | pub fn msync(memory: []align(heap.min_page_size) u8, flags: i32) MSyncError!void { | |
| 4817 | 4818 | switch (errno(system.msync(memory.ptr, memory.len, flags))) { |
| 4818 | 4819 | .SUCCESS => return, |
| 4819 | 4820 | .PERM => return error.PermissionDenied, |
| ... | ... | @@ -7135,7 +7136,7 @@ pub const MincoreError = error{ |
| 7135 | 7136 | } || UnexpectedError; |
| 7136 | 7137 | |
| 7137 | 7138 | /// Determine whether pages are resident in memory. |
| 7138 | pub fn mincore(ptr: [*]align(mem.page_size) u8, length: usize, vec: [*]u8) MincoreError!void { | |
| 7139 | pub fn mincore(ptr: [*]align(heap.min_page_size) u8, length: usize, vec: [*]u8) MincoreError!void { | |
| 7139 | 7140 | return switch (errno(system.mincore(ptr, length, vec))) { |
| 7140 | 7141 | .SUCCESS => {}, |
| 7141 | 7142 | .AGAIN => error.SystemResources, |
| ... | ... | @@ -7181,7 +7182,7 @@ pub const MadviseError = error{ |
| 7181 | 7182 | |
| 7182 | 7183 | /// Give advice about use of memory. |
| 7183 | 7184 | /// This syscall is optional and is sometimes configured to be disabled. |
| 7184 | pub fn madvise(ptr: [*]align(mem.page_size) u8, length: usize, advice: u32) MadviseError!void { | |
| 7185 | pub fn madvise(ptr: [*]align(heap.min_page_size) u8, length: usize, advice: u32) MadviseError!void { | |
| 7185 | 7186 | switch (errno(system.madvise(ptr, length, advice))) { |
| 7186 | 7187 | .SUCCESS => return, |
| 7187 | 7188 | .PERM => return error.PermissionDenied, |
lib/std/process.zig+1-1| ... | ... | @@ -1560,7 +1560,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { |
| 1560 | 1560 | ReadGroupId, |
| 1561 | 1561 | }; |
| 1562 | 1562 | |
| 1563 | var buf: [std.mem.page_size]u8 = undefined; | |
| 1563 | var buf: [std.heap.min_page_size]u8 = undefined; | |
| 1564 | 1564 | var name_index: usize = 0; |
| 1565 | 1565 | var state = State.Start; |
| 1566 | 1566 | var uid: posix.uid_t = 0; |
lib/std/start.zig+1-1| ... | ... | @@ -576,7 +576,7 @@ fn expandStackSize(phdrs: []elf.Phdr) void { |
| 576 | 576 | switch (phdr.p_type) { |
| 577 | 577 | elf.PT_GNU_STACK => { |
| 578 | 578 | if (phdr.p_memsz == 0) break; |
| 579 | assert(phdr.p_memsz % std.mem.page_size == 0); | |
| 579 | assert(phdr.p_memsz % std.heap.pageSize() == 0); | |
| 580 | 580 | |
| 581 | 581 | // Silently fail if we are unable to get limits. |
| 582 | 582 | const limits = std.posix.getrlimit(.STACK) catch break; |
lib/std/std.zig+4| ... | ... | @@ -119,6 +119,10 @@ pub const Options = struct { |
| 119 | 119 | args: anytype, |
| 120 | 120 | ) void = log.defaultLog, |
| 121 | 121 | |
| 122 | min_page_size: ?usize = null, | |
| 123 | max_page_size: ?usize = null, | |
| 124 | queryPageSizeFn: fn () usize = heap.defaultQueryPageSize, | |
| 125 | ||
| 122 | 126 | fmt_max_depth: usize = fmt.default_max_depth, |
| 123 | 127 | |
| 124 | 128 | cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed, |
lib/std/zip.zig+1-1| ... | ... | @@ -162,7 +162,7 @@ pub fn decompress( |
| 162 | 162 | var total_uncompressed: u64 = 0; |
| 163 | 163 | switch (method) { |
| 164 | 164 | .store => { |
| 165 | var buf: [std.mem.page_size]u8 = undefined; | |
| 165 | var buf: [4096]u8 = undefined; | |
| 166 | 166 | while (true) { |
| 167 | 167 | const len = try reader.read(&buf); |
| 168 | 168 | if (len == 0) break; |
src/Package/Fetch.zig+1-1| ... | ... | @@ -1249,7 +1249,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { |
| 1249 | 1249 | .{@errorName(err)}, |
| 1250 | 1250 | )); |
| 1251 | 1251 | defer zip_file.close(); |
| 1252 | var buf: [std.mem.page_size]u8 = undefined; | |
| 1252 | var buf: [std.heap.min_page_size]u8 = undefined; | |
| 1253 | 1253 | while (true) { |
| 1254 | 1254 | const len = reader.readAll(&buf) catch |err| return f.fail(f.location_tok, try eb.printString( |
| 1255 | 1255 | "read zip stream failed: {s}", |