| 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,7 +480,7 @@ pub const MemoryMappedList = struct { |
| 480 | /// of this ArrayList in accordance with the respective documentation. In | 480 | /// of this ArrayList in accordance with the respective documentation. In |
| 481 | /// all cases, "invalidated" means that the memory has been passed to this | 481 | /// all cases, "invalidated" means that the memory has been passed to this |
| 482 | /// allocator's resize or free function. | 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 | /// How many bytes this list can hold without allocating additional memory. | 484 | /// How many bytes this list can hold without allocating additional memory. |
| 485 | capacity: usize, | 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,7 +41,7 @@ const fuzzer_arch_os_abi = "wasm32-freestanding"; |
| 41 | const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; | 41 | const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; |
| 42 | 42 | ||
| 43 | const CoverageMap = struct { | 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 | coverage: Coverage, | 45 | coverage: Coverage, |
| 46 | source_locations: []Coverage.SourceLocation, | 46 | source_locations: []Coverage.SourceLocation, |
| 47 | /// Elements are indexes into `source_locations` pointing to the unit tests that are being fuzz tested. | 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,7 +769,7 @@ const PosixThreadImpl = struct { |
| 769 | // Use the same set of parameters used by the libc-less impl. | 769 | // Use the same set of parameters used by the libc-less impl. |
| 770 | const stack_size = @max(config.stack_size, 16 * 1024); | 770 | const stack_size = @max(config.stack_size, 16 * 1024); |
| 771 | assert(c.pthread_attr_setstacksize(&attr, stack_size) == .SUCCESS); | 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 | var handle: c.pthread_t = undefined; | 774 | var handle: c.pthread_t = undefined; |
| 775 | switch (c.pthread_create( | 775 | switch (c.pthread_create( |
| ... | @@ -1155,7 +1155,7 @@ const LinuxThreadImpl = struct { | ... | @@ -1155,7 +1155,7 @@ const LinuxThreadImpl = struct { |
| 1155 | completion: Completion = Completion.init(.running), | 1155 | completion: Completion = Completion.init(.running), |
| 1156 | child_tid: std.atomic.Value(i32) = std.atomic.Value(i32).init(1), | 1156 | child_tid: std.atomic.Value(i32) = std.atomic.Value(i32).init(1), |
| 1157 | parent_tid: i32 = undefined, | 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 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). | 1160 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). |
| 1161 | /// Ported over from musl libc's pthread detached implementation: | 1161 | /// Ported over from musl libc's pthread detached implementation: |
| ... | @@ -1362,7 +1362,7 @@ const LinuxThreadImpl = struct { | ... | @@ -1362,7 +1362,7 @@ const LinuxThreadImpl = struct { |
| 1362 | }; | 1362 | }; |
| 1363 | 1363 | ||
| 1364 | fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl { | 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 | const Args = @TypeOf(args); | 1366 | const Args = @TypeOf(args); |
| 1367 | const Instance = struct { | 1367 | const Instance = struct { |
| 1368 | fn_args: Args, | 1368 | fn_args: Args, |
lib/std/c.zig+48-11| ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const c = @This(); | 3 | const c = @This(); |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | const assert = std.debug.assert; | 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 | const native_abi = builtin.abi; | 7 | const native_abi = builtin.abi; |
| 8 | const native_arch = builtin.cpu.arch; | 8 | const native_arch = builtin.cpu.arch; |
| 9 | const native_os = builtin.os.tag; | 9 | const native_os = builtin.os.tag; |
| ... | @@ -2227,6 +2227,39 @@ pub const SC = switch (native_os) { | ... | @@ -2227,6 +2227,39 @@ pub const SC = switch (native_os) { |
| 2227 | .linux => linux.SC, | 2227 | .linux => linux.SC, |
| 2228 | else => void, | 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 | pub const SEEK = switch (native_os) { | 2263 | pub const SEEK = switch (native_os) { |
| 2231 | .linux => linux.SEEK, | 2264 | .linux => linux.SEEK, |
| 2232 | .emscripten => emscripten.SEEK, | 2265 | .emscripten => emscripten.SEEK, |
| ... | @@ -9232,7 +9265,7 @@ pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd; | ... | @@ -9232,7 +9265,7 @@ pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd; |
| 9232 | pub extern "c" fn getpwuid(uid: uid_t) ?*passwd; | 9265 | pub extern "c" fn getpwuid(uid: uid_t) ?*passwd; |
| 9233 | pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int; | 9266 | pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int; |
| 9234 | pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64; | 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 | pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int; | 9269 | pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int; |
| 9237 | pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int; | 9270 | pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int; |
| 9238 | pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize; | 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,13 +9357,13 @@ pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int; |
| 9324 | 9357 | ||
| 9325 | pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int; | 9358 | pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int; |
| 9326 | pub extern "c" fn mincore( | 9359 | pub extern "c" fn mincore( |
| 9327 | addr: *align(std.mem.page_size) anyopaque, | 9360 | addr: *align(min_page_size) anyopaque, |
| 9328 | length: usize, | 9361 | length: usize, |
| 9329 | vec: [*]u8, | 9362 | vec: [*]u8, |
| 9330 | ) c_int; | 9363 | ) c_int; |
| 9331 | 9364 | ||
| 9332 | pub extern "c" fn madvise( | 9365 | pub extern "c" fn madvise( |
| 9333 | addr: *align(std.mem.page_size) anyopaque, | 9366 | addr: *align(min_page_size) anyopaque, |
| 9334 | length: usize, | 9367 | length: usize, |
| 9335 | advice: u32, | 9368 | advice: u32, |
| 9336 | ) c_int; | 9369 | ) c_int; |
| ... | @@ -9428,6 +9461,10 @@ pub const posix_memalign = switch (native_os) { | ... | @@ -9428,6 +9461,10 @@ pub const posix_memalign = switch (native_os) { |
| 9428 | .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos => private.posix_memalign, | 9461 | .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos => private.posix_memalign, |
| 9429 | else => {}, | 9462 | else => {}, |
| 9430 | }; | 9463 | }; |
| 9464 | pub const sysconf = switch (native_os) { | ||
| 9465 | .solaris => solaris.sysconf, | ||
| 9466 | else => private.sysconf, | ||
| 9467 | }; | ||
| 9431 | 9468 | ||
| 9432 | pub const sf_hdtr = switch (native_os) { | 9469 | pub const sf_hdtr = switch (native_os) { |
| 9433 | .freebsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct { | 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,9 +9506,9 @@ pub extern "c" fn writev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint) i |
| 9469 | pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: off_t) isize; | 9506 | pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: off_t) isize; |
| 9470 | pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize; | 9507 | pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize; |
| 9471 | pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize; | 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; | 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; |
| 9473 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; | 9510 | pub extern "c" fn munmap(addr: *align(min_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; | 9511 | pub extern "c" fn mprotect(addr: *align(min_page_size) anyopaque, len: usize, prot: c_uint) c_int; |
| 9475 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int; | 9512 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int; |
| 9476 | pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int; | 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 | pub extern "c" fn unlink(path: [*:0]const u8) c_int; | 9514 | pub extern "c" fn unlink(path: [*:0]const u8) c_int; |
| ... | @@ -9823,7 +9860,6 @@ pub const SCM = solaris.SCM; | ... | @@ -9823,7 +9860,6 @@ pub const SCM = solaris.SCM; |
| 9823 | pub const SETCONTEXT = solaris.SETCONTEXT; | 9860 | pub const SETCONTEXT = solaris.SETCONTEXT; |
| 9824 | pub const SETUSTACK = solaris.GETUSTACK; | 9861 | pub const SETUSTACK = solaris.GETUSTACK; |
| 9825 | pub const SFD = solaris.SFD; | 9862 | pub const SFD = solaris.SFD; |
| 9826 | pub const _SC = solaris._SC; | ||
| 9827 | pub const cmsghdr = solaris.cmsghdr; | 9863 | pub const cmsghdr = solaris.cmsghdr; |
| 9828 | pub const ctid_t = solaris.ctid_t; | 9864 | pub const ctid_t = solaris.ctid_t; |
| 9829 | pub const file_obj = solaris.file_obj; | 9865 | pub const file_obj = solaris.file_obj; |
| ... | @@ -9840,7 +9876,6 @@ pub const priority = solaris.priority; | ... | @@ -9840,7 +9876,6 @@ pub const priority = solaris.priority; |
| 9840 | pub const procfs = solaris.procfs; | 9876 | pub const procfs = solaris.procfs; |
| 9841 | pub const projid_t = solaris.projid_t; | 9877 | pub const projid_t = solaris.projid_t; |
| 9842 | pub const signalfd_siginfo = solaris.signalfd_siginfo; | 9878 | pub const signalfd_siginfo = solaris.signalfd_siginfo; |
| 9843 | pub const sysconf = solaris.sysconf; | ||
| 9844 | pub const taskid_t = solaris.taskid_t; | 9879 | pub const taskid_t = solaris.taskid_t; |
| 9845 | pub const zoneid_t = solaris.zoneid_t; | 9880 | pub const zoneid_t = solaris.zoneid_t; |
| 9846 | 9881 | ||
| ... | @@ -9997,6 +10032,7 @@ pub const host_t = darwin.host_t; | ... | @@ -9997,6 +10032,7 @@ pub const host_t = darwin.host_t; |
| 9997 | pub const ipc_space_t = darwin.ipc_space_t; | 10032 | pub const ipc_space_t = darwin.ipc_space_t; |
| 9998 | pub const ipc_space_port_t = darwin.ipc_space_port_t; | 10033 | pub const ipc_space_port_t = darwin.ipc_space_port_t; |
| 9999 | pub const kern_return_t = darwin.kern_return_t; | 10034 | pub const kern_return_t = darwin.kern_return_t; |
| 10035 | pub const vm_size_t = darwin.vm_size_t; | ||
| 10000 | pub const kevent64 = darwin.kevent64; | 10036 | pub const kevent64 = darwin.kevent64; |
| 10001 | pub const kevent64_s = darwin.kevent64_s; | 10037 | pub const kevent64_s = darwin.kevent64_s; |
| 10002 | pub const mach_absolute_time = darwin.mach_absolute_time; | 10038 | pub const mach_absolute_time = darwin.mach_absolute_time; |
| ... | @@ -10155,7 +10191,7 @@ const private = struct { | ... | @@ -10155,7 +10191,7 @@ const private = struct { |
| 10155 | }; | 10191 | }; |
| 10156 | extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; | 10192 | extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; |
| 10157 | extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 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 | extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 10195 | extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 10160 | extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int; | 10196 | extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int; |
| 10161 | extern "c" fn readdir(dir: *DIR) ?*dirent; | 10197 | extern "c" fn readdir(dir: *DIR) ?*dirent; |
| ... | @@ -10168,6 +10204,7 @@ const private = struct { | ... | @@ -10168,6 +10204,7 @@ const private = struct { |
| 10168 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; | 10204 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 10169 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; | 10205 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; |
| 10170 | extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; | 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 | extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8) c_int; | 10209 | extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8) c_int; |
| 10173 | extern "c" fn getcontext(ucp: *ucontext_t) c_int; | 10210 | extern "c" fn getcontext(ucp: *ucontext_t) c_int; |
| ... | @@ -10202,7 +10239,7 @@ const private = struct { | ... | @@ -10202,7 +10239,7 @@ const private = struct { |
| 10202 | extern "c" fn __getrusage50(who: c_int, usage: *rusage) c_int; | 10239 | extern "c" fn __getrusage50(who: c_int, usage: *rusage) c_int; |
| 10203 | extern "c" fn __gettimeofday50(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 10240 | extern "c" fn __gettimeofday50(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 10204 | extern "c" fn __libc_thr_yield() c_int; | 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 | extern "c" fn __nanosleep50(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 10243 | extern "c" fn __nanosleep50(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 10207 | extern "c" fn __sigaction14(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; | 10244 | extern "c" fn __sigaction14(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; |
| 10208 | extern "c" fn __sigfillset14(set: ?*sigset_t) void; | 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,10 +154,6 @@ pub const AF_SUN = struct { |
| 154 | pub const NOPLM = 0x00000004; | 154 | pub const NOPLM = 0x00000004; |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | pub const _SC = struct { | ||
| 158 | pub const NPROCESSORS_ONLN = 15; | ||
| 159 | }; | ||
| 160 | |||
| 161 | pub const procfs = struct { | 157 | pub const procfs = struct { |
| 162 | pub const misc_header = extern struct { | 158 | pub const misc_header = extern struct { |
| 163 | size: u32, | 159 | size: u32, |
lib/std/crypto/tlcsprng.zig+3-2| ... | @@ -6,6 +6,7 @@ | ... | @@ -6,6 +6,7 @@ |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const heap = std.heap; | ||
| 9 | const native_os = builtin.os.tag; | 10 | const native_os = builtin.os.tag; |
| 10 | const posix = std.posix; | 11 | const posix = std.posix; |
| 11 | 12 | ||
| ... | @@ -42,7 +43,7 @@ var install_atfork_handler = std.once(struct { | ... | @@ -42,7 +43,7 @@ var install_atfork_handler = std.once(struct { |
| 42 | } | 43 | } |
| 43 | }.do); | 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 | fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { | 48 | fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 48 | if (os_has_arc4random) { | 49 | if (os_has_arc4random) { |
| ... | @@ -77,7 +78,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { | ... | @@ -77,7 +78,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 77 | } else { | 78 | } else { |
| 78 | // Use a static thread-local buffer. | 79 | // Use a static thread-local buffer. |
| 79 | const S = struct { | 80 | const S = struct { |
| 80 | threadlocal var buf: Context align(mem.page_size) = .{ | 81 | threadlocal var buf: Context align(heap.min_page_size) = .{ |
| 81 | .init_state = .uninitialized, | 82 | .init_state = .uninitialized, |
| 82 | .rng = undefined, | 83 | .rng = undefined, |
| 83 | }; | 84 | }; |
lib/std/debug.zig+9-8| ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 2 | const std = @import("std.zig"); |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const heap = std.heap; | ||
| 5 | const io = std.io; | 6 | const io = std.io; |
| 6 | const posix = std.posix; | 7 | const posix = std.posix; |
| 7 | const fs = std.fs; | 8 | const fs = std.fs; |
| ... | @@ -1134,7 +1135,7 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) | ... | @@ -1134,7 +1135,7 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) |
| 1134 | defer f.close(); | 1135 | defer f.close(); |
| 1135 | // TODO fstat and make sure that the file has the correct size | 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 | var amt_read = try f.read(buf[0..]); | 1139 | var amt_read = try f.read(buf[0..]); |
| 1139 | const line_start = seek: { | 1140 | const line_start = seek: { |
| 1140 | var current_line_start: usize = 0; | 1141 | var current_line_start: usize = 0; |
| ... | @@ -1237,7 +1238,7 @@ test printLineFromFileAnyOs { | ... | @@ -1237,7 +1238,7 @@ test printLineFromFileAnyOs { |
| 1237 | 1238 | ||
| 1238 | const overlap = 10; | 1239 | const overlap = 10; |
| 1239 | var writer = file.writer(); | 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 | try writer.writeByte('\n'); | 1242 | try writer.writeByte('\n'); |
| 1242 | try writer.writeByteNTimes('a', overlap); | 1243 | try writer.writeByteNTimes('a', overlap); |
| 1243 | 1244 | ||
| ... | @@ -1252,10 +1253,10 @@ test printLineFromFileAnyOs { | ... | @@ -1252,10 +1253,10 @@ test printLineFromFileAnyOs { |
| 1252 | defer allocator.free(path); | 1253 | defer allocator.free(path); |
| 1253 | 1254 | ||
| 1254 | var writer = file.writer(); | 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 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); | 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 | output.clearRetainingCapacity(); | 1260 | output.clearRetainingCapacity(); |
| 1260 | } | 1261 | } |
| 1261 | { | 1262 | { |
| ... | @@ -1265,18 +1266,18 @@ test printLineFromFileAnyOs { | ... | @@ -1265,18 +1266,18 @@ test printLineFromFileAnyOs { |
| 1265 | defer allocator.free(path); | 1266 | defer allocator.free(path); |
| 1266 | 1267 | ||
| 1267 | var writer = file.writer(); | 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 | try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); | 1271 | try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); |
| 1271 | 1272 | ||
| 1272 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); | 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 | output.clearRetainingCapacity(); | 1275 | output.clearRetainingCapacity(); |
| 1275 | 1276 | ||
| 1276 | try writer.writeAll("a\na"); | 1277 | try writer.writeAll("a\na"); |
| 1277 | 1278 | ||
| 1278 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); | 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 | output.clearRetainingCapacity(); | 1281 | output.clearRetainingCapacity(); |
| 1281 | 1282 | ||
| 1282 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); | 1283 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); |
| ... | @@ -1290,7 +1291,7 @@ test printLineFromFileAnyOs { | ... | @@ -1290,7 +1291,7 @@ test printLineFromFileAnyOs { |
| 1290 | defer allocator.free(path); | 1291 | defer allocator.free(path); |
| 1291 | 1292 | ||
| 1292 | var writer = file.writer(); | 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 | try writer.writeByteNTimes('\n', real_file_start); | 1295 | try writer.writeByteNTimes('\n', real_file_start); |
| 1295 | try writer.writeAll("abc\ndef"); | 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,8 +2120,8 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize { |
| 2120 | pub const ElfModule = struct { | 2120 | pub const ElfModule = struct { |
| 2121 | base_address: usize, | 2121 | base_address: usize, |
| 2122 | dwarf: Dwarf, | 2122 | dwarf: Dwarf, |
| 2123 | 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.mem.page_size) const u8, | 2124 | external_mapped_memory: ?[]align(std.heap.min_page_size) const u8, |
| 2125 | 2125 | ||
| 2126 | pub fn deinit(self: *@This(), allocator: Allocator) void { | 2126 | pub fn deinit(self: *@This(), allocator: Allocator) void { |
| 2127 | self.dwarf.deinit(allocator); | 2127 | self.dwarf.deinit(allocator); |
| ... | @@ -2167,11 +2167,11 @@ pub const ElfModule = struct { | ... | @@ -2167,11 +2167,11 @@ pub const ElfModule = struct { |
| 2167 | /// sections from an external file. | 2167 | /// sections from an external file. |
| 2168 | pub fn load( | 2168 | pub fn load( |
| 2169 | gpa: Allocator, | 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 | build_id: ?[]const u8, | 2171 | build_id: ?[]const u8, |
| 2172 | expected_crc: ?u32, | 2172 | expected_crc: ?u32, |
| 2173 | parent_sections: *Dwarf.SectionArray, | 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 | elf_filename: ?[]const u8, | 2175 | elf_filename: ?[]const u8, |
| 2176 | ) LoadError!Dwarf.ElfModule { | 2176 | ) LoadError!Dwarf.ElfModule { |
| 2177 | if (expected_crc) |crc| if (crc != std.hash.crc.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo; | 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,7 +2423,7 @@ pub const ElfModule = struct { |
| 2423 | build_id: ?[]const u8, | 2423 | build_id: ?[]const u8, |
| 2424 | expected_crc: ?u32, | 2424 | expected_crc: ?u32, |
| 2425 | parent_sections: *Dwarf.SectionArray, | 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 | ) LoadError!Dwarf.ElfModule { | 2427 | ) LoadError!Dwarf.ElfModule { |
| 2428 | const elf_file = elf_file_path.root_dir.handle.openFile(elf_file_path.sub_path, .{}) catch |err| switch (err) { | 2428 | const elf_file = elf_file_path.root_dir.handle.openFile(elf_file_path.sub_path, .{}) catch |err| switch (err) { |
| 2429 | error.FileNotFound => return missing(), | 2429 | error.FileNotFound => return missing(), |
lib/std/debug/Info.zig-1| ... | @@ -10,7 +10,6 @@ const std = @import("../std.zig"); | ... | @@ -10,7 +10,6 @@ const std = @import("../std.zig"); |
| 10 | const Allocator = std.mem.Allocator; | 10 | const Allocator = std.mem.Allocator; |
| 11 | const Path = std.Build.Cache.Path; | 11 | const Path = std.Build.Cache.Path; |
| 12 | const Dwarf = std.debug.Dwarf; | 12 | const Dwarf = std.debug.Dwarf; |
| 13 | const page_size = std.mem.page_size; | ||
| 14 | const assert = std.debug.assert; | 13 | const assert = std.debug.assert; |
| 15 | const Coverage = std.debug.Coverage; | 14 | const Coverage = std.debug.Coverage; |
| 16 | const SourceLocation = std.debug.Coverage.SourceLocation; | 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 +7,7 @@ const native_os = builtin.os.tag; |
| 7 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 8 | const posix = std.posix; | 8 | const posix = std.posix; |
| 9 | const File = std.fs.File; | 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 | const MemoryAccessor = @This(); | 12 | const MemoryAccessor = @This(); |
| 13 | 13 | ||
| ... | @@ -93,9 +93,10 @@ pub fn isValidMemory(address: usize) bool { | ... | @@ -93,9 +93,10 @@ pub fn isValidMemory(address: usize) bool { |
| 93 | // We are unable to determine validity of memory for freestanding targets | 93 | // We are unable to determine validity of memory for freestanding targets |
| 94 | if (native_os == .freestanding or native_os == .other or native_os == .uefi) return true; | 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 | if (aligned_address == 0) return false; | 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 | if (native_os == .windows) { | 101 | if (native_os == .windows) { |
| 101 | const windows = std.os.windows; | 102 | const windows = std.os.windows; |
| ... | @@ -104,7 +105,7 @@ pub fn isValidMemory(address: usize) bool { | ... | @@ -104,7 +105,7 @@ pub fn isValidMemory(address: usize) bool { |
| 104 | 105 | ||
| 105 | // The only error this function can throw is ERROR_INVALID_PARAMETER. | 106 | // The only error this function can throw is ERROR_INVALID_PARAMETER. |
| 106 | // supply an address that invalid i'll be thrown. | 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 | return false; | 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,7 +504,7 @@ pub const Module = switch (native_os) { |
| 504 | .macos, .ios, .watchos, .tvos, .visionos => struct { | 504 | .macos, .ios, .watchos, .tvos, .visionos => struct { |
| 505 | base_address: usize, | 505 | base_address: usize, |
| 506 | vmaddr_slide: usize, | 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 | symbols: []const MachoSymbol, | 508 | symbols: []const MachoSymbol, |
| 509 | strings: [:0]const u8, | 509 | strings: [:0]const u8, |
| 510 | ofiles: OFileTable, | 510 | ofiles: OFileTable, |
| ... | @@ -1046,7 +1046,7 @@ pub fn readElfDebugInfo( | ... | @@ -1046,7 +1046,7 @@ pub fn readElfDebugInfo( |
| 1046 | build_id: ?[]const u8, | 1046 | build_id: ?[]const u8, |
| 1047 | expected_crc: ?u32, | 1047 | expected_crc: ?u32, |
| 1048 | parent_sections: *Dwarf.SectionArray, | 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 | ) !Dwarf.ElfModule { | 1050 | ) !Dwarf.ElfModule { |
| 1051 | nosuspend { | 1051 | nosuspend { |
| 1052 | const elf_file = (if (elf_filename) |filename| blk: { | 1052 | const elf_file = (if (elf_filename) |filename| blk: { |
| ... | @@ -1088,7 +1088,7 @@ const MachoSymbol = struct { | ... | @@ -1088,7 +1088,7 @@ const MachoSymbol = struct { |
| 1088 | 1088 | ||
| 1089 | /// Takes ownership of file, even on error. | 1089 | /// Takes ownership of file, even on error. |
| 1090 | /// TODO it's weird to take ownership even on error, rework this code. | 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 | nosuspend { | 1092 | nosuspend { |
| 1093 | defer file.close(); | 1093 | defer file.close(); |
| 1094 | 1094 |
lib/std/dynamic_library.zig+6-5| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const heap = std.heap; | ||
| 4 | const testing = std.testing; | 5 | const testing = std.testing; |
| 5 | const elf = std.elf; | 6 | const elf = std.elf; |
| 6 | const windows = std.os.windows; | 7 | const windows = std.os.windows; |
| ... | @@ -143,7 +144,7 @@ pub const ElfDynLib = struct { | ... | @@ -143,7 +144,7 @@ pub const ElfDynLib = struct { |
| 143 | hashtab: [*]posix.Elf_Symndx, | 144 | hashtab: [*]posix.Elf_Symndx, |
| 144 | versym: ?[*]elf.Versym, | 145 | versym: ?[*]elf.Versym, |
| 145 | verdef: ?*elf.Verdef, | 146 | verdef: ?*elf.Verdef, |
| 146 | memory: []align(mem.page_size) u8, | 147 | memory: []align(heap.min_page_size) u8, |
| 147 | 148 | ||
| 148 | pub const Error = ElfDynLibError; | 149 | pub const Error = ElfDynLibError; |
| 149 | 150 | ||
| ... | @@ -223,7 +224,7 @@ pub const ElfDynLib = struct { | ... | @@ -223,7 +224,7 @@ pub const ElfDynLib = struct { |
| 223 | // corresponding to the actual LOAD sections. | 224 | // corresponding to the actual LOAD sections. |
| 224 | const file_bytes = try posix.mmap( | 225 | const file_bytes = try posix.mmap( |
| 225 | null, | 226 | null, |
| 226 | mem.alignForward(usize, size, mem.page_size), | 227 | mem.alignForward(usize, size, heap.pageSize()), |
| 227 | posix.PROT.READ, | 228 | posix.PROT.READ, |
| 228 | .{ .TYPE = .PRIVATE }, | 229 | .{ .TYPE = .PRIVATE }, |
| 229 | fd, | 230 | fd, |
| ... | @@ -284,10 +285,10 @@ pub const ElfDynLib = struct { | ... | @@ -284,10 +285,10 @@ pub const ElfDynLib = struct { |
| 284 | elf.PT_LOAD => { | 285 | elf.PT_LOAD => { |
| 285 | // The VirtAddr may not be page-aligned; in such case there will be | 286 | // The VirtAddr may not be page-aligned; in such case there will be |
| 286 | // extra nonsense mapped before/after the VirtAddr,MemSiz | 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 | const extra_bytes = (base + ph.p_vaddr) - aligned_addr; | 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 extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, heap.pageSize()); |
| 290 | const ptr = @as([*]align(mem.page_size) u8, @ptrFromInt(aligned_addr)); | 291 | const ptr = @as([*]align(heap.min_page_size) u8, @ptrFromInt(aligned_addr)); |
| 291 | const prot = elfToMmapProt(ph.p_flags); | 292 | const prot = elfToMmapProt(ph.p_flags); |
| 292 | if ((ph.p_flags & elf.PF_W) == 0) { | 293 | if ((ph.p_flags & elf.PF_W) == 0) { |
| 293 | // If it does not need write access, it can be mapped from the fd. | 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,7 +91,7 @@ pub fn LinearFifo( |
| 91 | mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]); | 91 | mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]); |
| 92 | self.head = 0; | 92 | self.head = 0; |
| 93 | } else { | 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 | while (self.head != 0) { | 96 | while (self.head != 0) { |
| 97 | const n = @min(self.head, tmp.len); | 97 | const n = @min(self.head, tmp.len); |
lib/std/heap.zig+391-7| ... | @@ -8,6 +8,376 @@ const c = std.c; | ... | @@ -8,6 +8,376 @@ const c = std.c; |
| 8 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
| 9 | const windows = std.os.windows; | 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 | pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator; | 381 | pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator; |
| 12 | pub const loggingAllocator = @import("heap/logging_allocator.zig").loggingAllocator; | 382 | pub const loggingAllocator = @import("heap/logging_allocator.zig").loggingAllocator; |
| 13 | pub const ScopedLoggingAllocator = @import("heap/logging_allocator.zig").ScopedLoggingAllocator; | 383 | pub const ScopedLoggingAllocator = @import("heap/logging_allocator.zig").ScopedLoggingAllocator; |
| ... | @@ -29,7 +399,7 @@ pub const MemoryPoolExtra = memory_pool.MemoryPoolExtra; | ... | @@ -29,7 +399,7 @@ pub const MemoryPoolExtra = memory_pool.MemoryPoolExtra; |
| 29 | pub const MemoryPoolOptions = memory_pool.Options; | 399 | pub const MemoryPoolOptions = memory_pool.Options; |
| 30 | 400 | ||
| 31 | /// TODO Utilize this on Windows. | 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 | const CAllocator = struct { | 404 | const CAllocator = struct { |
| 35 | comptime { | 405 | comptime { |
| ... | @@ -256,7 +626,7 @@ pub const wasm_allocator: Allocator = .{ | ... | @@ -256,7 +626,7 @@ pub const wasm_allocator: Allocator = .{ |
| 256 | /// Verifies that the adjusted length will still map to the full length | 626 | /// Verifies that the adjusted length will still map to the full length |
| 257 | pub fn alignPageAllocLen(full_len: usize, len: usize) usize { | 627 | pub fn alignPageAllocLen(full_len: usize, len: usize) usize { |
| 258 | const aligned_len = mem.alignAllocLen(full_len, len); | 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 | return aligned_len; | 630 | return aligned_len; |
| 261 | } | 631 | } |
| 262 | 632 | ||
| ... | @@ -615,13 +985,13 @@ test "PageAllocator" { | ... | @@ -615,13 +985,13 @@ test "PageAllocator" { |
| 615 | } | 985 | } |
| 616 | 986 | ||
| 617 | if (builtin.os.tag == .windows) { | 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 | slice[0] = 0x12; | 989 | slice[0] = 0x12; |
| 620 | slice[127] = 0x34; | 990 | slice[127] = 0x34; |
| 621 | allocator.free(slice); | 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 | defer allocator.free(buf); | 995 | defer allocator.free(buf); |
| 626 | buf = try allocator.realloc(buf, 1); // shrink past the page boundary | 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,7 +1194,7 @@ pub fn testAllocatorLargeAlignment(base_allocator: mem.Allocator) !void { |
| 824 | var validationAllocator = mem.validationWrap(base_allocator); | 1194 | var validationAllocator = mem.validationWrap(base_allocator); |
| 825 | const allocator = validationAllocator.allocator(); | 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 | var align_mask: usize = undefined; | 1199 | var align_mask: usize = undefined; |
| 830 | align_mask = @shlWithOverflow(~@as(usize, 0), @as(Allocator.Log2Align, @ctz(large_align)))[0]; | 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,7 +1227,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 857 | var fib = FixedBufferAllocator.init(&debug_buffer); | 1227 | var fib = FixedBufferAllocator.init(&debug_buffer); |
| 858 | const debug_allocator = fib.allocator(); | 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 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); | 1231 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 862 | defer allocator.free(slice); | 1232 | defer allocator.free(slice); |
| 863 | 1233 | ||
| ... | @@ -866,7 +1236,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { | ... | @@ -866,7 +1236,7 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 866 | // which is 16 pages, hence the 32. This test may require to increase | 1236 | // which is 16 pages, hence the 32. This test may require to increase |
| 867 | // the size of the allocations feeding the `allocator` parameter if they | 1237 | // the size of the allocations feeding the `allocator` parameter if they |
| 868 | // fail, because of this high over-alignment we want to have. | 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 | try stuff_to_free.append(slice); | 1240 | try stuff_to_free.append(slice); |
| 871 | slice = try allocator.alignedAlloc(u8, 16, alloc_size); | 1241 | slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 872 | } | 1242 | } |
| ... | @@ -881,6 +1251,20 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { | ... | @@ -881,6 +1251,20 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 881 | try testing.expect(slice[60] == 0x34); | 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 | test { | 1268 | test { |
| 885 | _ = LoggingAllocator; | 1269 | _ = LoggingAllocator; |
| 886 | _ = LogToWriterAllocator; | 1270 | _ = LogToWriterAllocator; |
lib/std/heap/PageAllocator.zig+10-9| ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); | ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Allocator = std.mem.Allocator; | 3 | const Allocator = std.mem.Allocator; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const heap = std.heap; | ||
| 5 | const maxInt = std.math.maxInt; | 6 | const maxInt = std.math.maxInt; |
| 6 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 7 | const native_os = builtin.os.tag; | 8 | const native_os = builtin.os.tag; |
| ... | @@ -18,7 +19,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { | ... | @@ -18,7 +19,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 18 | _ = ra; | 19 | _ = ra; |
| 19 | _ = log2_align; | 20 | _ = log2_align; |
| 20 | assert(n > 0); | 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 | if (native_os == .windows) { | 24 | if (native_os == .windows) { |
| 24 | const addr = windows.VirtualAlloc( | 25 | const addr = windows.VirtualAlloc( |
| ... | @@ -34,7 +35,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { | ... | @@ -34,7 +35,7 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 34 | return @ptrCast(addr); | 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 | const hint = @atomicLoad(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, .unordered); | 39 | const hint = @atomicLoad(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, .unordered); |
| 39 | const slice = posix.mmap( | 40 | const slice = posix.mmap( |
| 40 | hint, | 41 | hint, |
| ... | @@ -44,8 +45,8 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { | ... | @@ -44,8 +45,8 @@ fn alloc(_: *anyopaque, n: usize, log2_align: u8, ra: usize) ?[*]u8 { |
| 44 | -1, | 45 | -1, |
| 45 | 0, | 46 | 0, |
| 46 | ) catch return null; | 47 | ) catch return null; |
| 47 | assert(mem.isAligned(@intFromPtr(slice.ptr), mem.page_size)); | 48 | assert(mem.isAligned(@intFromPtr(slice.ptr), heap.pageSize())); |
| 48 | const new_hint: [*]align(mem.page_size) u8 = @alignCast(slice.ptr + aligned_len); | 49 | const new_hint: [*]align(heap.min_page_size) u8 = @alignCast(slice.ptr + aligned_len); |
| 49 | _ = @cmpxchgStrong(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, hint, new_hint, .monotonic, .monotonic); | 50 | _ = @cmpxchgStrong(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, hint, new_hint, .monotonic, .monotonic); |
| 50 | return slice.ptr; | 51 | return slice.ptr; |
| 51 | } | 52 | } |
| ... | @@ -59,13 +60,13 @@ fn resize( | ... | @@ -59,13 +60,13 @@ fn resize( |
| 59 | ) bool { | 60 | ) bool { |
| 60 | _ = log2_buf_align; | 61 | _ = log2_buf_align; |
| 61 | _ = return_address; | 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 | if (native_os == .windows) { | 65 | if (native_os == .windows) { |
| 65 | if (new_size <= buf_unaligned.len) { | 66 | if (new_size <= buf_unaligned.len) { |
| 66 | const base_addr = @intFromPtr(buf_unaligned.ptr); | 67 | const base_addr = @intFromPtr(buf_unaligned.ptr); |
| 67 | const old_addr_end = base_addr + buf_unaligned.len; | 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 | if (old_addr_end > new_addr_end) { | 70 | if (old_addr_end > new_addr_end) { |
| 70 | // For shrinking that is not releasing, we will only | 71 | // For shrinking that is not releasing, we will only |
| 71 | // decommit the pages not needed anymore. | 72 | // decommit the pages not needed anymore. |
| ... | @@ -77,14 +78,14 @@ fn resize( | ... | @@ -77,14 +78,14 @@ fn resize( |
| 77 | } | 78 | } |
| 78 | return true; | 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 | if (new_size_aligned <= old_size_aligned) { | 82 | if (new_size_aligned <= old_size_aligned) { |
| 82 | return true; | 83 | return true; |
| 83 | } | 84 | } |
| 84 | return false; | 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 | if (new_size_aligned == buf_aligned_len) | 89 | if (new_size_aligned == buf_aligned_len) |
| 89 | return true; | 90 | return true; |
| 90 | 91 | ||
| ... | @@ -107,7 +108,7 @@ fn free(_: *anyopaque, slice: []u8, log2_buf_align: u8, return_address: usize) v | ... | @@ -107,7 +108,7 @@ fn free(_: *anyopaque, slice: []u8, log2_buf_align: u8, return_address: usize) v |
| 107 | if (native_os == .windows) { | 108 | if (native_os == .windows) { |
| 108 | windows.VirtualFree(slice.ptr, 0, windows.MEM_RELEASE); | 109 | windows.VirtualFree(slice.ptr, 0, windows.MEM_RELEASE); |
| 109 | } else { | 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 | posix.munmap(@alignCast(slice.ptr[0..buf_aligned_len])); | 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,7 +48,7 @@ |
| 48 | //! | 48 | //! |
| 49 | //! ## Basic Design: | 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 | //! index obj_size | 54 | //! index obj_size |
| ... | @@ -75,6 +75,9 @@ | ... | @@ -75,6 +75,9 @@ |
| 75 | //! BucketHeader, followed by "used bits", and two stack traces for each slot | 75 | //! BucketHeader, followed by "used bits", and two stack traces for each slot |
| 76 | //! (allocation trace and free trace). | 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 | //! The "used bits" are 1 bit per slot representing whether the slot is used. | 81 | //! The "used bits" are 1 bit per slot representing whether the slot is used. |
| 79 | //! Allocations use the data to iterate to find a free slot. Frees assert that the | 82 | //! Allocations use the data to iterate to find a free slot. Frees assert that the |
| 80 | //! corresponding bit is 1 and set it to 0. | 83 | //! corresponding bit is 1 and set it to 0. |
| ... | @@ -99,11 +102,13 @@ const math = std.math; | ... | @@ -99,11 +102,13 @@ const math = std.math; |
| 99 | const assert = std.debug.assert; | 102 | const assert = std.debug.assert; |
| 100 | const mem = std.mem; | 103 | const mem = std.mem; |
| 101 | const Allocator = std.mem.Allocator; | 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 | const StackTrace = std.builtin.StackTrace; | 108 | const StackTrace = std.builtin.StackTrace; |
| 104 | 109 | ||
| 105 | /// Integer type for pointing to slots in a small allocation | 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 | const default_test_stack_trace_frames: usize = if (builtin.is_test) 10 else 6; | 113 | const default_test_stack_trace_frames: usize = if (builtin.is_test) 10 else 6; |
| 109 | const default_sys_stack_trace_frames: usize = if (std.debug.sys_can_stack_trace) default_test_stack_trace_frames else 0; | 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,6 +162,9 @@ pub const Config = struct { |
| 157 | 162 | ||
| 158 | pub const Check = enum { ok, leak }; | 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 | /// Default initialization of this struct is deprecated; use `.init` instead. | 168 | /// Default initialization of this struct is deprecated; use `.init` instead. |
| 161 | pub fn GeneralPurposeAllocator(comptime config: Config) type { | 169 | pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 162 | return struct { | 170 | return struct { |
| ... | @@ -206,9 +214,27 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -206,9 +214,27 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 206 | 214 | ||
| 207 | pub const Error = mem.Allocator.Error; | 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 | const largest_bucket_object_size = 1 << (small_bucket_count - 1); | 218 | const largest_bucket_object_size = 1 << (small_bucket_count - 1); |
| 211 | const LargestSizeClassInt = std.math.IntFittingRange(0, largest_bucket_object_size); | 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 | const bucketCompare = struct { | 239 | const bucketCompare = struct { |
| 214 | fn compare(a: *BucketHeader, b: *BucketHeader) std.math.Order { | 240 | fn compare(a: *BucketHeader, b: *BucketHeader) std.math.Order { |
| ... | @@ -261,7 +287,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -261,7 +287,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 261 | // * stack_trace_addresses: [N]usize, // traces_per_slot for every allocation | 287 | // * stack_trace_addresses: [N]usize, // traces_per_slot for every allocation |
| 262 | 288 | ||
| 263 | const BucketHeader = struct { | 289 | const BucketHeader = struct { |
| 264 | page: [*]align(page_size) u8, | 290 | page: [*]align(min_page_size) u8, |
| 265 | alloc_cursor: SlotIndex, | 291 | alloc_cursor: SlotIndex, |
| 266 | used_count: SlotIndex, | 292 | used_count: SlotIndex, |
| 267 | 293 | ||
| ... | @@ -273,14 +299,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -273,14 +299,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 273 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); | 299 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); |
| 274 | const start_ptr = @as([*]u8, @ptrCast(bucket)) + bucketRequestedSizesStart(size_class); | 300 | const start_ptr = @as([*]u8, @ptrCast(bucket)) + bucketRequestedSizesStart(size_class); |
| 275 | const sizes = @as([*]LargestSizeClassInt, @ptrCast(@alignCast(start_ptr))); | 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 | return sizes[0..slot_count]; | 303 | return sizes[0..slot_count]; |
| 278 | } | 304 | } |
| 279 | 305 | ||
| 280 | fn log2PtrAligns(bucket: *BucketHeader, size_class: usize) []u8 { | 306 | fn log2PtrAligns(bucket: *BucketHeader, size_class: usize) []u8 { |
| 281 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); | 307 | if (!config.safety) @compileError("requested size is only stored when safety is enabled"); |
| 282 | const aligns_ptr = @as([*]u8, @ptrCast(bucket)) + bucketAlignsStart(size_class); | 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 | return aligns_ptr[0..slot_count]; | 310 | return aligns_ptr[0..slot_count]; |
| 285 | } | 311 | } |
| 286 | 312 | ||
| ... | @@ -312,7 +338,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -312,7 +338,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 312 | /// Only valid for buckets within `empty_buckets`, and relies on the `alloc_cursor` | 338 | /// Only valid for buckets within `empty_buckets`, and relies on the `alloc_cursor` |
| 313 | /// of empty buckets being set to `slot_count` when they are added to `empty_buckets` | 339 | /// of empty buckets being set to `slot_count` when they are added to `empty_buckets` |
| 314 | fn emptyBucketSizeClass(bucket: *BucketHeader) usize { | 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,13 +381,13 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 355 | 381 | ||
| 356 | fn bucketAlignsStart(size_class: usize) usize { | 382 | fn bucketAlignsStart(size_class: usize) usize { |
| 357 | if (!config.safety) @compileError("requested sizes are not stored unless safety is enabled"); | 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 | return bucketRequestedSizesStart(size_class) + (@sizeOf(LargestSizeClassInt) * slot_count); | 385 | return bucketRequestedSizesStart(size_class) + (@sizeOf(LargestSizeClassInt) * slot_count); |
| 360 | } | 386 | } |
| 361 | 387 | ||
| 362 | fn bucketStackFramesStart(size_class: usize) usize { | 388 | fn bucketStackFramesStart(size_class: usize) usize { |
| 363 | const unaligned_start = if (config.safety) blk: { | 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 | break :blk bucketAlignsStart(size_class) + slot_count; | 391 | break :blk bucketAlignsStart(size_class) + slot_count; |
| 366 | } else @sizeOf(BucketHeader) + usedBitsCount(size_class); | 392 | } else @sizeOf(BucketHeader) + usedBitsCount(size_class); |
| 367 | return mem.alignForward( | 393 | return mem.alignForward( |
| ... | @@ -372,12 +398,12 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -372,12 +398,12 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 372 | } | 398 | } |
| 373 | 399 | ||
| 374 | fn bucketSize(size_class: usize) usize { | 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 | return bucketStackFramesStart(size_class) + one_trace_size * traces_per_slot * slot_count; | 402 | return bucketStackFramesStart(size_class) + one_trace_size * traces_per_slot * slot_count; |
| 377 | } | 403 | } |
| 378 | 404 | ||
| 379 | fn usedBitsCount(size_class: usize) usize { | 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 | if (slot_count < 8) return 1; | 407 | if (slot_count < 8) return 1; |
| 382 | return @divExact(slot_count, 8); | 408 | return @divExact(slot_count, 8); |
| 383 | } | 409 | } |
| ... | @@ -416,7 +442,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -416,7 +442,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 416 | pub fn detectLeaks(self: *Self) bool { | 442 | pub fn detectLeaks(self: *Self) bool { |
| 417 | var leaks = false; | 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 | if (buckets.root == null) continue; | 447 | if (buckets.root == null) continue; |
| 421 | const size_class = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(bucket_i)); | 448 | const size_class = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(bucket_i)); |
| 422 | const used_bits_count = usedBitsCount(size_class); | 449 | const used_bits_count = usedBitsCount(size_class); |
| ... | @@ -464,7 +491,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -464,7 +491,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 464 | var bucket = node.key; | 491 | var bucket = node.key; |
| 465 | if (config.never_unmap) { | 492 | if (config.never_unmap) { |
| 466 | // free page that was intentionally leaked by never_unmap | 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 | // alloc_cursor was set to slot count when bucket added to empty_buckets | 496 | // alloc_cursor was set to slot count when bucket added to empty_buckets |
| 470 | self.freeBucket(bucket, bucket.emptyBucketSizeClass()); | 497 | self.freeBucket(bucket, bucket.emptyBucketSizeClass()); |
| ... | @@ -531,7 +558,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -531,7 +558,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 531 | fn allocSlot(self: *Self, size_class: usize, trace_addr: usize) Error!Slot { | 558 | fn allocSlot(self: *Self, size_class: usize, trace_addr: usize) Error!Slot { |
| 532 | const bucket_index = math.log2(size_class); | 559 | const bucket_index = math.log2(size_class); |
| 533 | var buckets = &self.buckets[bucket_index]; | 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 | if (self.cur_buckets[bucket_index] == null or self.cur_buckets[bucket_index].?.alloc_cursor == slot_count) { | 562 | if (self.cur_buckets[bucket_index] == null or self.cur_buckets[bucket_index].?.alloc_cursor == slot_count) { |
| 536 | const new_bucket = try self.createBucket(size_class); | 563 | const new_bucket = try self.createBucket(size_class); |
| 537 | errdefer self.freeBucket(new_bucket, size_class); | 564 | errdefer self.freeBucket(new_bucket, size_class); |
| ... | @@ -564,7 +591,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -564,7 +591,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 564 | addr: usize, | 591 | addr: usize, |
| 565 | current_bucket: ?*BucketHeader, | 592 | current_bucket: ?*BucketHeader, |
| 566 | ) ?*BucketHeader { | 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 | if (current_bucket != null and current_bucket.?.page == search_page) { | 595 | if (current_bucket != null and current_bucket.?.page == search_page) { |
| 569 | return current_bucket; | 596 | return current_bucket; |
| 570 | } | 597 | } |
| ... | @@ -729,14 +756,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -729,14 +756,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 729 | assert(old_mem.len != 0); | 756 | assert(old_mem.len != 0); |
| 730 | 757 | ||
| 731 | const aligned_size = @max(old_mem.len, @as(usize, 1) << log2_old_align); | 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 | return self.resizeLarge(old_mem, log2_old_align, new_size, ret_addr); | 760 | return self.resizeLarge(old_mem, log2_old_align, new_size, ret_addr); |
| 734 | } | 761 | } |
| 735 | const size_class_hint = math.ceilPowerOfTwoAssert(usize, aligned_size); | 762 | const size_class_hint = math.ceilPowerOfTwoAssert(usize, aligned_size); |
| 736 | 763 | ||
| 737 | var bucket_index = math.log2(size_class_hint); | 764 | var bucket_index = math.log2(size_class_hint); |
| 738 | var size_class: usize = size_class_hint; | 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 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { | 767 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { |
| 741 | break bucket; | 768 | break bucket; |
| 742 | } | 769 | } |
| ... | @@ -847,7 +874,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -847,7 +874,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 847 | assert(old_mem.len != 0); | 874 | assert(old_mem.len != 0); |
| 848 | 875 | ||
| 849 | const aligned_size = @max(old_mem.len, @as(usize, 1) << log2_old_align); | 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 | self.freeLarge(old_mem, log2_old_align, ret_addr); | 878 | self.freeLarge(old_mem, log2_old_align, ret_addr); |
| 852 | return; | 879 | return; |
| 853 | } | 880 | } |
| ... | @@ -855,7 +882,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -855,7 +882,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 855 | 882 | ||
| 856 | var bucket_index = math.log2(size_class_hint); | 883 | var bucket_index = math.log2(size_class_hint); |
| 857 | var size_class: usize = size_class_hint; | 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 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { | 886 | if (searchBucket(&self.buckets[bucket_index], @intFromPtr(old_mem.ptr), self.cur_buckets[bucket_index])) |bucket| { |
| 860 | break bucket; | 887 | break bucket; |
| 861 | } | 888 | } |
| ... | @@ -944,14 +971,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -944,14 +971,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 944 | self.cur_buckets[bucket_index] = null; | 971 | self.cur_buckets[bucket_index] = null; |
| 945 | } | 972 | } |
| 946 | if (!config.never_unmap) { | 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 | if (!config.retain_metadata) { | 976 | if (!config.retain_metadata) { |
| 950 | self.freeBucket(bucket, size_class); | 977 | self.freeBucket(bucket, size_class); |
| 951 | self.bucket_node_pool.destroy(node); | 978 | self.bucket_node_pool.destroy(node); |
| 952 | } else { | 979 | } else { |
| 953 | // move alloc_cursor to end so we can tell size_class later | 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 | bucket.alloc_cursor = @as(SlotIndex, @truncate(slot_count)); | 982 | bucket.alloc_cursor = @as(SlotIndex, @truncate(slot_count)); |
| 956 | var empty_entry = self.empty_buckets.getEntryFor(node.key); | 983 | var empty_entry = self.empty_buckets.getEntryFor(node.key); |
| 957 | empty_entry.set(node); | 984 | empty_entry.set(node); |
| ... | @@ -992,7 +1019,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -992,7 +1019,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 992 | ret_addr: usize, | 1019 | ret_addr: usize, |
| 993 | ) Allocator.Error![*]u8 { | 1020 | ) Allocator.Error![*]u8 { |
| 994 | const new_aligned_size = @max(len, @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_ptr_align))); | 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 | try self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1); | 1023 | try self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1); |
| 997 | const ptr = self.backing_allocator.rawAlloc(len, log2_ptr_align, ret_addr) orelse | 1024 | const ptr = self.backing_allocator.rawAlloc(len, log2_ptr_align, ret_addr) orelse |
| 998 | return error.OutOfMemory; | 1025 | return error.OutOfMemory; |
| ... | @@ -1035,7 +1062,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -1035,7 +1062,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 1035 | } | 1062 | } |
| 1036 | 1063 | ||
| 1037 | fn createBucket(self: *Self, size_class: usize) Error!*BucketHeader { | 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 | errdefer self.backing_allocator.free(page); | 1066 | errdefer self.backing_allocator.free(page); |
| 1040 | 1067 | ||
| 1041 | const bucket_size = bucketSize(size_class); | 1068 | const bucket_size = bucketSize(size_class); |
| ... | @@ -1179,17 +1206,17 @@ test "large object - grow" { | ... | @@ -1179,17 +1206,17 @@ test "large object - grow" { |
| 1179 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); | 1206 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1180 | const allocator = gpa.allocator(); | 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 | defer allocator.free(slice1); | 1210 | defer allocator.free(slice1); |
| 1184 | 1211 | ||
| 1185 | const old = slice1; | 1212 | const old = slice1; |
| 1186 | slice1 = try allocator.realloc(slice1, page_size * 2 - 10); | 1213 | slice1 = try allocator.realloc(slice1, pageSize() * 2 - 10); |
| 1187 | try std.testing.expect(slice1.ptr == old.ptr); | 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 | try std.testing.expect(slice1.ptr == old.ptr); | 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 | test "realloc small object to large object" { | 1222 | test "realloc small object to large object" { |
| ... | @@ -1203,7 +1230,7 @@ test "realloc small object to large object" { | ... | @@ -1203,7 +1230,7 @@ test "realloc small object to large object" { |
| 1203 | slice[60] = 0x34; | 1230 | slice[60] = 0x34; |
| 1204 | 1231 | ||
| 1205 | // This requires upgrading to a large object | 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 | slice = try allocator.realloc(slice, large_object_size); | 1234 | slice = try allocator.realloc(slice, large_object_size); |
| 1208 | try std.testing.expect(slice[0] == 0x12); | 1235 | try std.testing.expect(slice[0] == 0x12); |
| 1209 | try std.testing.expect(slice[60] == 0x34); | 1236 | try std.testing.expect(slice[60] == 0x34); |
| ... | @@ -1214,22 +1241,22 @@ test "shrink large object to large object" { | ... | @@ -1214,22 +1241,22 @@ test "shrink large object to large object" { |
| 1214 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); | 1241 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1215 | const allocator = gpa.allocator(); | 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 | defer allocator.free(slice); | 1245 | defer allocator.free(slice); |
| 1219 | slice[0] = 0x12; | 1246 | slice[0] = 0x12; |
| 1220 | slice[60] = 0x34; | 1247 | slice[60] = 0x34; |
| 1221 | 1248 | ||
| 1222 | if (!allocator.resize(slice, page_size * 2 + 1)) return; | 1249 | if (!allocator.resize(slice, pageSize() * 2 + 1)) return; |
| 1223 | slice = slice.ptr[0 .. page_size * 2 + 1]; | 1250 | slice = slice.ptr[0 .. pageSize() * 2 + 1]; |
| 1224 | try std.testing.expect(slice[0] == 0x12); | 1251 | try std.testing.expect(slice[0] == 0x12); |
| 1225 | try std.testing.expect(slice[60] == 0x34); | 1252 | try std.testing.expect(slice[60] == 0x34); |
| 1226 | 1253 | ||
| 1227 | try std.testing.expect(allocator.resize(slice, page_size * 2 + 1)); | 1254 | try std.testing.expect(allocator.resize(slice, pageSize() * 2 + 1)); |
| 1228 | slice = slice[0 .. page_size * 2 + 1]; | 1255 | slice = slice[0 .. pageSize() * 2 + 1]; |
| 1229 | try std.testing.expect(slice[0] == 0x12); | 1256 | try std.testing.expect(slice[0] == 0x12); |
| 1230 | try std.testing.expect(slice[60] == 0x34); | 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 | try std.testing.expect(slice[0] == 0x12); | 1260 | try std.testing.expect(slice[0] == 0x12); |
| 1234 | try std.testing.expect(slice[60] == 0x34); | 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,13 +1272,13 @@ test "shrink large object to large object with larger alignment" { |
| 1245 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); | 1272 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); |
| 1246 | const debug_allocator = fba.allocator(); | 1273 | const debug_allocator = fba.allocator(); |
| 1247 | 1274 | ||
| 1248 | const alloc_size = page_size * 2 + 50; | 1275 | const alloc_size = pageSize() * 2 + 50; |
| 1249 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); | 1276 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
| 1250 | defer allocator.free(slice); | 1277 | defer allocator.free(slice); |
| 1251 | 1278 | ||
| 1252 | const big_alignment: usize = switch (builtin.os.tag) { | 1279 | const big_alignment: usize = switch (builtin.os.tag) { |
| 1253 | .windows => page_size * 32, // Windows aligns to 64K. | 1280 | .windows => pageSize() * 32, // Windows aligns to 64K. |
| 1254 | else => page_size * 2, | 1281 | else => pageSize() * 2, |
| 1255 | }; | 1282 | }; |
| 1256 | // This loop allocates until we find a page that is not aligned to the big | 1283 | // This loop allocates until we find a page that is not aligned to the big |
| 1257 | // alignment. Then we shrink the allocation after the loop, but increase the | 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,7 +1304,7 @@ test "realloc large object to small object" { |
| 1277 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); | 1304 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1278 | const allocator = gpa.allocator(); | 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 | defer allocator.free(slice); | 1308 | defer allocator.free(slice); |
| 1282 | slice[0] = 0x12; | 1309 | slice[0] = 0x12; |
| 1283 | slice[16] = 0x34; | 1310 | slice[16] = 0x34; |
| ... | @@ -1319,18 +1346,18 @@ test "realloc large object to larger alignment" { | ... | @@ -1319,18 +1346,18 @@ test "realloc large object to larger alignment" { |
| 1319 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); | 1346 | var fba = std.heap.FixedBufferAllocator.init(&debug_buffer); |
| 1320 | const debug_allocator = fba.allocator(); | 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 | defer allocator.free(slice); | 1350 | defer allocator.free(slice); |
| 1324 | 1351 | ||
| 1325 | const big_alignment: usize = switch (builtin.os.tag) { | 1352 | const big_alignment: usize = switch (builtin.os.tag) { |
| 1326 | .windows => page_size * 32, // Windows aligns to 64K. | 1353 | .windows => pageSize() * 32, // Windows aligns to 64K. |
| 1327 | else => page_size * 2, | 1354 | else => pageSize() * 2, |
| 1328 | }; | 1355 | }; |
| 1329 | // This loop allocates until we find a page that is not aligned to the big alignment. | 1356 | // This loop allocates until we find a page that is not aligned to the big alignment. |
| 1330 | var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator); | 1357 | var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator); |
| 1331 | while (mem.isAligned(@intFromPtr(slice.ptr), big_alignment)) { | 1358 | while (mem.isAligned(@intFromPtr(slice.ptr), big_alignment)) { |
| 1332 | try stuff_to_free.append(slice); | 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 | while (stuff_to_free.popOrNull()) |item| { | 1362 | while (stuff_to_free.popOrNull()) |item| { |
| 1336 | allocator.free(item); | 1363 | allocator.free(item); |
| ... | @@ -1338,15 +1365,15 @@ test "realloc large object to larger alignment" { | ... | @@ -1338,15 +1365,15 @@ test "realloc large object to larger alignment" { |
| 1338 | slice[0] = 0x12; | 1365 | slice[0] = 0x12; |
| 1339 | slice[16] = 0x34; | 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 | try std.testing.expect(slice[0] == 0x12); | 1369 | try std.testing.expect(slice[0] == 0x12); |
| 1343 | try std.testing.expect(slice[16] == 0x34); | 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 | try std.testing.expect(slice[0] == 0x12); | 1373 | try std.testing.expect(slice[0] == 0x12); |
| 1347 | try std.testing.expect(slice[16] == 0x34); | 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 | try std.testing.expect(slice[0] == 0x12); | 1377 | try std.testing.expect(slice[0] == 0x12); |
| 1351 | try std.testing.expect(slice[16] == 0x34); | 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,7 +1389,7 @@ test "large object shrinks to small but allocation fails during shrink" { |
| 1362 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); | 1389 | defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); |
| 1363 | const allocator = gpa.allocator(); | 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 | defer allocator.free(slice); | 1393 | defer allocator.free(slice); |
| 1367 | slice[0] = 0x12; | 1394 | slice[0] = 0x12; |
| 1368 | slice[3] = 0x34; | 1395 | slice[3] = 0x34; |
| ... | @@ -1433,7 +1460,7 @@ test "double frees" { | ... | @@ -1433,7 +1460,7 @@ test "double frees" { |
| 1433 | try std.testing.expect(GPA.searchBucket(&gpa.empty_buckets, @intFromPtr(small.ptr), null) != null); | 1460 | try std.testing.expect(GPA.searchBucket(&gpa.empty_buckets, @intFromPtr(small.ptr), null) != null); |
| 1434 | 1461 | ||
| 1435 | // detect a large allocation double free | 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 | try std.testing.expect(gpa.large_allocations.contains(@intFromPtr(large.ptr))); | 1464 | try std.testing.expect(gpa.large_allocations.contains(@intFromPtr(large.ptr))); |
| 1438 | try std.testing.expectEqual(gpa.large_allocations.getEntry(@intFromPtr(large.ptr)).?.value_ptr.bytes, large); | 1465 | try std.testing.expectEqual(gpa.large_allocations.getEntry(@intFromPtr(large.ptr)).?.value_ptr.bytes, large); |
| 1439 | allocator.free(large); | 1466 | allocator.free(large); |
| ... | @@ -1442,7 +1469,7 @@ test "double frees" { | ... | @@ -1442,7 +1469,7 @@ test "double frees" { |
| 1442 | 1469 | ||
| 1443 | const normal_small = try allocator.alloc(u8, size_class); | 1470 | const normal_small = try allocator.alloc(u8, size_class); |
| 1444 | defer allocator.free(normal_small); | 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 | defer allocator.free(normal_large); | 1473 | defer allocator.free(normal_large); |
| 1447 | 1474 | ||
| 1448 | // check that flushing retained metadata doesn't disturb live allocations | 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,8 +1502,8 @@ test "bug 9995 fix, large allocs count requested size not backing size" { |
| 1475 | var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){}; | 1502 | var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){}; |
| 1476 | const allocator = gpa.allocator(); | 1503 | const allocator = gpa.allocator(); |
| 1477 | 1504 | ||
| 1478 | var buf = try allocator.alignedAlloc(u8, 1, page_size + 1); | 1505 | var buf = try allocator.alignedAlloc(u8, 1, pageSize() + 1); |
| 1479 | try std.testing.expect(gpa.total_requested_bytes == page_size + 1); | 1506 | try std.testing.expect(gpa.total_requested_bytes == pageSize() + 1); |
| 1480 | buf = try allocator.realloc(buf, 1); | 1507 | buf = try allocator.realloc(buf, 1); |
| 1481 | try std.testing.expect(gpa.total_requested_bytes == 1); | 1508 | try std.testing.expect(gpa.total_requested_bytes == 1); |
| 1482 | buf = try allocator.realloc(buf, 2); | 1509 | buf = try allocator.realloc(buf, 2); |
lib/std/heap/sbrk_allocator.zig+4-3| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const heap = std.heap; | ||
| 6 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 7 | 8 | ||
| 8 | pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { | 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,7 +19,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 18 | const max_usize = math.maxInt(usize); | 19 | const max_usize = math.maxInt(usize); |
| 19 | const ushift = math.Log2Int(usize); | 20 | const ushift = math.Log2Int(usize); |
| 20 | const bigpage_size = 64 * 1024; | 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 | const bigpage_count = max_usize / bigpage_size; | 23 | const bigpage_count = max_usize / bigpage_size; |
| 23 | 24 | ||
| 24 | /// Because of storing free list pointers, the minimum size class is 3. | 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,7 +59,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | const next_addr = next_addrs[class]; | 61 | const next_addr = next_addrs[class]; |
| 61 | if (next_addr % mem.page_size == 0) { | 62 | if (next_addr % heap.pageSize == 0) { |
| 62 | const addr = allocBigPages(1); | 63 | const addr = allocBigPages(1); |
| 63 | if (addr == 0) return null; | 64 | if (addr == 0) return null; |
| 64 | //std.debug.print("allocated fresh slot_size={d} class={d} addr=0x{x}\n", .{ | 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,7 +154,7 @@ pub fn SbrkAllocator(comptime sbrk: *const fn (n: usize) usize) type { |
| 153 | big_frees[class] = node.*; | 154 | big_frees[class] = node.*; |
| 154 | return top_free_ptr; | 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,26 +8,6 @@ const testing = std.testing; |
| 8 | const Endian = std.builtin.Endian; | 8 | const Endian = std.builtin.Endian; |
| 9 | const native_endian = builtin.cpu.arch.endian(); | 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 | /// The standard library currently thoroughly depends on byte size | 11 | /// The standard library currently thoroughly depends on byte size |
| 32 | /// being 8 bits. (see the use of u8 throughout allocation code as | 12 | /// being 8 bits. (see the use of u8 throughout allocation code as |
| 33 | /// the "byte" type.) Code which depends on this can reference this | 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,12 +1052,13 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co |
| 1072 | const Block = @Vector(block_len, T); | 1052 | const Block = @Vector(block_len, T); |
| 1073 | const mask: Block = @splat(sentinel); | 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 | // First block may be unaligned | 1058 | // First block may be unaligned |
| 1078 | const start_addr = @intFromPtr(&p[i]); | 1059 | const start_addr = @intFromPtr(&p[i]); |
| 1079 | const offset_in_page = start_addr & (std.mem.page_size - 1); | 1060 | const offset_in_page = start_addr & (std.heap.pageSize() - 1); |
| 1080 | if (offset_in_page <= std.mem.page_size - block_size) { | 1061 | if (offset_in_page <= std.heap.pageSize() - @sizeOf(Block)) { |
| 1081 | // Will not read past the end of a page, full block. | 1062 | // Will not read past the end of a page, full block. |
| 1082 | const block: Block = p[i..][0..block_len].*; | 1063 | const block: Block = p[i..][0..block_len].*; |
| 1083 | const matches = block == mask; | 1064 | const matches = block == mask; |
| ... | @@ -1125,18 +1106,18 @@ test "indexOfSentinel vector paths" { | ... | @@ -1125,18 +1106,18 @@ test "indexOfSentinel vector paths" { |
| 1125 | const block_len = std.simd.suggestVectorLength(T) orelse continue; | 1106 | const block_len = std.simd.suggestVectorLength(T) orelse continue; |
| 1126 | 1107 | ||
| 1127 | // Allocate three pages so we guarantee a page-crossing address with a full page after | 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 | defer allocator.free(memory); | 1110 | defer allocator.free(memory); |
| 1130 | @memset(memory, 0xaa); | 1111 | @memset(memory, 0xaa); |
| 1131 | 1112 | ||
| 1132 | // Find starting page-alignment = 0 | 1113 | // Find starting page-alignment = 0 |
| 1133 | var start: usize = 0; | 1114 | var start: usize = 0; |
| 1134 | const start_addr = @intFromPtr(&memory); | 1115 | const start_addr = @intFromPtr(&memory); |
| 1135 | start += (std.mem.alignForward(usize, start_addr, std.mem.page_size) - start_addr) / @sizeOf(T); | 1116 | start += (std.mem.alignForward(usize, start_addr, std.heap.pageSize()) - start_addr) / @sizeOf(T); |
| 1136 | try testing.expect(start < std.mem.page_size / @sizeOf(T)); | 1117 | try testing.expect(start < std.heap.pageSize() / @sizeOf(T)); |
| 1137 | 1118 | ||
| 1138 | // Validate all sub-block alignments | 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 | memory[start + search_len] = 0; | 1121 | memory[start + search_len] = 0; |
| 1141 | for (0..block_len) |offset| { | 1122 | for (0..block_len) |offset| { |
| 1142 | try testing.expectEqual(search_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start + offset]))); | 1123 | try testing.expectEqual(search_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start + offset]))); |
| ... | @@ -1144,7 +1125,7 @@ test "indexOfSentinel vector paths" { | ... | @@ -1144,7 +1125,7 @@ test "indexOfSentinel vector paths" { |
| 1144 | memory[start + search_len] = 0xaa; | 1125 | memory[start + search_len] = 0xaa; |
| 1145 | 1126 | ||
| 1146 | // Validate page boundary crossing | 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 | memory[start_page_boundary + block_len] = 0; | 1129 | memory[start_page_boundary + block_len] = 0; |
| 1149 | for (0..block_len) |offset| { | 1130 | for (0..block_len) |offset| { |
| 1150 | try testing.expectEqual(2 * block_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start_page_boundary - block_len + offset]))); | 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,7 +218,7 @@ fn allocBytesWithAlignment(self: Allocator, comptime alignment: u29, byte_count: |
| 218 | // The Zig Allocator interface is not intended to solve alignments beyond | 218 | // The Zig Allocator interface is not intended to solve alignments beyond |
| 219 | // the minimum OS page size. For these use cases, the caller must use OS | 219 | // the minimum OS page size. For these use cases, the caller must use OS |
| 220 | // APIs directly. | 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 | if (byte_count == 0) { | 223 | if (byte_count == 0) { |
| 224 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); | 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,6 +3,7 @@ const std = @import("std"); |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const heap = std.heap; | ||
| 6 | const net = std.net; | 7 | const net = std.net; |
| 7 | const posix = std.posix; | 8 | const posix = std.posix; |
| 8 | const linux = std.os.linux; | 9 | const linux = std.os.linux; |
| ... | @@ -1341,8 +1342,8 @@ pub const SubmissionQueue = struct { | ... | @@ -1341,8 +1342,8 @@ pub const SubmissionQueue = struct { |
| 1341 | dropped: *u32, | 1342 | dropped: *u32, |
| 1342 | array: []u32, | 1343 | array: []u32, |
| 1343 | sqes: []linux.io_uring_sqe, | 1344 | sqes: []linux.io_uring_sqe, |
| 1344 | mmap: []align(mem.page_size) u8, | 1345 | mmap: []align(heap.min_page_size) u8, |
| 1345 | mmap_sqes: []align(mem.page_size) u8, | 1346 | mmap_sqes: []align(heap.min_page_size) u8, |
| 1346 | 1347 | ||
| 1347 | // We use `sqe_head` and `sqe_tail` in the same way as liburing: | 1348 | // We use `sqe_head` and `sqe_tail` in the same way as liburing: |
| 1348 | // We increment `sqe_tail` (but not `tail`) for each call to `get_sqe()`. | 1349 | // We increment `sqe_tail` (but not `tail`) for each call to `get_sqe()`. |
| ... | @@ -1460,7 +1461,7 @@ pub const BufferGroup = struct { | ... | @@ -1460,7 +1461,7 @@ pub const BufferGroup = struct { |
| 1460 | /// Pointer to the memory shared by the kernel. | 1461 | /// Pointer to the memory shared by the kernel. |
| 1461 | /// `buffers_count` of `io_uring_buf` structures are shared by the kernel. | 1462 | /// `buffers_count` of `io_uring_buf` structures are shared by the kernel. |
| 1462 | /// First `io_uring_buf` is overlaid by `io_uring_buf_ring` struct. | 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 | /// Contiguous block of memory of size (buffers_count * buffer_size). | 1465 | /// Contiguous block of memory of size (buffers_count * buffer_size). |
| 1465 | buffers: []u8, | 1466 | buffers: []u8, |
| 1466 | /// Size of each buffer in buffers. | 1467 | /// Size of each buffer in buffers. |
| ... | @@ -1555,7 +1556,7 @@ pub const BufferGroup = struct { | ... | @@ -1555,7 +1556,7 @@ pub const BufferGroup = struct { |
| 1555 | /// `fd` is IO_Uring.fd for which the provided buffer ring is being registered. | 1556 | /// `fd` is IO_Uring.fd for which the provided buffer ring is being registered. |
| 1556 | /// `entries` is the number of entries requested in the buffer ring, must be power of 2. | 1557 | /// `entries` is the number of entries requested in the buffer ring, must be power of 2. |
| 1557 | /// `group_id` is the chosen buffer group ID, unique in IO_Uring. | 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 | if (entries == 0 or entries > 1 << 15) return error.EntriesNotInRange; | 1560 | if (entries == 0 or entries > 1 << 15) return error.EntriesNotInRange; |
| 1560 | if (!std.math.isPowerOfTwo(entries)) return error.EntriesNotPowerOfTwo; | 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,7 +1572,7 @@ pub fn setup_buf_ring(fd: posix.fd_t, entries: u16, group_id: u16) !*align(mem.p |
| 1571 | errdefer posix.munmap(mmap); | 1572 | errdefer posix.munmap(mmap); |
| 1572 | assert(mmap.len == mmap_size); | 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 | try register_buf_ring(fd, @intFromPtr(br), entries, group_id); | 1576 | try register_buf_ring(fd, @intFromPtr(br), entries, group_id); |
| 1576 | return br; | 1577 | return br; |
| 1577 | } | 1578 | } |
| ... | @@ -1613,9 +1614,9 @@ fn handle_register_buf_ring_result(res: usize) !void { | ... | @@ -1613,9 +1614,9 @@ fn handle_register_buf_ring_result(res: usize) !void { |
| 1613 | } | 1614 | } |
| 1614 | 1615 | ||
| 1615 | // Unregisters a previously registered shared buffer ring, returned from io_uring_setup_buf_ring. | 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 | unregister_buf_ring(fd, group_id) catch {}; | 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 | mmap.ptr = @ptrCast(br); | 1620 | mmap.ptr = @ptrCast(br); |
| 1620 | mmap.len = entries * @sizeOf(linux.io_uring_buf); | 1621 | mmap.len = entries * @sizeOf(linux.io_uring_buf); |
| 1621 | posix.munmap(mmap); | 1622 | posix.munmap(mmap); |
lib/std/os/linux/tls.zig+4-3| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | ||
| 12 | const std = @import("std"); | 12 | const std = @import("std"); |
| 13 | const mem = std.mem; | 13 | const mem = std.mem; |
| 14 | const heap = std.heap; | ||
| 14 | const elf = std.elf; | 15 | const elf = std.elf; |
| 15 | const math = std.math; | 16 | const math = std.math; |
| 16 | const assert = std.debug.assert; | 17 | const assert = std.debug.assert; |
| ... | @@ -490,7 +491,7 @@ pub fn prepareArea(area: []u8) usize { | ... | @@ -490,7 +491,7 @@ pub fn prepareArea(area: []u8) usize { |
| 490 | // and LLVM or LLD is not smart enough to lay out the TLS data in a space-conserving way. Anyway, I | 491 | // and LLVM or LLD is not smart enough to lay out the TLS data in a space-conserving way. Anyway, I |
| 491 | // think it's fine because it's less than 3 pages of memory, and putting it in the ELF like this is | 492 | // think it's fine because it's less than 3 pages of memory, and putting it in the ELF like this is |
| 492 | // equivalent to moving the `mmap` call below into the kernel, avoiding syscall overhead. | 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 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, | 496 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, |
| 496 | /// and assigns the architecture-specific value to the TP register. | 497 | /// and assigns the architecture-specific value to the TP register. |
| ... | @@ -503,7 +504,7 @@ pub fn initStatic(phdrs: []elf.Phdr) void { | ... | @@ -503,7 +504,7 @@ pub fn initStatic(phdrs: []elf.Phdr) void { |
| 503 | const area = blk: { | 504 | const area = blk: { |
| 504 | // Fast path for the common case where the TLS data is really small, avoid an allocation and | 505 | // Fast path for the common case where the TLS data is really small, avoid an allocation and |
| 505 | // use our local buffer. | 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 | break :blk main_thread_area_buffer[0..area_desc.size]; | 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,7 +518,7 @@ pub fn initStatic(phdrs: []elf.Phdr) void { |
| 517 | ); | 518 | ); |
| 518 | if (@as(isize, @bitCast(begin_addr)) < 0) @trap(); | 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 | // Make sure the slice is correctly aligned. | 523 | // Make sure the slice is correctly aligned. |
| 523 | const begin_aligned_addr = alignForward(begin_addr, area_desc.alignment); | 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,8 +367,8 @@ pub fn sbrk(n: usize) usize { |
| 367 | bloc = @intFromPtr(&ExecData.end); | 367 | bloc = @intFromPtr(&ExecData.end); |
| 368 | bloc_max = @intFromPtr(&ExecData.end); | 368 | bloc_max = @intFromPtr(&ExecData.end); |
| 369 | } | 369 | } |
| 370 | const bl = std.mem.alignForward(usize, bloc, 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.mem.page_size); | 371 | const n_aligned = std.mem.alignForward(usize, n, std.heap.pageSize()); |
| 372 | if (bl + n_aligned > bloc_max) { | 372 | if (bl + n_aligned > bloc_max) { |
| 373 | // we need to allocate | 373 | // we need to allocate |
| 374 | if (brk_(bl + n_aligned) < 0) return 0; | 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,6 +42,7 @@ const WCHAR = windows.WCHAR; |
| 42 | const WIN32_FIND_DATAW = windows.WIN32_FIND_DATAW; | 42 | const WIN32_FIND_DATAW = windows.WIN32_FIND_DATAW; |
| 43 | const Win32Error = windows.Win32Error; | 43 | const Win32Error = windows.Win32Error; |
| 44 | const WORD = windows.WORD; | 44 | const WORD = windows.WORD; |
| 45 | const SYSTEM_INFO = windows.SYSTEM_INFO; | ||
| 45 | 46 | ||
| 46 | // I/O - Filesystem | 47 | // I/O - Filesystem |
| 47 | 48 | ||
| ... | @@ -667,6 +668,6 @@ pub extern "kernel32" fn SetLastError( | ... | @@ -667,6 +668,6 @@ pub extern "kernel32" fn SetLastError( |
| 667 | // TODO: | 668 | // TODO: |
| 668 | // Wrapper around KUSER_SHARED_DATA.SystemTime. | 669 | // Wrapper around KUSER_SHARED_DATA.SystemTime. |
| 669 | // Much better to use NtQuerySystemTime or NtQuerySystemTimePrecise for guaranteed 0.1ns precision. | 670 | // Much better to use NtQuerySystemTime or NtQuerySystemTimePrecise for guaranteed 0.1ns precision. |
| 670 | pub extern "kernel32" fn GetSystemTimeAsFileTime( | 671 | pub extern "kernel32" fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *FILETIME) callconv(.winapi) void; |
| 671 | lpSystemTimeAsFileTime: *FILETIME, | 672 | |
| 672 | ) callconv(.winapi) void; | 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,6 +18,7 @@ const builtin = @import("builtin"); |
| 18 | const root = @import("root"); | 18 | const root = @import("root"); |
| 19 | const std = @import("std.zig"); | 19 | const std = @import("std.zig"); |
| 20 | const mem = std.mem; | 20 | const mem = std.mem; |
| 21 | const heap = std.heap; | ||
| 21 | const fs = std.fs; | 22 | const fs = std.fs; |
| 22 | const max_path_bytes = fs.max_path_bytes; | 23 | const max_path_bytes = fs.max_path_bytes; |
| 23 | const maxInt = std.math.maxInt; | 24 | const maxInt = std.math.maxInt; |
| ... | @@ -4694,7 +4695,7 @@ pub const MProtectError = error{ | ... | @@ -4694,7 +4695,7 @@ pub const MProtectError = error{ |
| 4694 | OutOfMemory, | 4695 | OutOfMemory, |
| 4695 | } || UnexpectedError; | 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 | if (native_os == .windows) { | 4699 | if (native_os == .windows) { |
| 4699 | const win_prot: windows.DWORD = switch (@as(u3, @truncate(protection))) { | 4700 | const win_prot: windows.DWORD = switch (@as(u3, @truncate(protection))) { |
| 4700 | 0b000 => windows.PAGE_NOACCESS, | 4701 | 0b000 => windows.PAGE_NOACCESS, |
| ... | @@ -4759,21 +4760,21 @@ pub const MMapError = error{ | ... | @@ -4759,21 +4760,21 @@ pub const MMapError = error{ |
| 4759 | /// * SIGSEGV - Attempted write into a region mapped as read-only. | 4760 | /// * SIGSEGV - Attempted write into a region mapped as read-only. |
| 4760 | /// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file | 4761 | /// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file |
| 4761 | pub fn mmap( | 4762 | pub fn mmap( |
| 4762 | ptr: ?[*]align(mem.page_size) u8, | 4763 | ptr: ?[*]align(heap.min_page_size) u8, |
| 4763 | length: usize, | 4764 | length: usize, |
| 4764 | prot: u32, | 4765 | prot: u32, |
| 4765 | flags: system.MAP, | 4766 | flags: system.MAP, |
| 4766 | fd: fd_t, | 4767 | fd: fd_t, |
| 4767 | offset: u64, | 4768 | offset: u64, |
| 4768 | ) MMapError![]align(mem.page_size) u8 { | 4769 | ) MMapError![]align(heap.min_page_size) u8 { |
| 4769 | const mmap_sym = if (lfs64_abi) system.mmap64 else system.mmap; | 4770 | const mmap_sym = if (lfs64_abi) system.mmap64 else system.mmap; |
| 4770 | const rc = mmap_sym(ptr, length, prot, @bitCast(flags), fd, @bitCast(offset)); | 4771 | const rc = mmap_sym(ptr, length, prot, @bitCast(flags), fd, @bitCast(offset)); |
| 4771 | const err: E = if (builtin.link_libc) blk: { | 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 | break :blk @enumFromInt(system._errno().*); | 4774 | break :blk @enumFromInt(system._errno().*); |
| 4774 | } else blk: { | 4775 | } else blk: { |
| 4775 | const err = errno(rc); | 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 | break :blk err; | 4778 | break :blk err; |
| 4778 | }; | 4779 | }; |
| 4779 | switch (err) { | 4780 | switch (err) { |
| ... | @@ -4799,7 +4800,7 @@ pub fn mmap( | ... | @@ -4799,7 +4800,7 @@ pub fn mmap( |
| 4799 | /// Zig's munmap function does not, for two reasons: | 4800 | /// Zig's munmap function does not, for two reasons: |
| 4800 | /// * It violates the Zig principle that resource deallocation must succeed. | 4801 | /// * It violates the Zig principle that resource deallocation must succeed. |
| 4801 | /// * The Windows function, VirtualFree, has this restriction. | 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 | switch (errno(system.munmap(memory.ptr, memory.len))) { | 4804 | switch (errno(system.munmap(memory.ptr, memory.len))) { |
| 4804 | .SUCCESS => return, | 4805 | .SUCCESS => return, |
| 4805 | .INVAL => unreachable, // Invalid parameters. | 4806 | .INVAL => unreachable, // Invalid parameters. |
| ... | @@ -4813,7 +4814,7 @@ pub const MSyncError = error{ | ... | @@ -4813,7 +4814,7 @@ pub const MSyncError = error{ |
| 4813 | PermissionDenied, | 4814 | PermissionDenied, |
| 4814 | } || UnexpectedError; | 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 | switch (errno(system.msync(memory.ptr, memory.len, flags))) { | 4818 | switch (errno(system.msync(memory.ptr, memory.len, flags))) { |
| 4818 | .SUCCESS => return, | 4819 | .SUCCESS => return, |
| 4819 | .PERM => return error.PermissionDenied, | 4820 | .PERM => return error.PermissionDenied, |
| ... | @@ -7135,7 +7136,7 @@ pub const MincoreError = error{ | ... | @@ -7135,7 +7136,7 @@ pub const MincoreError = error{ |
| 7135 | } || UnexpectedError; | 7136 | } || UnexpectedError; |
| 7136 | 7137 | ||
| 7137 | /// Determine whether pages are resident in memory. | 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 | return switch (errno(system.mincore(ptr, length, vec))) { | 7140 | return switch (errno(system.mincore(ptr, length, vec))) { |
| 7140 | .SUCCESS => {}, | 7141 | .SUCCESS => {}, |
| 7141 | .AGAIN => error.SystemResources, | 7142 | .AGAIN => error.SystemResources, |
| ... | @@ -7181,7 +7182,7 @@ pub const MadviseError = error{ | ... | @@ -7181,7 +7182,7 @@ pub const MadviseError = error{ |
| 7181 | 7182 | ||
| 7182 | /// Give advice about use of memory. | 7183 | /// Give advice about use of memory. |
| 7183 | /// This syscall is optional and is sometimes configured to be disabled. | 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 | switch (errno(system.madvise(ptr, length, advice))) { | 7186 | switch (errno(system.madvise(ptr, length, advice))) { |
| 7186 | .SUCCESS => return, | 7187 | .SUCCESS => return, |
| 7187 | .PERM => return error.PermissionDenied, | 7188 | .PERM => return error.PermissionDenied, |
lib/std/process.zig+1-1| ... | @@ -1560,7 +1560,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { | ... | @@ -1560,7 +1560,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { |
| 1560 | ReadGroupId, | 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 | var name_index: usize = 0; | 1564 | var name_index: usize = 0; |
| 1565 | var state = State.Start; | 1565 | var state = State.Start; |
| 1566 | var uid: posix.uid_t = 0; | 1566 | var uid: posix.uid_t = 0; |
lib/std/start.zig+1-1| ... | @@ -576,7 +576,7 @@ fn expandStackSize(phdrs: []elf.Phdr) void { | ... | @@ -576,7 +576,7 @@ fn expandStackSize(phdrs: []elf.Phdr) void { |
| 576 | switch (phdr.p_type) { | 576 | switch (phdr.p_type) { |
| 577 | elf.PT_GNU_STACK => { | 577 | elf.PT_GNU_STACK => { |
| 578 | if (phdr.p_memsz == 0) break; | 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 | // Silently fail if we are unable to get limits. | 581 | // Silently fail if we are unable to get limits. |
| 582 | const limits = std.posix.getrlimit(.STACK) catch break; | 582 | const limits = std.posix.getrlimit(.STACK) catch break; |
lib/std/std.zig+4| ... | @@ -119,6 +119,10 @@ pub const Options = struct { | ... | @@ -119,6 +119,10 @@ pub const Options = struct { |
| 119 | args: anytype, | 119 | args: anytype, |
| 120 | ) void = log.defaultLog, | 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 | fmt_max_depth: usize = fmt.default_max_depth, | 126 | fmt_max_depth: usize = fmt.default_max_depth, |
| 123 | 127 | ||
| 124 | cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed, | 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,7 +162,7 @@ pub fn decompress( |
| 162 | var total_uncompressed: u64 = 0; | 162 | var total_uncompressed: u64 = 0; |
| 163 | switch (method) { | 163 | switch (method) { |
| 164 | .store => { | 164 | .store => { |
| 165 | var buf: [std.mem.page_size]u8 = undefined; | 165 | var buf: [4096]u8 = undefined; |
| 166 | while (true) { | 166 | while (true) { |
| 167 | const len = try reader.read(&buf); | 167 | const len = try reader.read(&buf); |
| 168 | if (len == 0) break; | 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,7 +1249,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { |
| 1249 | .{@errorName(err)}, | 1249 | .{@errorName(err)}, |
| 1250 | )); | 1250 | )); |
| 1251 | defer zip_file.close(); | 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 | while (true) { | 1253 | while (true) { |
| 1254 | const len = reader.readAll(&buf) catch |err| return f.fail(f.location_tok, try eb.printString( | 1254 | const len = reader.readAll(&buf) catch |err| return f.fail(f.location_tok, try eb.printString( |
| 1255 | "read zip stream failed: {s}", | 1255 | "read zip stream failed: {s}", |