Commit 41c40f4bbe

Koakuma <koachan@protonmail.com>
2020-11-27 17:02:22
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.
1 parent cf2ee4a
Changed files (2)
lib
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
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);