authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-17 22:37:40+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-17 22:37:40+02:00
logdab794394ff816e892d757b4c7fe52958f14dfe9
tree5620621db02fe6a8aa0c2040b475acaa3b7863d2
parenta3da3eea8f3bf0c9e26a84e9c280662d95c6bda2
parent386153612e4aab74b76c416eb96aa81dfca0c370

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

4 files changed, 48 insertions(+), 7 deletions(-)

lib/std/Io/Threaded.zig+2-2
...@@ -10195,7 +10195,7 @@ fn fileSeekBy(userdata: ?*anyopaque, file: File, offset: i64) File.SeekError!voi...@@ -10195,7 +10195,7 @@ fn fileSeekBy(userdata: ?*anyopaque, file: File, offset: i64) File.SeekError!voi
1019510195
10196 if (posix.SEEK == void) return error.Unseekable;10196 if (posix.SEEK == void) return error.Unseekable;
1019710197
10198 if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {10198 if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) {
10199 var result: i64 = undefined;10199 var result: i64 = undefined;
10200 const syscall: Syscall = try .start();10200 const syscall: Syscall = try .start();
10201 while (true) {10201 while (true) {
...@@ -10307,7 +10307,7 @@ fn fileSeekTo(userdata: ?*anyopaque, file: File, offset: u64) File.SeekError!voi...@@ -10307,7 +10307,7 @@ fn fileSeekTo(userdata: ?*anyopaque, file: File, offset: u64) File.SeekError!voi
10307}10307}
1030810308
10309fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void {10309fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void {
10310 if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {10310 if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) {
10311 const syscall: Syscall = try .start();10311 const syscall: Syscall = try .start();
10312 while (true) {10312 while (true) {
10313 var result: i64 = undefined;10313 var result: i64 = undefined;
lib/std/os/linux.zig+13-5
...@@ -80,6 +80,7 @@ pub const restore_rt = syscall_bits.restore_rt;...@@ -80,6 +80,7 @@ pub const restore_rt = syscall_bits.restore_rt;
80pub const socketcall = syscall_bits.socketcall;80pub const socketcall = syscall_bits.socketcall;
81pub const syscall_pipe = syscall_bits.syscall_pipe;81pub const syscall_pipe = syscall_bits.syscall_pipe;
82pub const syscall_fork = syscall_bits.syscall_fork;82pub const syscall_fork = syscall_bits.syscall_fork;
83pub const syscall_lseek = syscall_bits.syscall_lseek;
8384
84pub fn clone(85pub fn clone(
85 func: *const fn (arg: usize) callconv(.c) u8,86 func: *const fn (arg: usize) callconv(.c) u8,
...@@ -751,8 +752,8 @@ fn splitValue64(val: i64) [2]u32 {...@@ -751,8 +752,8 @@ fn splitValue64(val: i64) [2]u32 {
751}752}
752753
753/// Get the errno from a syscall return value. SUCCESS means no error.754/// Get the errno from a syscall return value. SUCCESS means no error.
754pub fn errno(r: usize) E {755pub fn errno(r: u64) E {
755 const signed_r: isize = @bitCast(r);756 const signed_r: i32 = @bitCast(@as(u32, @truncate(r)));
756 const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0;757 const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0;
757 return @enumFromInt(int);758 return @enumFromInt(int);
758}759}
...@@ -1809,7 +1810,7 @@ pub fn fchmodat2(fd: fd_t, path: [*:0]const u8, mode: mode_t, flags: u32) usize...@@ -1809,7 +1810,7 @@ pub fn fchmodat2(fd: fd_t, path: [*:0]const u8, mode: mode_t, flags: u32) usize
1809}1810}
18101811
1811/// Can only be called on 32 bit systems. For 64 bit see `lseek`.1812/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
1812pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {1813pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) u32 {
1813 // NOTE: The offset parameter splitting is independent from the target1814 // NOTE: The offset parameter splitting is independent from the target
1814 // endianness.1815 // endianness.
1815 return syscall5(1816 return syscall5(
...@@ -1823,8 +1824,15 @@ pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {...@@ -1823,8 +1824,15 @@ pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {
1823}1824}
18241825
1825/// Can only be called on 64 bit systems. For 32 bit see `llseek`.1826/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
1826pub fn lseek(fd: fd_t, offset: off_t, whence: u32) usize {1827pub fn lseek(fd: fd_t, offset: off_t, whence: u32) u64 {
1827 return syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence);1828 return switch (builtin.abi) {
1829 .gnuabin32,
1830 .muslabin32,
1831 .gnux32,
1832 .muslx32,
1833 => syscall_lseek(fd, offset, whence),
1834 else => syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence),
1835 };
1828}1836}
18291837
1830pub fn exit(status: i32) noreturn {1838pub fn exit(status: i32) noreturn {
lib/std/os/linux/mipsn32.zig+19
...@@ -163,6 +163,25 @@ pub fn syscall_pipe(...@@ -163,6 +163,25 @@ pub fn syscall_pipe(
163 : .{ .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 });163 : .{ .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 });
164}164}
165165
166pub fn syscall_lseek(
167 fd: std.os.linux.fd_t,
168 offset: std.os.linux.off_t,
169 whence: u32,
170) u64 {
171 return asm volatile (
172 \\ syscall
173 \\ beq $a3, $zero, 1f
174 \\ blez $v0, 1f
175 \\ dsubu $v0, $zero, $v0
176 \\1:
177 : [ret] "={$2}" (-> u64),
178 : [number] "{$2}" (@intFromEnum(SYS.lseek)),
179 [fd] "{$4}" (@as(u32, @bitCast(fd))),
180 [offset] "{$5}" (@as(u64, @bitCast(offset))),
181 [whence] "{$6}" (whence),
182 : .{ .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 });
183}
184
166pub fn clone() callconv(.naked) u32 {185pub fn clone() callconv(.naked) u32 {
167 // __clone(func, stack, flags, arg, ptid, tls, ctid)186 // __clone(func, stack, flags, arg, ptid, tls, ctid)
168 // a0, a1, a2, a3, a4, a5, a6187 // a0, a1, a2, a3, a4, a5, a6
lib/std/os/linux/x32.zig+14
...@@ -109,6 +109,20 @@ pub fn syscall6(...@@ -109,6 +109,20 @@ pub fn syscall6(
109 : .{ .rcx = true, .r11 = true, .memory = true });109 : .{ .rcx = true, .r11 = true, .memory = true });
110}110}
111111
112pub fn syscall_lseek(
113 fd: std.os.linux.fd_t,
114 offset: std.os.linux.off_t,
115 whence: u32,
116) u64 {
117 return asm volatile ("syscall"
118 : [ret] "={rax}" (-> u64),
119 : [number] "{rax}" (@intFromEnum(SYS.lseek)),
120 [fd] "{rdi}" (@as(u32, @bitCast(fd))),
121 [offset] "{rsi}" (@as(u64, @bitCast(offset))),
122 [whence] "{rdx}" (whence),
123 : .{ .rcx = true, .r11 = true, .memory = true });
124}
125
112pub fn clone() callconv(.naked) u32 {126pub fn clone() callconv(.naked) u32 {
113 asm volatile (127 asm volatile (
114 \\ movl $0x40000038,%%eax // SYS_clone128 \\ movl $0x40000038,%%eax // SYS_clone