Skip to content

Commit

Permalink
std.os: add getDefaultPageSize() with smoke tests
Browse files Browse the repository at this point in the history
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
rg 'define.*_SC_PAGE_SIZE' -B 1 --vimgrep

Closes #11308.
  • Loading branch information
Jan Philipp Hafer committed Aug 2, 2023
1 parent 9e19969 commit 9e3f451
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/dragonfly.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/freebsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions lib/std/c/fuchsia.zig
Original file line number Diff line number Diff line change
@@ -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,
};
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/haiku.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/hermit.zig
Original file line number Diff line number Diff line change
@@ -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),
};
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions lib/std/c/minix.zig
Original file line number Diff line number Diff line change
@@ -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,
};
Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/netbsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions lib/std/c/openbsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
11 changes: 5 additions & 6 deletions lib/std/c/solaris.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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,
Expand Down
39 changes: 39 additions & 0 deletions lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4338,6 +4338,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
.emscripten, .wasm32, .wasm64 => 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;
},
.macos, .ios, .watchos, .tvos => return @bitCast(darwin.getPageSize() catch unreachable),
// zig fmt: off
.dragonfly, .freebsd, .fuchsia, haiku,
.minix, netbsd, openbsd, solaris, => return std.c.sysconf(std.c._SC.PAGESIZE),
// TODO .hermit
// zig fmt: on
else => unreachable,
}
}

pub const MMapError = error{
/// The underlying filesystem of the specified file does not support memory mapping.
MemoryMappingNotSupported,
Expand Down
11 changes: 11 additions & 0 deletions lib/std/os/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 = os.getDefaultPageSize();
switch (page_size) {
// zig fmt: off
1024, 4096, 8192, 16384, 16384, 32768, // 1, 4, 8, 16, 32KB
2097152, 4194304 => {}, // 2, 4MB
// zig fmt: on
else => return error.InvalidDefaultPageSize,
}
}

0 comments on commit 9e3f451

Please sign in to comment.