Hi,
Attached is the updated patch, src_libgo_build.diff, to build gccgo properly on
Debian GNU/Hurd on gcc-7 (7-7.3.0-{8,9,10}) again after the update of glibc to
2.26+
The libgo tests show the following:
=== libgo Summary ===
# of expected passes 119
# of unexpected failures 26
Replacing the stub code of netpoll_gnu.go with a poll-based implementation the
libgo tests improves to:
=== libgo Summary ===
# of expected passes 124
# of unexpected failures 21
The change is reflected in the updated version of src_libgo_go_runtime.diff,
also attached!
Thanks!
Index: gcc-7-7.3.0-8.1/src/libgo/configure.ac
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/configure.ac
+++ gcc-7-7.3.0-8.1/src/libgo/configure.ac
@@ -146,7 +146,7 @@ AC_SUBST(go_include)
# All known GOOS values. This is the union of all operating systems
# supported by the gofrontend and all operating systems supported by
# the gc toolchain.
-ALLGOOS="android darwin dragonfly freebsd irix linux netbsd openbsd plan9 rtems solaris windows"
+ALLGOOS="android darwin dragonfly freebsd irix gnu linux netbsd openbsd plan9 rtems solaris windows"
is_darwin=no
is_freebsd=no
@@ -157,6 +157,7 @@ is_openbsd=no
is_dragonfly=no
is_rtems=no
is_solaris=no
+is_gnu=no
GOOS=unknown
case ${host} in
*-*-darwin*) is_darwin=yes; GOOS=darwin ;;
@@ -168,6 +169,7 @@ case ${host} in
*-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
+ *-*-gnu*) is_gnu=yes; GOOS=gnu ;;
esac
AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes)
AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
@@ -178,6 +180,7 @@ AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $i
AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonfly = yes)
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
+AM_CONDITIONAL(LIBGO_IS_GNU, test $is_gnu = yes)
AM_CONDITIONAL(LIBGO_IS_BSD, test $is_darwin = yes -o $is_dragonfly = yes -o $is_freebsd = yes -o $is_netbsd = yes -o $is_openbsd = yes)
AC_SUBST(GOOS)
AC_SUBST(ALLGOOS)
@@ -838,6 +841,14 @@ main ()
CFLAGS="$CFLAGS_hold"
LIBS="$LIBS_hold"
])
+
+case ${host} in
+ *-*-gnu*)
+ LIBS="$LIBS -lpthread"
+ AC_SUBST(LIBS)
+ ;;
+esac
+
dnl overwrite for the mips* 64bit multilibs, fails on some buildds
if test "$libgo_cv_lib_setcontext_clobbers_tls" = "yes"; then
case "$target" in
Index: gcc-7-7.3.0-8.1/src/libgo/Makefile.am
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/Makefile.am
+++ gcc-7-7.3.0-8.1/src/libgo/Makefile.am
@@ -420,10 +420,14 @@ else
if LIBGO_IS_NETBSD
runtime_getncpu_file = runtime/getncpu-bsd.c
else
+if LIBGO_IS_GNU
+runtime_getncpu_file = runtime/getncpu-gnu.c
+else
runtime_getncpu_file = runtime/getncpu-none.c
endif
endif
endif
+endif
endif
endif
endif
Index: gcc-7-7.3.0-8.1/src/libgo/Makefile.in
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/Makefile.in
+++ gcc-7-7.3.0-8.1/src/libgo/Makefile.in
@@ -183,7 +183,8 @@ libgo_llgo_la_DEPENDENCIES = $(am__DEPEN
@LIBGO_IS_LINUX_FALSE@am__objects_2 = thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_2 = thread-linux.lo
@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-none.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_GNU_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-none.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_GNU_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-gnu.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_4 = getncpu-solaris.lo
@@ -768,7 +769,8 @@ toolexeclibgounicode_DATA = \
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@LIBGO_IS_LINUX_FALSE@runtime_thread_files = runtime/thread-sema.c
@LIBGO_IS_LINUX_TRUE@runtime_thread_files = runtime/thread-linux.c
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_GNU_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_GNU_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-gnu.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_getncpu_file = runtime/getncpu-solaris.c
@@ -1086,7 +1088,7 @@ BUILDGOX = \
$(SHELL) $(srcdir)/mvifdiff.sh $@.tmp `echo $@ | sed -e 's/s-gox/gox/'`
GOTESTFLAGS =
-GOBENCH =
+GOBENCH =
# Check a package.
CHECK = \
@@ -1494,6 +1496,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aeshash.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-bsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-gnu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-irix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-none.Plo@am__quote@
@@ -1979,6 +1982,13 @@ getncpu-none.lo: runtime/getncpu-none.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-none.lo `test -f 'runtime/getncpu-none.c' || echo '$(srcdir)/'`runtime/getncpu-none.c
+getncpu-gnu.lo: runtime/getncpu-gnu.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-gnu.lo -MD -MP -MF $(DEPDIR)/getncpu-gnu.Tpo -c -o getncpu-gnu.lo `test -f 'runtime/getncpu-gnu.c' || echo '$(srcdir)/'`runtime/getncpu-gnu.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/getncpu-gnu.Tpo $(DEPDIR)/getncpu-gnu.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/getncpu-gnu.c' object='getncpu-gnu.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-gnu.lo `test -f 'runtime/getncpu-gnu.c' || echo '$(srcdir)/'`runtime/getncpu-gnu.c
+
getncpu-bsd.lo: runtime/getncpu-bsd.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-bsd.lo -MD -MP -MF $(DEPDIR)/getncpu-bsd.Tpo -c -o getncpu-bsd.lo `test -f 'runtime/getncpu-bsd.c' || echo '$(srcdir)/'`runtime/getncpu-bsd.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/getncpu-bsd.Tpo $(DEPDIR)/getncpu-bsd.Plo
Index: gcc-7-7.3.0-8.1/src/libgo/match.sh
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/match.sh
+++ gcc-7-7.3.0-8.1/src/libgo/match.sh
@@ -113,7 +113,7 @@ for f in $gofiles; do
"") ;;
$goarch) ;;
$goos) ;;
- android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
+ android | darwin | dragonfly | freebsd | gnu | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag1=nonmatchingtag
;;
386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | s390 | s390x | sparc | sparc64)
@@ -125,7 +125,7 @@ for f in $gofiles; do
"") ;;
$goarch) ;;
$goos) ;;
- android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
+ android | darwin | dragonfly | freebsd | gnu | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag2=nonmatchingtag
;;
386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | s390 | s390x | sparc | sparc64)
Index: gcc-7-7.3.0-8.1/src/libgo/mksigtab.sh
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/mksigtab.sh
+++ gcc-7-7.3.0-8.1/src/libgo/mksigtab.sh
@@ -29,7 +29,13 @@ echo ' _SIGINT: {_SigNotify + _SigKil
echo ' _SIGQUIT: {_SigNotify + _SigThrow, "SIGQUIT: quit"},'
echo ' _SIGILL: {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},'
echo ' _SIGTRAP: {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},'
+# Special treatment of SIGABRT for GNU/Hurd
+# /usr/include/i386-gnu/bits/signum.h: #define SIGABRT SIGIOT
+if egrep 'define SIGABRT SIGIOT' gen-sysinfo.go > /dev/null 2>&1; then
+echo ' _SIGIOT: {_SigNotify + _SigThrow, "SIGIOT: abort"},'
+else
echo ' _SIGABRT: {_SigNotify + _SigThrow, "SIGABRT: abort"},'
+fi
echo ' _SIGBUS: {_SigPanic + _SigUnblock, "SIGBUS: bus error"},'
echo ' _SIGFPE: {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},'
echo ' _SIGKILL: {0, "SIGKILL: kill"},'
@@ -77,6 +83,7 @@ checksig _SIGCANCEL ' {_SigSetStack + _S
checksig _SIGXRES ' {_SigNotify, "SIGXRES: resource control exceeded"}'
checksig _SIGJVM1 ' {_SigNotify, "SIGJVM1: reserved signal for Java Virtual Machine"}'
checksig _SIGJVM2 ' {_SigNotify, "SIGJVM2: reserved signal for Java Virtual Machine"}'
+checksig _SIGLOST ' {_SigNotify, "SIGLOST: resource lost (Sun); server died (GNU)"}'
# Special handling of signals 32 and 33 on GNU/Linux systems,
# because they are special to glibc.
@@ -91,6 +98,11 @@ if test -z "$nsig"; then
rtmax=`grep 'const _*SIGRTMAX = [0-9]*$' gen-sysinfo.go | sed -e 's/.* = \([0-9]*\)/\1/'`
if test -n "$rtmax"; then
nsig=`expr $rtmax + 1`
+ elif grep 'const _*SIGRTMAX = [ (]*_*SIGRTMIN[ )]*' gen-sysinfo.go >/dev/null 2>&1; then
+ rtmin=`grep 'const _*SIGRTMIN = [0-9]*$' gen-sysinfo.go | sed -e 's/.* = \([0-9]*\)/\1/'`
+ if test -n "$rtmin"; then
+ nsig=`expr $rtmin + 1`
+ fi
fi
fi
fi
Index: gcc-7-7.3.0-8.1/src/libgo/mksysinfo.sh
===================================================================
--- gcc-7-7.3.0-8.1.orig/src/libgo/mksysinfo.sh
+++ gcc-7-7.3.0-8.1/src/libgo/mksysinfo.sh
@@ -43,8 +43,19 @@ grep -v '^// ' gen-sysinfo.go | \
>> ${OUT}
# The errno constants. These get type Errno.
- egrep '#define E[A-Z0-9_]+ ' errno.i | \
- sed -e 's/^#define \(E[A-Z0-9_]*\) .*$/const \1 = Errno(_\1)/' >> ${OUT}
+egrep '#define E[A-Z0-9_]+ [0-9]' errno.i | \
+ sed -e 's/^#define \(E[A-Z0-9_]*\) .*$/const \1 = Errno(_\1)/' >> ${OUT}
+# Workaround for GNU/Hurd _EMIG_* errors having negative values
+egrep '#define E[A-Z0-9_]+ -[0-9]' errno.i | \
+ sed -e 's/^#define \(E[A-Z0-9_]*\) .*$/const \1 = Errno(-_\1)/' >> ${OUT}
+
+# Special treatment of EWOULDBLOCK for GNU/Hurd
+# /usr/include/i386-gnu/bits/errno.h: #define EWOULDBLOCK EAGAIN
+if egrep '^const _EWOULDBLOCK = _EAGAIN' gen-sysinfo.go > /dev/null 2>&1; then
+ if egrep '^const EAGAIN = Errno\(_EAGAIN\)' ${OUT}; then
+ echo 'const EWOULDBLOCK = Errno(_EAGAIN)' >> ${OUT}
+ fi
+fi
# The O_xxx flags.
egrep '^const _(O|F|FD)_' gen-sysinfo.go | \
@@ -61,6 +72,11 @@ if ! grep '^const F_DUPFD_CLOEXEC' ${OUT
echo "const F_DUPFD_CLOEXEC = 0" >> ${OUT}
fi
+# Special treatment of SYS_IOCTL for GNU/Hurd
+if ! grep '^const SYS_IOCTL' ${OUT} > /dev/null 2>&1; then
+ echo "const SYS_IOCTL = 0" >> ${OUT}
+fi
+
# These flags can be lost on i386 GNU/Linux when using
# -D_FILE_OFFSET_BITS=64, because we see "#define F_SETLK F_SETLK64"
# before we see the definition of F_SETLK64.
@@ -425,6 +441,11 @@ grep '^type _tms ' gen-sysinfo.go | \
# The stat type.
# Prefer largefile variant if available.
+# Special treatment of st_dev for GNU/Hurd
+# /usr/include/i386-gnu/bits/stat.h: #define st_dev st_fsid
+if grep 'define st_dev st_fsid' gen-sysinfo.go > /dev/null 2>&1; then
+ sed -i -e 's/; st_fsid/; st_dev/' gen-sysinfo.go
+fi
stat=`grep '^type _stat64 ' gen-sysinfo.go || true`
if test "$stat" != ""; then
grep '^type _stat64 ' gen-sysinfo.go
Index: gcc-7-7.3.0-8.1/src/libgo/go/runtime/netpoll_gnu.go
===================================================================
--- /dev/null
+++ gcc-7-7.3.0-8.1/src/libgo/go/runtime/netpoll_gnu.go
@@ -0,0 +1,303 @@
+// Copyright 2013 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.
+
+// FIXME: Fake network poller for gnu.
+// This is based on the former libgo/runtime/netpoll_select.c implementation
+// except that it uses poll instead of select and is written in Go.
+// Inspiration was also taken from netpoll_aix.go and netpoll_solaris.go
+
+// +build gnu
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+//From /usr/include/i386-gnu/bits/poll.h
+const _POLLIN = 01 // There is data to read.
+const _POLLPRI = 02 // There is urgent data to read.
+const _POLLOUT = 04 // Writing now will not block.
+const _POLLERR = 010 // Error condition.
+const _POLLHUP = 020 // Hung up.
+const _POLLNVAL = 040 // Invalid polling request.
+
+type pollfd struct {
+ fd int32 // File descriptor to poll.
+ events int16 // Types of events poller cares about.
+ revents int16 // Types of events that actually occurred.
+}
+
+//From /usr/include/x86_64-linux-gnu/sys/poll.h
+//extern poll
+func poll (polldata_array *pollfd, nfds int32, timeout int32) int32
+
+//extern pipe2
+func libc_pipe2(fd *int32, flags int32) int32
+
+var (
+ pipefd [2]int32
+ pollfds int32 = -1
+ nfds int32 = 0
+ rdwake int32
+ wrwake int32
+ fds [207]pollfd
+ data [207]*pollDesc
+ pd *pollDesc
+ pmtx mutex
+ needsUpdate bool
+ b byte
+ err int32 = 0
+)
+
+func netpollinit() {
+
+ ret := libc_pipe2(&pipefd[0], _O_CLOEXEC|_O_NONBLOCK);
+ if ret == -1 {
+ throw("runtime:netpollinit(): failed to create pipe2")
+ }
+
+ rdwake = pipefd[0]
+ wrwake = pipefd[1]
+
+ // Add the read side of the pipe to the pollset.
+ lock(&pmtx)
+ fds[0].fd = int32(rdwake)
+ fds[0].events = int16(_POLLIN)
+ fds[0].revents = int16(0)
+
+// Checks for pd != nil are made in netpoll()
+ data[0] = nil
+ unlock(&pmtx)
+
+ nfds = 1
+ pollfds = 1
+
+ return
+}
+
+func netpolldescriptor() uintptr {
+ // FIXME: see src/libgo/go/os/exec/exec_test.go
+ // Need to return two fds here: wrwake and rdwake
+ return ^uintptr(0)
+}
+
+func fdadd(fd uintptr, events int16, pd *pollDesc) {
+// println("netpollopen:fdadd: nfds =", nfds, "fd =", fd)
+
+ fdfound := false
+ // Omit fds[0].fd = rdwake
+ for i := int32(1); i < nfds; i++ {
+ fdsi := fds[i]
+ if fdsi.fd == int32(fd) {
+ fdfound = true
+ fdsi.events = int16(events)
+ fdsi.revents = int16(0)
+ data[i] = pd
+ break
+ }
+ }
+ // fd not found, add it.
+ if fdfound == false {
+ fds[nfds].fd = int32(fd)
+ fds[nfds].events = int16(events)
+ fds[nfds].revents = int16(0)
+ data[nfds] = pd
+ nfds++
+ }
+
+// for l := int32(0); l < nfds; l++ {
+// println("fds[", l, "].fd =", fds[l].fd)
+// }
+
+ return
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ lock(&pmtx)
+ needsUpdate = true
+ unlock(&pmtx)
+
+ // poll will block so wakeup using wrwake first.
+wrloop1:
+ nwritten := write(uintptr(wrwake), unsafe.Pointer(&b), 1)
+ if nwritten == 0 {
+ println("runtime:netpollopen: write retuned zero, fd =", wrwake)
+ return -1
+ }
+ if nwritten == -1 {
+ err = int32(errno())
+ if err == _EAGAIN {
+ goto wrloop1
+ }
+ println("runtime:netpollopen: write failed fd =", wrwake, "errno =", err)
+ return err
+ }
+
+ // Add fd to the pollset.
+ lock(&pmtx)
+ fdadd(fd, _POLLIN|_POLLOUT, pd)
+ needsUpdate = false
+ unlock(&pmtx)
+
+ return 0
+}
+
+func fdremove(fd uintptr) {
+// println("netpollclose():fdremove() nfds =", nfds, "fd =", fd)
+
+ fdfound := false
+ // Omit fds[0].fd = rdwake
+ j := 1
+ for i := int32(1); i < nfds; i++ {
+ fdsi := fds[i]
+ if fdsi.fd == int32(fd) {
+ fdfound = true
+ fdsi.fd = int32(0)
+ fdsi.events = int16(0)
+ fdsi.revents = int16(0)
+ data[i] = nil
+ } else {
+ fds[j].fd = fdsi.fd
+ fds[j].events = fdsi.events
+ fds[j].revents = int16(0)
+ data[j] = data[i]
+ j++
+ }
+ }
+ nfds--
+ // fd not found, print an error
+ //FIXME: Still output from here
+ if fdfound == false {
+ println("netpollclose:fdremove: fd =", fd, "NOT FOUND")
+ }
+
+// for l := int32(0); l < nfds; l++ {
+// println("fds[", l, "].fd =", fds[l].fd)
+// }
+
+ return
+}
+
+func netpollclose(fd uintptr) int32 {
+ lock(&pmtx)
+ needsUpdate = true
+ unlock(&pmtx)
+
+ // poll will block so wakeup using wrwake first.
+wrloop2:
+ nwritten := write(uintptr(wrwake), unsafe.Pointer(&b), 1)
+ if nwritten == 0 {
+ println("runtime:netpollclose: write retuned zero, fd =", wrwake)
+ return -1
+ }
+ if nwritten == -1 {
+ err = int32(errno())
+ if err == _EAGAIN {
+ goto wrloop2
+ }
+ println("runtime:netpollclose: write failed fd =", wrwake, "errno =", err)
+ return err
+ }
+
+ // Remove fd from the pollset.
+ lock(&pmtx)
+ fdremove(fd)
+ needsUpdate = false
+ unlock(&pmtx)
+
+ return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ throw("runtime:netpollarm() unused")
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+func netpoll(block bool) *g {
+ if pollfds == -1 {
+ return nil
+ }
+
+ timeout := int32(-1)
+ if !block {
+ timeout = 0
+ }
+
+retry:
+ lock(&pmtx)
+ if needsUpdate {
+ unlock(&pmtx)
+ osyield()
+ goto retry
+ }
+ unlock(&pmtx)
+
+ // Note: poll only returns fds with non-zero revents!
+ nfound := poll(&fds[0], nfds, timeout)
+ if nfound == 0 {
+ return nil
+ }
+ if nfound < 0 {
+ err = int32(errno())
+ if err == _EINTR || err == _EAGAIN {
+ goto retry
+ }
+ println("runtime: poll failed errno =", err)
+ throw("runtime: netpoll failed")
+ }
+
+ var mode int32
+ var gp guintptr
+ // We assume that nfound <= nfds
+ for i := int32(0); i < nfds; i++ {
+ fdsi := &fds[i]
+
+ // Skip fds with zero revents as poll does
+ if fdsi.revents == 0 {
+ continue
+ }
+
+ mode = 0
+ if fdsi.revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 {
+ if fdsi.fd == rdwake {
+rdloop:
+ nread := read(fdsi.fd, unsafe.Pointer(&b), 1)
+ // EOF
+ if nread == 0 {
+ println("runtime:netpoll: read returned zero fd =", fdsi.fd)
+ return nil
+ }
+ if nread == -1 {
+ err = int32(errno())
+ if err == _EAGAIN {
+ goto rdloop
+ }
+ println("runtime:netpoll: read failed fd =", fdsi.fd, "errno =", err)
+ return nil
+ }
+ continue
+ }
+ mode += 'r'
+ }
+ if fdsi.revents&(_POLLOUT|_POLLHUP|_POLLERR) != 0 {
+ mode += 'w'
+ }
+ if mode != 0 {
+ lock(&pmtx)
+ pd = data[i]
+ unlock(&pmtx)
+ if pd != nil {
+ netpollready(&gp, pd, mode)
+ }
+ }
+ }
+
+ if block && gp == 0 {
+ goto retry
+ }
+
+ return gp.ptr()
+}
Index: gcc-7-7.3.0-8.1/src/libgo/go/runtime/os_gnu.go
===================================================================
--- /dev/null
+++ gcc-7-7.3.0-8.1/src/libgo/go/runtime/os_gnu.go
@@ -0,0 +1,86 @@
+// Copyright 2011 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.
+
+package runtime
+
+import "unsafe"
+
+type mOS struct {
+ waitsema uintptr // semaphore for parking on locks
+}
+
+//extern malloc
+func libc_malloc(uintptr) unsafe.Pointer
+
+//go:noescape
+//extern sem_init
+func sem_init(sem *_sem_t, pshared int32, value uint32) int32
+
+//go:noescape
+//extern sem_wait
+func sem_wait(sem *_sem_t) int32
+
+//go:noescape
+//extern sem_post
+func sem_post(sem *_sem_t) int32
+
+//go:noescape
+//extern sem_timedwait
+func sem_timedwait(sem *_sem_t, timeout *timespec) int32
+
+//go:nosplit
+func semacreate(mp *m) {
+ if mp.mos.waitsema != 0 {
+ return
+ }
+
+ var sem *_sem_t
+
+ // Call libc's malloc rather than malloc. This will
+ // allocate space on the C heap. We can't call malloc
+ // here because it could cause a deadlock.
+ sem = (*_sem_t)(libc_malloc(unsafe.Sizeof(*sem)))
+ if sem_init(sem, 0, 0) != 0 {
+ throw("sem_init")
+ }
+ mp.mos.waitsema = uintptr(unsafe.Pointer(sem))
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+ _m_ := getg().m
+ if ns >= 0 {
+ var ts timespec
+ ts.set_sec(ns / 1000000000)
+ ts.set_nsec(int32(ns % 1000000000))
+
+ if sem_timedwait((*_sem_t)(unsafe.Pointer(_m_.mos.waitsema)), &ts) != 0 {
+ err := errno()
+ if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
+ return -1
+ }
+ throw("sem_timedwait")
+ }
+ return 0
+ }
+ for {
+ r1 := sem_wait((*_sem_t)(unsafe.Pointer(_m_.mos.waitsema)))
+ if r1 == 0 {
+ break
+ }
+ if errno() == _EINTR {
+ continue
+ }
+ throw("sem_wait")
+ }
+ return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+ if sem_post((*_sem_t)(unsafe.Pointer(mp.mos.waitsema))) != 0 {
+ throw("sem_post")
+ }
+}
+
Index: gcc-7-7.3.0-8.1/src/libgo/go/runtime/signal_gnu.go
===================================================================
--- /dev/null
+++ gcc-7-7.3.0-8.1/src/libgo/go/runtime/signal_gnu.go
@@ -0,0 +1,606 @@
+// Copyright 2012 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 gnu
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+// For gccgo's C code to call:
+//go:linkname initsig runtime.initsig
+//go:linkname crash runtime.crash
+//go:linkname resetcpuprofiler runtime.resetcpuprofiler
+//go:linkname sigtrampgo runtime.sigtrampgo
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+ systemstack(sigpipe)
+}
+
+func signame(sig uint32) string {
+ if sig >= uint32(len(sigtable)) {
+ return ""
+ }
+ return sigtable[sig].name
+}
+
+const (
+ _SIG_DFL uintptr = 0
+ _SIG_IGN uintptr = 1
+)
+
+// Stores the signal handlers registered before Go installed its own.
+// These signal handlers will be invoked in cases where Go doesn't want to
+// handle a particular signal (e.g., signal occurred on a non-Go thread).
+// See sigfwdgo() for more information on when the signals are forwarded.
+//
+// Signal forwarding is currently available only on Darwin and Linux.
+var fwdSig [_NSIG]uintptr
+
+// channels for synchronizing signal mask updates with the signal mask
+// thread
+var (
+ disableSigChan chan uint32
+ enableSigChan chan uint32
+ maskUpdatedChan chan struct{}
+)
+
+func init() {
+ // _NSIG is the number of signals on this operating system.
+ // sigtable should describe what to do for all the possible signals.
+ if len(sigtable) != _NSIG {
+ print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
+ throw("bad sigtable len")
+ }
+}
+
+var signalsOK bool
+
+// Initialize signals.
+// Called by libpreinit so runtime may not be initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func initsig(preinit bool) {
+ if preinit {
+ // preinit is only passed as true if isarchive should be true.
+ isarchive = true
+ }
+
+ if !preinit {
+ // It's now OK for signal handlers to run.
+ signalsOK = true
+ }
+
+ // For c-archive/c-shared this is called by libpreinit with
+ // preinit == true.
+ if (isarchive || islibrary) && !preinit {
+ return
+ }
+
+ for i := uint32(0); i < _NSIG; i++ {
+ t := &sigtable[i]
+ if t.flags == 0 || t.flags&_SigDefault != 0 {
+ continue
+ }
+ fwdSig[i] = getsig(i)
+
+ if !sigInstallGoHandler(i) {
+ // Even if we are not installing a signal handler,
+ // set SA_ONSTACK if necessary.
+ if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
+ setsigstack(i)
+ }
+ continue
+ }
+
+ t.flags |= _SigHandling
+ setsig(i, getSigtramp())
+ }
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func sigInstallGoHandler(sig uint32) bool {
+ // For some signals, we respect an inherited SIG_IGN handler
+ // rather than insist on installing our own default handler.
+ // Even these signals can be fetched using the os/signal package.
+ switch sig {
+ case _SIGHUP, _SIGINT:
+ if fwdSig[sig] == _SIG_IGN {
+ return false
+ }
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigSetStack != 0 {
+ return false
+ }
+
+ // When built using c-archive or c-shared, only install signal
+ // handlers for synchronous signals.
+ if (isarchive || islibrary) && t.flags&_SigPanic == 0 {
+ return false
+ }
+
+ return true
+}
+
+func sigenable(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ ensureSigM()
+ enableSigChan <- sig
+ <-maskUpdatedChan
+ if t.flags&_SigHandling == 0 {
+ t.flags |= _SigHandling
+ fwdSig[sig] = getsig(sig)
+ setsig(sig, getSigtramp())
+ }
+ }
+}
+
+func sigdisable(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ ensureSigM()
+ disableSigChan <- sig
+ <-maskUpdatedChan
+
+ // If initsig does not install a signal handler for a
+ // signal, then to go back to the state before Notify
+ // we should remove the one we installed.
+ if !sigInstallGoHandler(sig) {
+ t.flags &^= _SigHandling
+ setsig(sig, fwdSig[sig])
+ }
+ }
+}
+
+func sigignore(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ t.flags &^= _SigHandling
+ setsig(sig, _SIG_IGN)
+ }
+}
+
+func resetcpuprofiler(hz int32) {
+ var it _itimerval
+ if hz == 0 {
+ setitimer(_ITIMER_PROF, &it, nil)
+ } else {
+ it.it_interval.tv_sec = 0
+ it.it_interval.set_usec(1000000 / hz)
+ it.it_value = it.it_interval
+ setitimer(_ITIMER_PROF, &it, nil)
+ }
+ _g_ := getg()
+ _g_.m.profilehz = hz
+}
+
+func sigpipe() {
+ if sigsend(_SIGPIPE) {
+ return
+ }
+ dieFromSignal(_SIGPIPE)
+}
+
+// sigtrampgo is called from the signal handler function, sigtramp,
+// written in assembly code.
+// This is called by the signal handler, and the world may be stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
+ if sigfwdgo(sig, info, ctx) {
+ return
+ }
+ g := getg()
+ if g == nil {
+ c := sigctxt{info, ctx}
+ if sig == _SIGPROF {
+ _, pc := getSiginfo(info, ctx)
+ sigprofNonGoPC(pc)
+ return
+ }
+ badsignal(uintptr(sig), &c)
+ return
+ }
+
+ setg(g.m.gsignal)
+ sighandler(sig, info, ctx, g)
+ setg(g)
+}
+
+// sigpanic turns a synchronous signal into a run-time panic.
+// If the signal handler sees a synchronous panic, it arranges the
+// stack to look like the function where the signal occurred called
+// sigpanic, sets the signal's PC value to sigpanic, and returns from
+// the signal handler. The effect is that the program will act as
+// though the function that got the signal simply called sigpanic
+// instead.
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ throw("unexpected signal during runtime execution")
+ }
+
+ switch g.sig {
+ case _SIGBUS:
+ if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 {
+ panicmem()
+ }
+ // Support runtime/debug.SetPanicOnFault.
+ if g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGSEGV:
+ if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 {
+ panicmem()
+ }
+ // Support runtime/debug.SetPanicOnFault.
+ if g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGFPE:
+ switch g.sigcode0 {
+ case _FPE_INTDIV:
+ panicdivide()
+ case _FPE_INTOVF:
+ panicoverflow()
+ }
+ panicfloat()
+ }
+
+ if g.sig >= uint32(len(sigtable)) {
+ // can't happen: we looked up g.sig in sigtable to decide to call sigpanic
+ throw("unexpected signal value")
+ }
+ panic(errorString(sigtable[g.sig].name))
+}
+
+// dieFromSignal kills the program with a signal.
+// This provides the expected exit status for the shell.
+// This is only called with fatal signals expected to kill the process.
+//go:nosplit
+//go:nowritebarrierrec
+func dieFromSignal(sig uint32) {
+ setsig(sig, _SIG_DFL)
+ unblocksig(sig)
+ raise(sig)
+
+ // That should have killed us. On some systems, though, raise
+ // sends the signal to the whole process rather than to just
+ // the current thread, which means that the signal may not yet
+ // have been delivered. Give other threads a chance to run and
+ // pick up the signal.
+ osyield()
+ osyield()
+ osyield()
+
+ // If we are still somehow running, just exit with the wrong status.
+ exit(2)
+}
+
+// raisebadsignal is called when a signal is received on a non-Go
+// thread, and the Go program does not want to handle it (that is, the
+// program has not called os/signal.Notify for the signal).
+func raisebadsignal(sig uint32, c *sigctxt) {
+ if sig == _SIGPROF {
+ // Ignore profiling signals that arrive on non-Go threads.
+ return
+ }
+
+ var handler uintptr
+ if sig >= _NSIG {
+ handler = _SIG_DFL
+ } else {
+ handler = fwdSig[sig]
+ }
+
+ // Reset the signal handler and raise the signal.
+ // We are currently running inside a signal handler, so the
+ // signal is blocked. We need to unblock it before raising the
+ // signal, or the signal we raise will be ignored until we return
+ // from the signal handler. We know that the signal was unblocked
+ // before entering the handler, or else we would not have received
+ // it. That means that we don't have to worry about blocking it
+ // again.
+ unblocksig(sig)
+ setsig(sig, handler)
+
+ // If we're linked into a non-Go program we want to try to
+ // avoid modifying the original context in which the signal
+ // was raised. If the handler is the default, we know it
+ // is non-recoverable, so we don't have to worry about
+ // re-installing sighandler. At this point we can just
+ // return and the signal will be re-raised and caught by
+ // the default handler with the correct context.
+ if (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER {
+ return
+ }
+
+ raise(sig)
+
+ // Give the signal a chance to be delivered.
+ // In almost all real cases the program is about to crash,
+ // so sleeping here is not a waste of time.
+ usleep(1000)
+
+ // If the signal didn't cause the program to exit, restore the
+ // Go signal handler and carry on.
+ //
+ // We may receive another instance of the signal before we
+ // restore the Go handler, but that is not so bad: we know
+ // that the Go program has been ignoring the signal.
+ setsig(sig, getSigtramp())
+}
+
+func crash() {
+ if GOOS == "darwin" {
+ // OS X core dumps are linear dumps of the mapped memory,
+ // from the first virtual byte to the last, with zeros in the gaps.
+ // Because of the way we arrange the address space on 64-bit systems,
+ // this means the OS X core file will be >128 GB and even on a zippy
+ // workstation can take OS X well over an hour to write (uninterruptible).
+ // Save users from making that mistake.
+ if sys.PtrSize == 8 {
+ return
+ }
+ }
+
+ dieFromSignal(_SIGIOT)
+}
+
+// ensureSigM starts one global, sleeping thread to make sure at least one thread
+// is available to catch signals enabled for os/signal.
+func ensureSigM() {
+ if maskUpdatedChan != nil {
+ return
+ }
+ maskUpdatedChan = make(chan struct{})
+ disableSigChan = make(chan uint32)
+ enableSigChan = make(chan uint32)
+ go func() {
+ // Signal masks are per-thread, so make sure this goroutine stays on one
+ // thread.
+ LockOSThread()
+ defer UnlockOSThread()
+ // The sigBlocked mask contains the signals not active for os/signal,
+ // initially all signals except the essential. When signal.Notify()/Stop is called,
+ // sigenable/sigdisable in turn notify this thread to update its signal
+ // mask accordingly.
+ var sigBlocked sigset
+ sigfillset(&sigBlocked)
+ for i := range sigtable {
+ if sigtable[i].flags&_SigUnblock != 0 {
+ sigdelset(&sigBlocked, i)
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
+ for {
+ select {
+ case sig := <-enableSigChan:
+ if sig > 0 {
+ sigdelset(&sigBlocked, int(sig))
+ }
+ case sig := <-disableSigChan:
+ if sig > 0 {
+ sigaddset(&sigBlocked, int(sig))
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
+ maskUpdatedChan <- struct{}{}
+ }
+ }()
+}
+
+// This is called when we receive a signal when there is no signal stack.
+// This can only happen if non-Go code calls sigaltstack to disable the
+// signal stack.
+func noSignalStack(sig uint32) {
+ println("signal", sig, "received on thread with no signal stack")
+ throw("non-Go code disabled sigaltstack")
+}
+
+// This is called if we receive a signal when there is a signal stack
+// but we are not on it. This can only happen if non-Go code called
+// sigaction without setting the SS_ONSTACK flag.
+func sigNotOnStack(sig uint32) {
+ println("signal", sig, "received but handler not on signal stack")
+ throw("non-Go code set up signal handler without SA_ONSTACK flag")
+}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+//go:nosplit
+//go:norace
+//go:nowritebarrierrec
+func badsignal(sig uintptr, c *sigctxt) {
+ needm(0)
+ if !sigsend(uint32(sig)) {
+ // A foreign thread received the signal sig, and the
+ // Go code does not want to handle it.
+ raisebadsignal(uint32(sig), c)
+ }
+ dropm()
+}
+
+// Determines if the signal should be handled by Go and if not, forwards the
+// signal to the handler that was installed before Go's. Returns whether the
+// signal was forwarded.
+// This is called by the signal handler, and the world may be stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigfwdgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) bool {
+ if sig >= uint32(len(sigtable)) {
+ return false
+ }
+ fwdFn := fwdSig[sig]
+
+ if !signalsOK {
+ // The only way we can get here is if we are in a
+ // library or archive, we installed a signal handler
+ // at program startup, but the Go runtime has not yet
+ // been initialized.
+ if fwdFn == _SIG_DFL {
+ dieFromSignal(sig)
+ } else {
+ sigfwd(fwdFn, sig, info, ctx)
+ }
+ return true
+ }
+
+ flags := sigtable[sig].flags
+
+ // If there is no handler to forward to, no need to forward.
+ if fwdFn == _SIG_DFL {
+ return false
+ }
+
+ // If we aren't handling the signal, forward it.
+ if flags&_SigHandling == 0 {
+ sigfwd(fwdFn, sig, info, ctx)
+ return true
+ }
+
+ // Only forward synchronous signals.
+ c := sigctxt{info, ctx}
+ if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
+ return false
+ }
+ // Determine if the signal occurred inside Go code. We test that:
+ // (1) we were in a goroutine (i.e., m.curg != nil), and
+ // (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
+ g := getg()
+ if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
+ return false
+ }
+ // Signal not handled by Go, forward it.
+ if fwdFn != _SIG_IGN {
+ sigfwd(fwdFn, sig, info, ctx)
+ }
+ return true
+}
+
+// msigsave saves the current thread's signal mask into mp.sigmask.
+// This is used to preserve the non-Go signal mask when a non-Go
+// thread calls a Go function.
+// This is nosplit and nowritebarrierrec because it is called by needm
+// which may be called on a non-Go thread with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func msigsave(mp *m) {
+ sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
+}
+
+// msigrestore sets the current thread's signal mask to sigmask.
+// This is used to restore the non-Go signal mask when a non-Go thread
+// calls a Go function.
+// This is nosplit and nowritebarrierrec because it is called by dropm
+// after g has been cleared.
+//go:nosplit
+//go:nowritebarrierrec
+func msigrestore(sigmask sigset) {
+ sigprocmask(_SIG_SETMASK, &sigmask, nil)
+}
+
+// sigblock blocks all signals in the current thread's signal mask.
+// This is used to block signals while setting up and tearing down g
+// when a non-Go thread calls a Go function.
+// The OS-specific code is expected to define sigset_all.
+// This is nosplit and nowritebarrierrec because it is called by needm
+// which may be called on a non-Go thread with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func sigblock() {
+ var set sigset
+ sigfillset(&set)
+ sigprocmask(_SIG_SETMASK, &set, nil)
+}
+
+// unblocksig removes sig from the current thread's signal mask.
+// This is nosplit and nowritebarrierrec because it is called from
+// dieFromSignal, which can be called by sigfwdgo while running in the
+// signal handler, on the signal stack, with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func unblocksig(sig uint32) {
+ var set sigset
+ sigemptyset(&set)
+ sigaddset(&set, int(sig))
+ sigprocmask(_SIG_UNBLOCK, &set, nil)
+}
+
+// minitSignals is called when initializing a new m to set the
+// thread's alternate signal stack and signal mask.
+func minitSignals() {
+ minitSignalStack()
+ minitSignalMask()
+}
+
+// minitSignalStack is called when initializing a new m to set the
+// alternate signal stack. If the alternate signal stack is not set
+// for the thread (the normal case) then set the alternate signal
+// stack to the gsignal stack. If the alternate signal stack is set
+// for the thread (the case when a non-Go thread sets the alternate
+// signal stack and then calls a Go function) then set the gsignal
+// stack to the alternate signal stack. Record which choice was made
+// in newSigstack, so that it can be undone in unminit.
+func minitSignalStack() {
+ _g_ := getg()
+ var st _stack_t
+ sigaltstack(nil, &st)
+ if st.ss_flags&_SS_DISABLE != 0 {
+ signalstack(_g_.m.gsignalstack, _g_.m.gsignalstacksize)
+ _g_.m.newSigstack = true
+ } else {
+ _g_.m.newSigstack = false
+ }
+}
+
+// minitSignalMask is called when initializing a new m to set the
+// thread's signal mask. When this is called all signals have been
+// blocked for the thread. This starts with m.sigmask, which was set
+// either from initSigmask for a newly created thread or by calling
+// msigsave if this is a non-Go thread calling a Go function. It
+// removes all essential signals from the mask, thus causing those
+// signals to not be blocked. Then it sets the thread's signal mask.
+// After this is called the thread can receive signals.
+func minitSignalMask() {
+ nmask := getg().m.sigmask
+ for i := range sigtable {
+ if sigtable[i].flags&_SigUnblock != 0 {
+ sigdelset(&nmask, i)
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &nmask, nil)
+}
+
+// unminitSignals is called from dropm, via unminit, to undo the
+// effect of calling minit on a non-Go thread.
+//go:nosplit
+func unminitSignals() {
+ if getg().m.newSigstack {
+ signalstack(nil, 0)
+ }
+}