diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 6c88d9eae1d8..09f3c79aa640 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1440,6 +1440,65 @@ pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize, ); } +pub fn fadvise(fd: fd_t, offset: u64, len: u64, advice: usize) usize { + if (comptime std.Target.current.cpu.arch.isMIPS()) { + // MIPS requires a 7 argument syscall + + const offset_halves = splitValue64(@bitCast(u64, offset)); + const length_halves = splitValue64(@bitCast(u64, len)); + + return syscall7( + .fadvise64, + @bitCast(usize, @as(isize, fd)), + 0, + offset_halves[0], + offset_halves[1], + length_halves[0], + length_halves[1], + advice, + ); + } else if (comptime std.Target.current.cpu.arch.isARM()) { + // ARM reorders the arguments + + const offset_halves = splitValue64(@bitCast(u64, offset)); + const length_halves = splitValue64(@bitCast(u64, len)); + + return syscall6( + .fadvise64_64, + @bitCast(usize, @as(isize, fd)), + advice, + offset_halves[0], + offset_halves[1], + length_halves[0], + length_halves[1], + ); + } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) { + // The extra usize check is needed to avoid SPARC64 because it provides both + // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms. + + const offset_halves = splitValue64(@bitCast(u64, offset)); + const length_halves = splitValue64(@bitCast(u64, len)); + + return syscall6( + .fadvise64_64, + @bitCast(usize, @as(isize, fd)), + offset_halves[0], + offset_halves[1], + length_halves[0], + length_halves[1], + advice, + ); + } else { + return syscall4( + .fadvise64, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, offset), + @bitCast(usize, len), + advice, + ); + } +} + test { if (builtin.os.tag == .linux) { _ = @import("linux/test.zig"); diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 039678e40579..80f011e618f5 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -108,3 +108,23 @@ test "user and group ids" { expectEqual(linux.getauxval(elf.AT_EUID), linux.geteuid()); expectEqual(linux.getauxval(elf.AT_EGID), linux.getegid()); } + +test "fadvise" { + const tmp_file_name = "temp_posix_fadvise.txt"; + var file = try fs.cwd().createFile(tmp_file_name, .{}); + defer { + file.close(); + fs.cwd().deleteFile(tmp_file_name) catch {}; + } + + var buf: [2048]u8 = undefined; + try file.writeAll(&buf); + + const ret = linux.fadvise( + file.handle, + 0, + 0, + linux.POSIX_FADV_SEQUENTIAL, + ); + expectEqual(@as(usize, 0), ret); +}