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
git clone --depth=1 https://github.com/apple-open-source-mirror/Libc
rg 'define.*_SC_PAGE_SIZE' -B 1 --vimgrep

Closes #11308.
  • Loading branch information
Jan Philipp Hafer committed Aug 13, 2023
1 parent a1049d4 commit 8e01635
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 8 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
5 changes: 4 additions & 1 deletion lib/std/c/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
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 @@ -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,
Expand Down
13 changes: 12 additions & 1 deletion lib/std/os/test.zig
Original file line number Diff line number Diff line change
@@ -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;
Expand Down 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 = 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,
}
}

0 comments on commit 8e01635

Please sign in to comment.