From 8e016355bc8e2a993e246e8fa12c98e05eab4660 Mon Sep 17 00:00:00 2001 From: Jan Philipp Hafer Date: Tue, 1 Aug 2023 01:39:42 +0200 Subject: [PATCH] std.os: add getDefaultPageSize() with smoke tests The Kernel provides each program with the default page size, which this function reads. Reproduce added abi bits with: git clone --depth=1 https://github.com/DragonFlyBSD/DragonFlyBSD git clone --depth=1 https://git.FreeBSD.org/src.git freebsd git clone --depth=1 https://fuchsia.googlesource.com/fuchsia git clone --depth=1 https://github.com/haiku/haiku git clone --depth=1 https://github.com/Stichting-MINIX-Research-Foundation/minix/ git clone --depth=1 https://github.com/NetBSD/src netbsd git clone --depth=1 https://github.com/openbsd/src openbsd git clone --depth=1 https://github.com/kofemann/opensolaris git clone --depth=1 https://github.com/apple-open-source-mirror/Libc rg 'define.*_SC_PAGE_SIZE' -B 1 --vimgrep Closes #11308. --- lib/std/c.zig | 1 + lib/std/c/darwin.zig | 5 ++++- lib/std/c/dragonfly.zig | 4 ++++ lib/std/c/freebsd.zig | 4 ++++ lib/std/c/fuchsia.zig | 5 +++++ lib/std/c/haiku.zig | 4 ++++ lib/std/c/hermit.zig | 4 ++++ lib/std/c/linux.zig | 4 ++++ lib/std/c/minix.zig | 5 +++++ lib/std/c/netbsd.zig | 4 ++++ lib/std/c/openbsd.zig | 4 ++++ lib/std/c/solaris.zig | 11 +++++------ lib/std/os.zig | 39 +++++++++++++++++++++++++++++++++++++++ lib/std/os/test.zig | 13 ++++++++++++- 14 files changed, 99 insertions(+), 8 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 66875eadd034..32157b3611b4 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -78,6 +78,7 @@ pub usingnamespace switch (builtin.os.tag) { pub extern "c" fn getrusage(who: c_int, usage: *c.rusage) c_int; + pub extern "c" fn sysconf(sc: c_int) c_long; pub extern "c" fn sched_yield() c_int; pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const c.Sigaction, noalias oact: ?*c.Sigaction) c_int; diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index fa121c49c527..39270a40f466 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -233,6 +233,9 @@ pub const mach_header_64 = macho.mach_header_64; pub const mach_header = macho.mach_header; pub const _errno = __error; +pub const _SC = struct { + pub const PAGESIZE = 29; +}; pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int; pub extern "c" fn mach_host_self() mach_port_t; @@ -3691,7 +3694,7 @@ pub const MachTask = extern struct { return left; } - fn getPageSize(task: MachTask) MachError!usize { + pub fn getPageSize(task: MachTask) MachError!usize { if (task.isValid()) { var info_count = TASK_VM_INFO_COUNT; var vm_info: task_vm_info_data_t = undefined; diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig index d4f2867fda3a..3215295773a5 100644 --- a/lib/std/c/dragonfly.zig +++ b/lib/std/c/dragonfly.zig @@ -9,6 +9,10 @@ pub fn _errno() *c_int { return &errno; } +pub const _SC = struct { + pub const PAGESIZE = 47; +}; + pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 6a8997bedf99..11bf39339888 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -8,6 +8,10 @@ const iovec_const = std.os.iovec_const; extern "c" fn __error() *c_int; pub const _errno = __error; +pub const _SC = struct { + pub const PAGESIZE = 47; +}; + pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) isize; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; diff --git a/lib/std/c/fuchsia.zig b/lib/std/c/fuchsia.zig index af6c4756b9ee..eb5763bcafee 100644 --- a/lib/std/c/fuchsia.zig +++ b/lib/std/c/fuchsia.zig @@ -1,3 +1,8 @@ +// third party ulib musl +pub const _SC = struct { + pub const PAGESIZE = 30; +}; + pub const pthread_mutex_t = extern struct { size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, }; diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index a64eb03b419f..6276199ff050 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -9,6 +9,10 @@ extern "c" fn _errnop() *c_int; pub const _errno = _errnop; +pub const _SC = struct { + pub const PAGESIZE = 27; +}; + pub extern "c" fn find_directory(which: c_int, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; pub extern "c" fn find_thread(thread_name: ?*anyopaque) i32; diff --git a/lib/std/c/hermit.zig b/lib/std/c/hermit.zig index 879346ba13d7..088cf0689f5f 100644 --- a/lib/std/c/hermit.zig +++ b/lib/std/c/hermit.zig @@ -1,6 +1,10 @@ const std = @import("std"); const maxInt = std.math.maxInt; +// pub const _SC = struct { +// pub const PAGESIZE = TODO; +// }; + pub const pthread_mutex_t = extern struct { inner: usize = ~@as(usize, 0), }; diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index c4986101dfad..33c3b7509171 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -105,6 +105,10 @@ pub const user_desc = linux.user_desc; pub const utsname = linux.utsname; pub const PR = linux.PR; +pub const _SC = struct { + pub const PAGESIZE = 30; +}; + pub const _errno = switch (native_abi) { .android => struct { extern fn __errno() *c_int; diff --git a/lib/std/c/minix.zig b/lib/std/c/minix.zig index 62cefc14fb57..fa9e0742d828 100644 --- a/lib/std/c/minix.zig +++ b/lib/std/c/minix.zig @@ -1,4 +1,9 @@ const builtin = @import("builtin"); + +pub const _SC = struct { + pub const PAGESIZE = 28; +}; + pub const pthread_mutex_t = extern struct { size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, }; diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig index 4b627ed083b7..06a75fab3bcd 100644 --- a/lib/std/c/netbsd.zig +++ b/lib/std/c/netbsd.zig @@ -10,6 +10,10 @@ const rusage = std.c.rusage; extern "c" fn __errno() *c_int; pub const _errno = __errno; +pub const _SC = struct { + pub const PAGESIZE = 28; +}; + pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int; diff --git a/lib/std/c/openbsd.zig b/lib/std/c/openbsd.zig index 33a60df95428..e341ad81d584 100644 --- a/lib/std/c/openbsd.zig +++ b/lib/std/c/openbsd.zig @@ -8,6 +8,10 @@ const iovec_const = std.os.iovec_const; extern "c" fn __errno() *c_int; pub const _errno = __errno; +pub const _SC = struct { + pub const PAGESIZE = 28; +}; + pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int; diff --git a/lib/std/c/solaris.zig b/lib/std/c/solaris.zig index 58d02416cbdb..b42322ef3b39 100644 --- a/lib/std/c/solaris.zig +++ b/lib/std/c/solaris.zig @@ -9,6 +9,11 @@ const timezone = std.c.timezone; extern "c" fn ___errno() *c_int; pub const _errno = ___errno; +pub const _SC = struct { + pub const PAGESIZE = 11; + pub const NPROCESSORS_ONLN = 15; +}; + pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int; @@ -17,7 +22,6 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void; pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int; -pub extern "c" fn sysconf(sc: c_int) i64; pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int; pub extern "c" fn madvise(address: [*]u8, len: usize, advise: u32) c_int; @@ -1684,11 +1688,6 @@ pub const AF_SUN = struct { pub const NOPLM = 0x00000004; }; -// TODO: Add sysconf numbers when the other OSs do. -pub const _SC = struct { - pub const NPROCESSORS_ONLN = 15; -}; - pub const procfs = struct { pub const misc_header = extern struct { size: u32, diff --git a/lib/std/os.zig b/lib/std/os.zig index 0a1bcc9ac1e0..70dab006f8fc 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4335,6 +4335,45 @@ pub fn fork() ForkError!pid_t { } } +/// Returns page size assigned by the Kernel to the process. This size is +/// constant during process lifetime, but other page sizes might be usable. +pub fn getDefaultPageSize() error{UnknownPageSize}!usize { + switch (builtin.cpu.arch) { // archs with fixed size page size + .wasm32, .wasm64 => return 64 * 1024, + else => {}, + } + + switch (builtin.os.tag) { // kernel chooses the page size + .linux => { + if (builtin.link_libc) { + return @bitCast(std.c.sysconf(std.c._SC.PAGESIZE)); + } else { + return linux.getauxval(std.elf.AT_PAGESZ); + } + }, + .windows => { + var sbi: std.os.windows.SYSTEM_BASIC_INFORMATION = undefined; + const rc = std.os.windows.ntdll.NtQuerySystemInformation( + .SystemBasicInformation, + &sbi, + @sizeOf(std.os.windows.SYSTEM_BASIC_INFORMATION), + null, + ); + if (rc != .SUCCESS) { + return error.UnknownPageSize; + } + return sbi.PageSize; + }, + // zig fmt: off + .dragonfly, .freebsd, .fuchsia, .haiku, + .macos, .ios, .watchos, .tvos, + .minix, .netbsd, .openbsd, .solaris, => return std.c.sysconf(std.c._SC.PAGESIZE), + // TODO .hermit (no reliable page size and api yet) + // zig fmt: on + else => unreachable, + } +} + pub const MMapError = error{ /// The underlying filesystem of the specified file does not support memory mapping. MemoryMappingNotSupported, diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index d5451f64ac61..21eafc3321b6 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -1,4 +1,4 @@ -const std = @import("../std.zig"); +const std = @import("std"); const os = std.os; const testing = std.testing; const expect = testing.expect; @@ -1219,3 +1219,14 @@ test "fchmodat smoke test" { const st = try os.fstatat(tmp.dir.fd, "foo.txt", 0); try expectEqual(@as(os.mode_t, 0o755), st.mode & 0b111_111_111); } + +test "getDefaultPageSize smoke test" { + const page_size = try os.getDefaultPageSize(); + switch (page_size) { + // zig fmt: off + 1024, 2048, 4096, 8192, 16384, 32768, // 1, 2, 4, 8, 16, 32KB + 2097152, 4194304 => {}, // 2, 4MB + // zig fmt: on + else => return error.InvalidDefaultPageSize, + } +}