| ... | @@ -474,7 +474,7 @@ pub fn dup2(old: i32, new: i32) usize { | ... | @@ -474,7 +474,7 @@ pub fn dup2(old: i32, new: i32) usize { |
| 474 | } else { | 474 | } else { |
| 475 | if (old == new) { | 475 | if (old == new) { |
| 476 | if (std.debug.runtime_safety) { | 476 | if (std.debug.runtime_safety) { |
| 477 | const rc = syscall2(.fcntl, @as(usize, @bitCast(@as(isize, old))), F.GETFD); | 477 | const rc = fcntl(F.GETFD, @as(fd_t, old), 0); |
| 478 | if (@as(isize, @bitCast(rc)) < 0) return rc; | 478 | if (@as(isize, @bitCast(rc)) < 0) return rc; |
| 479 | } | 479 | } |
| 480 | return @as(usize, @intCast(old)); | 480 | return @as(usize, @intCast(old)); |
| ... | @@ -1211,7 +1211,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { | ... | @@ -1211,7 +1211,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { |
| 1211 | // NOTE: The offset parameter splitting is independent from the target | 1211 | // NOTE: The offset parameter splitting is independent from the target |
| 1212 | // endianness. | 1212 | // endianness. |
| 1213 | return syscall5( | 1213 | return syscall5( |
| 1214 | ._llseek, | 1214 | .llseek, |
| 1215 | @as(usize, @bitCast(@as(isize, fd))), | 1215 | @as(usize, @bitCast(@as(isize, fd))), |
| 1216 | @as(usize, @truncate(offset >> 32)), | 1216 | @as(usize, @truncate(offset >> 32)), |
| 1217 | @as(usize, @truncate(offset)), | 1217 | @as(usize, @truncate(offset)), |
| ... | @@ -1370,7 +1370,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize { | ... | @@ -1370,7 +1370,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize { |
| 1370 | } | 1370 | } |
| 1371 | | 1371 | |
| 1372 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize { | 1372 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize { |
| 1373 | return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); | 1373 | if (@hasField(SYS, "fcntl64")) { |
| | 1374 | return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); |
| | 1375 | } else { |
| | 1376 | return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); |
| | 1377 | } |
| 1374 | } | 1378 | } |
| 1375 | | 1379 | |
| 1376 | pub fn flock(fd: fd_t, operation: i32) usize { | 1380 | pub fn flock(fd: fd_t, operation: i32) usize { |
| ... | @@ -2198,40 +2202,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const | ... | @@ -2198,40 +2202,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const |
| 2198 | } | 2202 | } |
| 2199 | | 2203 | |
| 2200 | pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { | 2204 | pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { |
| 2201 | if (comptime builtin.cpu.arch.isMIPS()) { | 2205 | if (comptime native_arch.isARM() or native_arch.isPPC()) { |
| 2202 | // MIPS requires a 7 argument syscall | 2206 | // These architectures reorder the arguments so that a register is not skipped to align the |
| | 2207 | // register number that `offset` is passed in. |
| 2203 | | 2208 | |
| 2204 | const offset_halves = splitValue64(offset); | 2209 | const offset_halves = splitValue64(offset); |
| 2205 | const length_halves = splitValue64(len); | 2210 | const length_halves = splitValue64(len); |
| 2206 | | 2211 | |
| 2207 | return syscall7( | 2212 | return syscall6( |
| 2208 | .fadvise64, | 2213 | .fadvise64_64, |
| 2209 | @as(usize, @bitCast(@as(isize, fd))), | 2214 | @as(usize, @bitCast(@as(isize, fd))), |
| 2210 | 0, | 2215 | advice, |
| 2211 | offset_halves[0], | 2216 | offset_halves[0], |
| 2212 | offset_halves[1], | 2217 | offset_halves[1], |
| 2213 | length_halves[0], | 2218 | length_halves[0], |
| 2214 | length_halves[1], | 2219 | length_halves[1], |
| 2215 | advice, | | |
| 2216 | ); | 2220 | ); |
| 2217 | } else if (comptime builtin.cpu.arch.isARM()) { | 2221 | } else if (comptime native_arch == .mips or native_arch == .mipsel) { |
| 2218 | // ARM reorders the arguments | 2222 | // MIPS O32 does not deal with the register alignment issue, so pass a dummy value. |
| 2219 | | 2223 | |
| 2220 | const offset_halves = splitValue64(offset); | 2224 | const offset_halves = splitValue64(offset); |
| 2221 | const length_halves = splitValue64(len); | 2225 | const length_halves = splitValue64(len); |
| 2222 | | 2226 | |
| 2223 | return syscall6( | 2227 | return syscall7( |
| 2224 | .fadvise64_64, | 2228 | .fadvise64, |
| 2225 | @as(usize, @bitCast(@as(isize, fd))), | 2229 | @as(usize, @bitCast(@as(isize, fd))), |
| 2226 | advice, | 2230 | 0, |
| 2227 | offset_halves[0], | 2231 | offset_halves[0], |
| 2228 | offset_halves[1], | 2232 | offset_halves[1], |
| 2229 | length_halves[0], | 2233 | length_halves[0], |
| 2230 | length_halves[1], | 2234 | length_halves[1], |
| | 2235 | advice, |
| 2231 | ); | 2236 | ); |
| 2232 | } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) { | 2237 | } else if (comptime usize_bits < 64) { |
| 2233 | // The extra usize check is needed to avoid SPARC64 because it provides both | 2238 | // Other 32-bit architectures do not require register alignment. |
| 2234 | // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms. | | |
| 2235 | | 2239 | |
| 2236 | const offset_halves = splitValue64(offset); | 2240 | const offset_halves = splitValue64(offset); |
| 2237 | const length_halves = splitValue64(len); | 2241 | const length_halves = splitValue64(len); |
| ... | @@ -2246,8 +2250,18 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { | ... | @@ -2246,8 +2250,18 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { |
| 2246 | advice, | 2250 | advice, |
| 2247 | ); | 2251 | ); |
| 2248 | } else { | 2252 | } else { |
| | 2253 | // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports |
| | 2254 | // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V, |
| | 2255 | // LoongArch, etc). SPARC is the odd one out because it has both. |
| 2249 | return syscall4( | 2256 | return syscall4( |
| 2250 | .fadvise64, | 2257 | // 64-bit SPARC (apparently?) has a broken fadvise64_64, so use its fadvise64 instead. |
| | 2258 | // TODO: I can't make sense of this. They go to the same code in the kernel, and there |
| | 2259 | // is no special-casing for SPARC in glibc and musl. I suspect a QEMU bug, which is |
| | 2260 | // really not our responsibility. |
| | 2261 | if (@hasField(SYS, "fadvise64_64") and native_arch != .sparc64) |
| | 2262 | .fadvise64_64 |
| | 2263 | else |
| | 2264 | .fadvise64, |
| 2251 | @as(usize, @bitCast(@as(isize, fd))), | 2265 | @as(usize, @bitCast(@as(isize, fd))), |
| 2252 | @as(usize, @bitCast(offset)), | 2266 | @as(usize, @bitCast(offset)), |
| 2253 | @as(usize, @bitCast(len)), | 2267 | @as(usize, @bitCast(len)), |