This patch to libgo by James Clarke fixes libgo for sparc64.  The
getrandom syscall was being ignored because the file was named
"sparc".  The clone syscall apparently needs special attention on
SPARC.  Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.
Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 240993)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-03e53c928ebaa15a915eb1e1b07f193d83fc2852
+d56717f8c434b3d6b753c027487681769e201e14
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am   (revision 240956)
+++ libgo/Makefile.am   (working copy)
@@ -736,6 +736,12 @@ s-epoll: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh epoll.go.tmp epoll.go
        $(STAMP) $@
 
+if LIBGO_IS_LINUX
+syscall_lib_clone_lo = syscall/clone_linux.lo
+else
+syscall_lib_clone_lo =
+endif
+
 libgo_go_objs = \
        bufio.lo \
        bytes.lo \
@@ -767,6 +773,7 @@ libgo_go_objs = \
        strings/index.lo \
        sync.lo \
        syscall.lo \
+       $(syscall_lib_clone_lo) \
        syscall/errno.lo \
        syscall/signame.lo \
        syscall/wait.lo \
@@ -2534,6 +2541,9 @@ syscall.lo.dep: $(srcdir)/go/syscall/*.g
        $(BUILDDEPS)
 syscall.lo:
        $(BUILDPACKAGE)
+syscall/clone_linux.lo: go/syscall/clone_linux.c runtime.inc
+       @$(MKDIR_P) syscall
+       $(LTCOMPILE) -c -o $@ $<
 syscall/errno.lo: go/syscall/errno.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
Index: libgo/go/internal/syscall/unix/getrandom_linux_sparc.go
===================================================================
--- libgo/go/internal/syscall/unix/getrandom_linux_sparc.go     (revision 
240942)
+++ libgo/go/internal/syscall/unix/getrandom_linux_sparc.go     (working copy)
@@ -1,11 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build sparc sparc64
-
-package unix
-
-// Linux getrandom system call number.
-// See GetRandom in getrandom_linux.go.
-const randomTrap uintptr = 347
Index: libgo/go/internal/syscall/unix/getrandom_linux_sparcx.go
===================================================================
--- libgo/go/internal/syscall/unix/getrandom_linux_sparcx.go    (revision 0)
+++ libgo/go/internal/syscall/unix/getrandom_linux_sparcx.go    (working copy)
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build sparc sparc64
+
+package unix
+
+// Linux getrandom system call number.
+// See GetRandom in getrandom_linux.go.
+const randomTrap uintptr = 347
Index: libgo/go/syscall/clone_linux.c
===================================================================
--- libgo/go/syscall/clone_linux.c      (revision 0)
+++ libgo/go/syscall/clone_linux.c      (working copy)
@@ -0,0 +1,100 @@
+/* clone_linux.c -- consistent wrapper around Linux clone syscall
+
+   Copyright 2016 The Go Authors. All rights reserved.
+   Use of this source code is governed by a BSD-style
+   license that can be found in the LICENSE file.  */
+
+#include <errno.h>
+#include <asm/ptrace.h>
+#include <sys/syscall.h>
+
+#include "runtime.h"
+
+long rawClone (unsigned long flags, void *child_stack, void *ptid, void *ctid, 
struct pt_regs *regs) __asm__ (GOSYM_PREFIX "syscall.rawClone");
+
+long
+rawClone (unsigned long flags, void *child_stack, void *ptid, void *ctid, 
struct pt_regs *regs)
+{
+#if defined(__arc__) || defined(__aarch64__) || defined(__arm__) || 
defined(__mips__) || defined(__hppa__) || defined(__powerpc__) || 
defined(__score__) || defined(__i386__) || defined(__xtensa__)
+  // CLONE_BACKWARDS
+  return syscall(__NR_clone, flags, child_stack, ptid, regs, ctid);
+#elif defined(__s390__) || defined(__cris__)
+  // CLONE_BACKWARDS2
+  return syscall(__NR_clone, child_stack, flags, ptid, ctid, regs);
+#elif defined(__microblaze__)
+  // CLONE_BACKWARDS3
+  return syscall(__NR_clone, flags, child_stack, 0, ptid, ctid, regs);
+#elif defined(__sparc__)
+
+  /* SPARC has a unique return value convention:
+
+     Parent -->  %o0 == child's  pid, %o1 == 0
+     Child  -->  %o0 == parent's pid, %o1 == 1
+
+     Translate this to look like a normal clone.  */
+
+# if defined(__arch64__)
+
+#  define SYSCALL_STRING                                               \
+       "ta     0x6d;"                                                  \
+       "bcc,pt %%xcc, 1f;"                                             \
+       " mov   0, %%g1;"                                               \
+       "sub    %%g0, %%o0, %%o0;"                                      \
+       "mov    1, %%g1;"                                               \
+       "1:"
+
+#  define SYSCALL_CLOBBERS                                             \
+       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",                 \
+       "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",           \
+       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",         \
+       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",         \
+       "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",         \
+       "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",         \
+       "cc", "memory"
+
+# else /* __arch64__ */
+
+#  define SYSCALL_STRING                                               \
+       "ta     0x10;"                                                  \
+       "bcc    1f;"                                                    \
+       " mov   0, %%g1;"                                               \
+       "sub    %%g0, %%o0, %%o0;"                                      \
+       "mov    1, %%g1;"                                               \
+       "1:"
+
+#  define SYSCALL_CLOBBERS                                             \
+       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",                 \
+       "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",           \
+       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",         \
+       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",         \
+       "cc", "memory"
+
+# endif /* __arch64__ */
+
+  register long o0 __asm__ ("o0") = (long)flags;
+  register long o1 __asm__ ("o1") = (long)child_stack;
+  register long o2 __asm__ ("o2") = (long)ptid;
+  register long o3 __asm__ ("o3") = (long)ctid;
+  register long o4 __asm__ ("o4") = (long)regs;
+  register long g1 __asm__ ("g1") = __NR_clone;
+
+  __asm __volatile (SYSCALL_STRING :
+                   "=r" (g1), "=r" (o0), "=r" (o1) :
+                   "0" (g1), "1" (o0), "2" (o1),
+                   "r" (o2), "r" (o3), "r" (o4) :
+                   SYSCALL_CLOBBERS);
+
+  if (__builtin_expect(g1 != 0, 0))
+    {
+      errno = -o0;
+      o0 = -1L;
+    }
+  else
+    o0 &= (o1 - 1);
+
+  return o0;
+
+#else
+  return syscall(__NR_clone, flags, child_stack, ptid, ctid, regs);
+#endif
+}
Index: libgo/go/syscall/exec_linux.go
===================================================================
--- libgo/go/syscall/exec_linux.go      (revision 240942)
+++ libgo/go/syscall/exec_linux.go      (working copy)
@@ -7,7 +7,6 @@
 package syscall
 
 import (
-       "runtime"
        "unsafe"
 )
 
