zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit dab794394ff816e892d757b4c7fe52958f14dfe9 (tree)
parent a3da3eea8f3bf0c9e26a84e9c280662d95c6bda2
Author: Alex Rønne Petersen <alex@alexrp.com>
Date:   Wed, 17 Jun 2026 22:37:40 +0200

Merge pull request '`std.Io.Threaded`: only use `llseek()` on Linux if `@sizeOf(syscall_arg_t) == 4`' (#35820) from alexrp/zig:x32-n32-llseek into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35820

Diffstat:
Mlib/std/Io/Threaded.zig | 4++--
Mlib/std/os/linux.zig | 18+++++++++++++-----
Mlib/std/os/linux/mipsn32.zig | 19+++++++++++++++++++
Mlib/std/os/linux/x32.zig | 14++++++++++++++
4 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig @@ -10195,7 +10195,7 @@ fn fileSeekBy(userdata: ?*anyopaque, file: File, offset: i64) File.SeekError!voi if (posix.SEEK == void) return error.Unseekable; - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { + if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) { var result: i64 = undefined; const syscall: Syscall = try .start(); while (true) { @@ -10307,7 +10307,7 @@ fn fileSeekTo(userdata: ?*anyopaque, file: File, offset: u64) File.SeekError!voi } fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void { - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { + if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) { const syscall: Syscall = try .start(); while (true) { var result: i64 = undefined; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig @@ -80,6 +80,7 @@ pub const restore_rt = syscall_bits.restore_rt; pub const socketcall = syscall_bits.socketcall; pub const syscall_pipe = syscall_bits.syscall_pipe; pub const syscall_fork = syscall_bits.syscall_fork; +pub const syscall_lseek = syscall_bits.syscall_lseek; pub fn clone( func: *const fn (arg: usize) callconv(.c) u8, @@ -751,8 +752,8 @@ fn splitValue64(val: i64) [2]u32 { } /// Get the errno from a syscall return value. SUCCESS means no error. -pub fn errno(r: usize) E { - const signed_r: isize = @bitCast(r); +pub fn errno(r: u64) E { + const signed_r: i32 = @bitCast(@as(u32, @truncate(r))); const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0; return @enumFromInt(int); } @@ -1809,7 +1810,7 @@ pub fn fchmodat2(fd: fd_t, path: [*:0]const u8, mode: mode_t, flags: u32) usize } /// Can only be called on 32 bit systems. For 64 bit see `lseek`. -pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize { +pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) u32 { // NOTE: The offset parameter splitting is independent from the target // endianness. return syscall5( @@ -1823,8 +1824,15 @@ pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize { } /// Can only be called on 64 bit systems. For 32 bit see `llseek`. -pub fn lseek(fd: fd_t, offset: off_t, whence: u32) usize { - return syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence); +pub fn lseek(fd: fd_t, offset: off_t, whence: u32) u64 { + return switch (builtin.abi) { + .gnuabin32, + .muslabin32, + .gnux32, + .muslx32, + => syscall_lseek(fd, offset, whence), + else => syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence), + }; } pub fn exit(status: i32) noreturn { diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig @@ -163,6 +163,25 @@ pub fn syscall_pipe( : .{ .r1 = true, .r3 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); } +pub fn syscall_lseek( + fd: std.os.linux.fd_t, + offset: std.os.linux.off_t, + whence: u32, +) u64 { + return asm volatile ( + \\ syscall + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: + : [ret] "={$2}" (-> u64), + : [number] "{$2}" (@intFromEnum(SYS.lseek)), + [fd] "{$4}" (@as(u32, @bitCast(fd))), + [offset] "{$5}" (@as(u64, @bitCast(offset))), + [whence] "{$6}" (whence), + : .{ .r1 = true, .r3 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); +} + pub fn clone() callconv(.naked) u32 { // __clone(func, stack, flags, arg, ptid, tls, ctid) // a0, a1, a2, a3, a4, a5, a6 diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig @@ -109,6 +109,20 @@ pub fn syscall6( : .{ .rcx = true, .r11 = true, .memory = true }); } +pub fn syscall_lseek( + fd: std.os.linux.fd_t, + offset: std.os.linux.off_t, + whence: u32, +) u64 { + return asm volatile ("syscall" + : [ret] "={rax}" (-> u64), + : [number] "{rax}" (@intFromEnum(SYS.lseek)), + [fd] "{rdi}" (@as(u32, @bitCast(fd))), + [offset] "{rsi}" (@as(u64, @bitCast(offset))), + [whence] "{rdx}" (whence), + : .{ .rcx = true, .r11 = true, .memory = true }); +} + pub fn clone() callconv(.naked) u32 { asm volatile ( \\ movl $0x40000038,%%eax // SYS_clone