From 41c40f4bbec35ac260b6a7af6b0db0dafccb56ca Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 27 Nov 2020 23:02:22 +0700 Subject: [PATCH] Fix fork() on Linux/sparc64 fork() on Linux/sparc64 seems to return its result in two registers, with %o0 always holding the current process' PID, and the parent/child status returned in %o1. Add some glue code to convert those into the libc-style return value. --- lib/std/os/linux.zig | 4 +++- lib/std/os/linux/sparc64.zig | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 56e9d45a0..dbb9225aa 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -112,7 +112,9 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*: } pub fn fork() usize { - if (@hasField(SYS, "fork")) { + if (comptime builtin.arch.isSPARC()) { + return syscall_fork(); + } else if (@hasField(SYS, "fork")) { return syscall0(.fork); } else { return syscall2(.clone, SIGCHLD, 0); diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index eefa4d60f..20fdc275d 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -21,6 +21,23 @@ pub fn syscall_pipe(fd: *[2]i32) usize { ); } +pub fn syscall_fork() usize { + return asm volatile ( + \\ t 0x6d + \\ bcc,pt %%xcc, 1f + \\ nop + \\ ba 2f + \\ neg %%o0 + \\ 1: + \\ dec %%o1 + \\ and %%o1, %%o0, %%o0 + \\ 2: + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(SYS.fork)) + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" + ); +} + pub fn syscall0(number: SYS) usize { return asm volatile ( \\ t 0x6d