@@ -49,6 +48,9 @@ type SysProcAttr struct {
 func runtime_BeforeFork()
 func runtime_AfterFork()
 
+// Implemented in clone_linux.c
+func rawClone(flags _C_ulong, child_stack *byte, ptid *Pid_t, ctid *Pid_t, 
regs unsafe.Pointer) _C_long
+
 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
 // If a dup or exec fails, write the errno error to pipe.
 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
@@ -64,6 +66,7 @@ func forkAndExecInChild(argv0 *byte, arg
        // declarations require heap allocation (e.g., err1).
        var (
                r1     uintptr
+               r2     _C_long
                err1   Errno
                err2   Errno
                nextfd int
@@ -98,20 +101,16 @@ func forkAndExecInChild(argv0 *byte, arg
        // About to call fork.
        // No more allocation or calls of non-assembly functions.
        runtime_BeforeFork()
-       if runtime.GOARCH == "s390x" || runtime.GOARCH == "s390" {
-               r1, _, err1 = RawSyscall6(SYS_CLONE, 0, 
uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0)
-       } else {
-               r1, _, err1 = RawSyscall6(SYS_CLONE, 
uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0)
-       }
-       if err1 != 0 {
+       r2 = rawClone(_C_ulong(uintptr(SIGCHLD)|sys.Cloneflags), nil, nil, nil, 
unsafe.Pointer(nil))
+       if r2 < 0 {
                runtime_AfterFork()
-               return 0, err1
+               return 0, GetErrno()
        }
 
-       if r1 != 0 {
+       if r2 != 0 {
                // parent; return PID
                runtime_AfterFork()
-               pid = int(r1)
+               pid = int(r2)
 
                if sys.UidMappings != nil || sys.GidMappings != nil {
                        Close(p[0])
Index: libgo/mksysinfo.sh
===================================================================
--- libgo/mksysinfo.sh  (revision 240942)
+++ libgo/mksysinfo.sh  (working copy)
@@ -349,8 +349,10 @@ fi
 sizeof_long=`grep '^const ___SIZEOF_LONG__ = ' gen-sysinfo.go | sed -e 's/.*= 
//'`
 if test "$sizeof_long" = "4"; then
   echo "type _C_long int32" >> ${OUT}
+  echo "type _C_ulong uint32" >> ${OUT}
 elif test "$sizeof_long" = "8"; then
   echo "type _C_long int64" >> ${OUT}
+  echo "type _C_ulong uint64" >> ${OUT}
 else
   echo 1>&2 "mksysinfo.sh: could not determine size of long (got $sizeof_long)"
   exit 1

Reply via email to