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:
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