diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 110393d91a..7fd231aba7 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -215,7 +215,8 @@ pub const ElfDynLib = struct { const fd = try resolveFromName(path); defer posix.close(fd); - const stat = try posix.fstat(fd); + const file: std.fs.File = .{ .handle = fd }; + const stat = try file.stat(); const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig; // This one is to read the ELF info. We do more mmapping later diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index df9d491a5e..9039acedee 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1456,6 +1456,16 @@ pub fn clock_settime(clk_id: i32, tp: *const timespec) usize { return syscall2(.clock_settime, @as(usize, @bitCast(@as(isize, clk_id))), @intFromPtr(tp)); } +pub fn clock_nanosleep(clockid: clockid_t, flags: TIMER, request: *const timespec, remain: ?*timespec) usize { + return syscall4( + .clock_nanosleep, + @intFromEnum(clockid), + @as(u32, @bitCast(flags)), + @intFromPtr(request), + @intFromPtr(remain), + ); +} + pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) usize { return syscall2(.gettimeofday, @intFromPtr(tv), @intFromPtr(tz)); } @@ -1465,7 +1475,9 @@ pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize { } pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { - return syscall2(.nanosleep, @intFromPtr(req), @intFromPtr(rem)); + if (native_arch == .riscv32) { + @compileError("No nanosleep syscall on this architecture."); + } else return syscall2(.nanosleep, @intFromPtr(req), @intFromPtr(rem)); } pub fn pause() usize { @@ -4525,6 +4537,11 @@ pub const clockid_t = enum(u32) { _, }; +pub const TIMER = packed struct(u32) { + ABSTIME: bool, + _: u31 = 0, +}; + pub const CSIGNAL = 0x000000ff; pub const CLONE = struct { @@ -7452,7 +7469,7 @@ pub const kernel_timespec = extern struct { }; // https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877 -pub const timespec = if (!builtin.link_libc and native_arch == .riscv32) kernel_timespec else extern struct { +pub const timespec = if (native_arch == .riscv32) kernel_timespec else extern struct { sec: isize, nsec: isize, }; diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index 08288d45e5..457d7e50b4 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -212,8 +212,37 @@ pub const msghdr_const = extern struct { flags: i32, }; -/// No `Stat` structure on this platform, only `Statx`. -pub const Stat = void; +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + rdev: dev_t, + __pad: usize, + size: off_t, + blksize: blksize_t, + __pad2: i32, + blocks: blkcnt_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + __unused: [2]u32, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) timespec { + return self.ctim; + } +}; pub const Elf_Symndx = u32; diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 474de28f6d..e62ffa39ca 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -349,6 +349,7 @@ test "linkat with different directories" { } test "fstatat" { + if (builtin.cpu.arch == .riscv32 and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. // enable when `fstat` and `fstatat` are implemented on Windows if (native_os == .windows) return error.SkipZigTest; @@ -1264,6 +1265,9 @@ test "fchmodat smoke test" { 0o644, ); posix.close(fd); + + if (builtin.cpu.arch == .riscv32 and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. + try posix.symlinkat("regfile", tmp.dir.fd, "symlink"); const sym_mode = blk: { const st = try posix.fstatat(tmp.dir.fd, "symlink", posix.AT.SYMLINK_NOFOLLOW); diff --git a/lib/std/time.zig b/lib/std/time.zig index 34e544a28b..a80a2477ac 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -50,6 +50,34 @@ pub fn sleep(nanoseconds: u64) void { const s = nanoseconds / ns_per_s; const ns = nanoseconds % ns_per_s; + + // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around + // since Linux 2.6 and glibc 2.1 anyway. + if (builtin.os.tag == .linux) { + const linux = std.os.linux; + + var req: linux.timespec = .{ + .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t), + .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t), + }; + var rem: linux.timespec = undefined; + + while (true) { + switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) { + .SUCCESS => return, + .INTR => { + req = rem; + continue; + }, + .FAULT, + .INVAL, + .OPNOTSUPP, + => unreachable, + else => return, + } + } + } + posix.nanosleep(s, ns); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a46d875b34..dbaaa92597 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -12398,6 +12398,7 @@ fn backendSupportsF16(target: std.Target) bool { .mipsel, .mips64, .mips64el, + .riscv32, .s390x, => false, .aarch64,