aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
committerIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
commit8d703821c69062c0cd255787d793e44f1a95d463 (patch)
tree6b1df9cdc36cc47b6164db69a14bc86a63dc77c6 /libgo
parent9cd320ea6572c577cdf17ce1f9ea5230b166af6d (diff)
parentcf392dbdf17e38026f8e3c0e9af7f5b87f63be56 (diff)
downloadgcc-8d703821c69062c0cd255787d793e44f1a95d463.zip
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.gz
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.bz2
Merge from trunk revision cf392dbdf17e38026f8e3c0e9af7f5b87f63be56.
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am68
-rw-r--r--libgo/Makefile.in64
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/config.h.in9
-rwxr-xr-xlibgo/configure2
-rw-r--r--libgo/configure.ac2
-rw-r--r--libgo/go/bytes/bytes.go50
-rw-r--r--libgo/go/cmd/cgo/gcc.go15
-rw-r--r--libgo/go/cmd/cgo/main.go3
-rw-r--r--libgo/go/cmd/cgo/out.go3
-rw-r--r--libgo/go/cmd/go/internal/base/goflags.go17
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo_test.go5
-rw-r--r--libgo/go/cmd/go/internal/version/version.go9
-rw-r--r--libgo/go/cmd/go/internal/work/init.go22
-rw-r--r--libgo/go/cmd/go/testdata/script/version.txt6
-rw-r--r--libgo/go/compress/flate/deflate_test.go57
-rw-r--r--libgo/go/compress/flate/deflatefast.go11
-rw-r--r--libgo/go/go/internal/gccgoimporter/parser.go7
-rw-r--r--libgo/go/internal/bytealg/index_generic.go38
-rw-r--r--libgo/go/internal/poll/fd_unix.go12
-rw-r--r--libgo/go/internal/reflectlite/eqtype.go12
-rw-r--r--libgo/go/internal/reflectlite/eqtype_aix_gccgo.go26
-rw-r--r--libgo/go/internal/reflectlite/type.go8
-rw-r--r--libgo/go/net/http/cgi/host.go6
-rw-r--r--libgo/go/net/http/h2_bundle.go11
-rw-r--r--libgo/go/net/http/request.go2
-rw-r--r--libgo/go/net/http/request_test.go21
-rw-r--r--libgo/go/os/dir_regfile.go2
-rw-r--r--libgo/go/os/user/decls_unix.go10
-rw-r--r--libgo/go/reflect/deepequal.go12
-rw-r--r--libgo/go/reflect/eqtype.go24
-rw-r--r--libgo/go/reflect/eqtype_aix_gccgo.go74
-rw-r--r--libgo/go/reflect/type.go40
-rw-r--r--libgo/go/reflect/value.go14
-rw-r--r--libgo/go/runtime/chan.go22
-rw-r--r--libgo/go/runtime/chan_test.go56
-rw-r--r--libgo/go/runtime/export_test.go24
-rw-r--r--libgo/go/runtime/internal/atomic/atomic_test.go10
-rw-r--r--libgo/go/runtime/mpagealloc.go13
-rw-r--r--libgo/go/runtime/netpoll.go48
-rw-r--r--libgo/go/runtime/netpoll_kqueue.go4
-rw-r--r--libgo/go/runtime/os_aix.go4
-rw-r--r--libgo/go/runtime/os_gccgo.go7
-rw-r--r--libgo/go/runtime/os_hurd.go4
-rw-r--r--libgo/go/runtime/os_linux.go4
-rw-r--r--libgo/go/runtime/os_netbsd.go26
-rw-r--r--libgo/go/runtime/os_solaris.go4
-rw-r--r--libgo/go/runtime/proc.go21
-rw-r--r--libgo/go/runtime/proc_test.go10
-rw-r--r--libgo/go/runtime/runtime2.go9
-rw-r--r--libgo/go/runtime/select.go19
-rw-r--r--libgo/go/runtime/signal_gccgo.go22
-rw-r--r--libgo/go/runtime/signal_unix.go7
-rw-r--r--libgo/go/runtime/stubs2.go2
-rw-r--r--libgo/go/runtime/trace/trace_stack_test.go1
-rw-r--r--libgo/go/syscall/exec_bsd.go2
-rw-r--r--libgo/go/syscall/exec_linux.go2
-rw-r--r--libgo/go/syscall/exec_stubs.go2
-rw-r--r--libgo/go/syscall/exec_unix_test.go45
-rw-r--r--libgo/go/syscall/libcall_aix.go2
-rw-r--r--libgo/go/syscall/libcall_bsd.go110
-rw-r--r--libgo/go/syscall/libcall_bsd_regfile.go2
-rw-r--r--libgo/go/syscall/libcall_bsd_sendfile.go31
-rw-r--r--libgo/go/syscall/libcall_glibc.go3
-rw-r--r--libgo/go/syscall/libcall_hurd.go2
-rw-r--r--libgo/go/syscall/libcall_irix.go2
-rw-r--r--libgo/go/syscall/libcall_linux.go5
-rw-r--r--libgo/go/syscall/libcall_solaris_386.go2
-rw-r--r--libgo/go/syscall/libcall_solaris_amd64.go2
-rw-r--r--libgo/go/syscall/libcall_solaris_sparc.go2
-rw-r--r--libgo/go/syscall/libcall_solaris_sparc64.go2
-rw-r--r--libgo/go/syscall/mksyscall.awk4
-rw-r--r--libgo/go/syscall/route_bsd.go2
-rw-r--r--libgo/go/syscall/socket_bsd.go53
-rw-r--r--libgo/go/syscall/syscall_netbsd.go89
-rw-r--r--libgo/go/testing/benchmark.go18
-rw-r--r--libgo/go/testing/sub_test.go19
-rw-r--r--libgo/go/testing/testing.go138
-rw-r--r--libgo/go/time/zoneinfo_read.go19
-rw-r--r--libgo/go/time/zoneinfo_test.go19
-rw-r--r--libgo/misc/cgo/test/testdata/issue41761.go20
-rw-r--r--libgo/misc/cgo/test/testdata/issue41761a/a.go14
-rw-r--r--libgo/mklinknames.awk46
-rwxr-xr-xlibgo/mksysinfo.sh157
-rw-r--r--libgo/runtime/go-signal.c2
-rw-r--r--libgo/runtime/go-unwind.c14
-rw-r--r--libgo/runtime/go-varargs.c9
-rw-r--r--libgo/sysinfo.c58
89 files changed, 1536 insertions, 344 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index cfbf488..ad239c9 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-9706f510a5e2754595d716bd64be8375997311fb
+0e953add9656c32a788e06438cd7b533e968b7f8
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index e3f08a2..f7a163e 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -574,6 +574,48 @@ s-gccgosizes: Makefile goarch.sh
$(SHELL) $(srcdir)/mvifdiff.sh gccgosizes.go.tmp gccgosizes.go
$(STAMP) $@
+os_linknames.go: s-os_linknames; @true
+s-os_linknames: os-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/os/*.go
+ rm -f os_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=os `cat os-list` > os_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os_linknames.go.tmp os_linknames.go
+ $(STAMP) $@
+
+os-list: s-os-list; @true
+s-os-list: Makefile $(srcdir)/go/os/*.go
+ rm -f os-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/os > os-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os-list.tmp os-list
+ $(STAMP) $@
+
+os_user_linknames.go: s-os_user_linknames; @true
+s-os_user_linknames: os-user-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/os/user/*.go
+ rm -f os_user_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=user `cat os-user-list` > os_user_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os_user_linknames.go.tmp os_user_linknames.go
+ $(STAMP) $@
+
+os-user-list: s-os-user-list; @true
+s-os-user-list: Makefile $(srcdir)/go/os/user/*.go
+ rm -f os-user-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/os/user > os-user-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os-user-list.tmp os-user-list
+ $(STAMP) $@
+
+runtime_linknames.go: s-runtime_linknames; @true
+s-runtime_linknames: runtime-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/runtime/*.go
+ rm -f runtime_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=runtime `cat runtime-list` > runtime_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh runtime_linknames.go.tmp runtime_linknames.go
+ $(STAMP) $@
+
+runtime-list: s-runtime-list; @true
+s-runtime-list: Makefile $(srcdir)/go/runtime/*.go
+ rm -f runtime-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/runtime > runtime-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh runtime-list.tmp runtime-list
+ $(STAMP) $@
+
runtime_sysinfo.go: s-runtime_sysinfo; @true
s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
GOARCH=$(GOARCH) GOOS=$(GOOS) $(SHELL) $(srcdir)/mkrsysinfo.sh
@@ -654,6 +696,13 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/mvifdiff.sh syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
+syscall_linknames.go: s-syscall_linknames; @true
+s-syscall_linknames: libcalls.go gen-sysinfo.go $(srcdir)/mklinknames.awk
+ rm -f syscall_linknames.go.tmp
+ $(AWK) -v package=syscall -f $(srcdir)/mklinknames.awk libcalls.go > syscall_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh syscall_linknames.go.tmp syscall_linknames.go
+ $(STAMP) $@
+
SYSINFO_FLAGS = \
$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(OSCFLAGS) -O
@@ -940,8 +989,8 @@ $(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package)))
math_lo_GOCFLAGS = $(MATH_FLAG)
math_check_GOCFLAGS = $(MATH_FLAG)
-# Add the generated file runtime_sysinfo.go to the runtime package.
-extra_go_files_runtime = runtime_sysinfo.go sigtab.go
+# Add generated files to the runtime package.
+extra_go_files_runtime = runtime_linknames.go runtime_sysinfo.go sigtab.go
runtime.lo.dep: $(extra_go_files_runtime)
# Add generated files to the syscall package.
@@ -949,6 +998,7 @@ extra_go_files_syscall = \
libcalls.go \
sysinfo.go \
syscall_arch.go \
+ syscall_linknames.go \
$(syscall_epoll_file)
syscall.lo.dep: $(extra_go_files_syscall)
@@ -973,6 +1023,12 @@ endif
# Also use -fno-inline to get better results from the memory profiler.
runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
+if LIBGO_IS_AIX
+# reflect tests must be done with -static-libgo. Otherwize,
+# there will be a duplication of the canonicalization map.
+reflect_check_GOCFLAGS = -static-libgo -Wl,-bbigtoc
+endif
+
if HAVE_STATIC_LINK
# Use -static for the syscall tests if possible, because otherwise when
# running as root the re-execs ignore LD_LIBRARY_PATH.
@@ -1000,6 +1056,12 @@ cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi)
extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
+extra_go_files_os = os_linknames.go
+os.lo.dep: $(extra_go_files_os)
+
+extra_go_files_os_user = os_user_linknames.go
+os/user.lo.dep: $(extra_go_files_os_user)
+
extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a
extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
@@ -1090,7 +1152,7 @@ if LIBGO_IS_BSD
$(eval $(call PACKAGE_template,golang.org/x/net/route))
golangorg_x_net_route_lo = \
- golang.org/net/route.lo
+ golang.org/x/net/route.lo
endif
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 18b1a06..ba202a6 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -1085,14 +1085,15 @@ CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
math_lo_GOCFLAGS = $(MATH_FLAG)
math_check_GOCFLAGS = $(MATH_FLAG)
-# Add the generated file runtime_sysinfo.go to the runtime package.
-extra_go_files_runtime = runtime_sysinfo.go sigtab.go
+# Add generated files to the runtime package.
+extra_go_files_runtime = runtime_linknames.go runtime_sysinfo.go sigtab.go
# Add generated files to the syscall package.
extra_go_files_syscall = \
libcalls.go \
sysinfo.go \
syscall_arch.go \
+ syscall_linknames.go \
$(syscall_epoll_file)
@@ -1114,6 +1115,10 @@ runtime_internal_sys_lo_check_GOCFLAGS = -fgo-compiling-runtime
# Also use -fno-inline to get better results from the memory profiler.
runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
+# reflect tests must be done with -static-libgo. Otherwize,
+# there will be a duplication of the canonicalization map.
+@LIBGO_IS_AIX_TRUE@reflect_check_GOCFLAGS = -static-libgo -Wl,-bbigtoc
+
# Use -static for the syscall tests if possible, because otherwise when
# running as root the re-execs ignore LD_LIBRARY_PATH.
@HAVE_STATIC_LINK_TRUE@syscall_check_GOCFLAGS = -static
@@ -1124,6 +1129,8 @@ extra_go_files_internal_goroot = zstdpkglist.go
extra_go_files_go_types = gccgosizes.go
extra_go_files_cmd_internal_objabi = objabi.go
extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
+extra_go_files_os = os_linknames.go
+extra_go_files_os_user = os_user_linknames.go
extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a
extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
@@ -1149,7 +1156,7 @@ extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a
@HAVE_STAT_TIMESPEC_TRUE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = --tag=solaristag
@LIBGO_IS_SOLARIS_FALSE@matchargs_os =
@LIBGO_IS_BSD_TRUE@golangorg_x_net_route_lo = \
-@LIBGO_IS_BSD_TRUE@ golang.org/net/route.lo
+@LIBGO_IS_BSD_TRUE@ golang.org/x/net/route.lo
@LIBGO_IS_SOLARIS_TRUE@golangorg_x_net_lif_lo = \
@LIBGO_IS_SOLARIS_TRUE@ golang.org/x/net/lif.lo
@@ -2744,6 +2751,48 @@ s-gccgosizes: Makefile goarch.sh
$(SHELL) $(srcdir)/mvifdiff.sh gccgosizes.go.tmp gccgosizes.go
$(STAMP) $@
+os_linknames.go: s-os_linknames; @true
+s-os_linknames: os-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/os/*.go
+ rm -f os_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=os `cat os-list` > os_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os_linknames.go.tmp os_linknames.go
+ $(STAMP) $@
+
+os-list: s-os-list; @true
+s-os-list: Makefile $(srcdir)/go/os/*.go
+ rm -f os-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/os > os-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os-list.tmp os-list
+ $(STAMP) $@
+
+os_user_linknames.go: s-os_user_linknames; @true
+s-os_user_linknames: os-user-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/os/user/*.go
+ rm -f os_user_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=user `cat os-user-list` > os_user_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os_user_linknames.go.tmp os_user_linknames.go
+ $(STAMP) $@
+
+os-user-list: s-os-user-list; @true
+s-os-user-list: Makefile $(srcdir)/go/os/user/*.go
+ rm -f os-user-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/os/user > os-user-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh os-user-list.tmp os-user-list
+ $(STAMP) $@
+
+runtime_linknames.go: s-runtime_linknames; @true
+s-runtime_linknames: runtime-list gen-sysinfo.go $(srcdir)/mklinknames.awk $(srcdir)/go/runtime/*.go
+ rm -f runtime_linknames.go.tmp
+ $(AWK) -f $(srcdir)/mklinknames.awk -v package=runtime `cat runtime-list` > runtime_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh runtime_linknames.go.tmp runtime_linknames.go
+ $(STAMP) $@
+
+runtime-list: s-runtime-list; @true
+s-runtime-list: Makefile $(srcdir)/go/runtime/*.go
+ rm -f runtime-list.tmp
+ $(SHELL) $(srcdir)/match.sh --goarch=$(GOARCH) --goos=$(GOOS) --srcdir=$(srcdir)/go/runtime > runtime-list.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh runtime-list.tmp runtime-list
+ $(STAMP) $@
+
runtime_sysinfo.go: s-runtime_sysinfo; @true
s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
GOARCH=$(GOARCH) GOOS=$(GOOS) $(SHELL) $(srcdir)/mkrsysinfo.sh
@@ -2812,6 +2861,13 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/mvifdiff.sh syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
+syscall_linknames.go: s-syscall_linknames; @true
+s-syscall_linknames: libcalls.go gen-sysinfo.go $(srcdir)/mklinknames.awk
+ rm -f syscall_linknames.go.tmp
+ $(AWK) -v package=syscall -f $(srcdir)/mklinknames.awk libcalls.go > syscall_linknames.go.tmp
+ $(SHELL) $(srcdir)/mvifdiff.sh syscall_linknames.go.tmp syscall_linknames.go
+ $(STAMP) $@
+
gen-sysinfo.go: s-gen-sysinfo; @true
s-gen-sysinfo: $(srcdir)/sysinfo.c config.h
$(CC) $(SYSINFO_FLAGS) -fdump-go-spec=tmp-gen-sysinfo.go -std=gnu99 -S -o sysinfo.s $(srcdir)/sysinfo.c
@@ -2914,6 +2970,8 @@ internal/goroot.lo.dep: $(extra_go_files_internal_goroot)
go/types.lo.dep: $(extra_go_files_go_types)
cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi)
cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
+os.lo.dep: $(extra_go_files_os)
+os/user.lo.dep: $(extra_go_files_os_user)
# FIXME: The following C files may as well move to the runtime
# directory and be treated like other C files.
diff --git a/libgo/VERSION b/libgo/VERSION
index c19def3..baff222 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.15.2
+go1.15.4
diff --git a/libgo/config.h.in b/libgo/config.h.in
index bbb2516..1126790 100644
--- a/libgo/config.h.in
+++ b/libgo/config.h.in
@@ -138,6 +138,9 @@
/* Define to 1 if you have the `logl' function. */
#undef HAVE_LOGL
+/* Define to 1 if you have the <lwp.h> header file. */
+#undef HAVE_LWP_H
+
/* Define to 1 if you have the `matherr' function. */
#undef HAVE_MATHERR
@@ -174,6 +177,9 @@
/* Define to 1 if you have the <netpacket/packet.h> header file. */
#undef HAVE_NETPACKET_PACKET_H
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#undef HAVE_NET_BPF_H
+
/* Define to 1 if you have the <net/if_arp.h> header file. */
#undef HAVE_NET_IF_ARP_H
@@ -294,6 +300,9 @@
/* Define to 1 if you have the <sys/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_H
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
/* Define to 1 if you have the <sys/sysinfo.h> header file. */
#undef HAVE_SYS_SYSINFO_H
diff --git a/libgo/configure b/libgo/configure
index 792ac6f..e7379f8 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -15202,7 +15202,7 @@ $as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
fi
-for ac_header in port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
+for ac_header in port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/sysctl.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/bpf.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h lwp.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 9a10d33..80537f5 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -580,7 +580,7 @@ AC_C_BIGENDIAN
GCC_CHECK_UNWIND_GETIPINFO
-AC_CHECK_HEADERS(port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
+AC_CHECK_HEADERS(port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/sysctl.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/bpf.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h lwp.h)
AC_CHECK_HEADERS([netinet/icmp6.h], [], [],
[#include <netinet/in.h>
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index aa07b9f..ce52649f1 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -227,19 +227,26 @@ func IndexAny(s []byte, chars string) int {
continue
}
r, width = utf8.DecodeRune(s[i:])
- if r == utf8.RuneError {
- for _, r = range chars {
- if r == utf8.RuneError {
+ if r != utf8.RuneError {
+ // r is 2 to 4 bytes
+ if len(chars) == width {
+ if chars == string(r) {
return i
}
+ continue
+ }
+ // Use bytealg.IndexString for performance if available.
+ if bytealg.MaxLen >= width {
+ if bytealg.IndexString(chars, string(r)) >= 0 {
+ return i
+ }
+ continue
}
- continue
}
- // r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes
- // package should not import the strings package, use bytealg.IndexString
- // instead. And this does not seem to lose much performance.
- if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 {
- return i
+ for _, ch := range chars {
+ if r == ch {
+ return i
+ }
}
}
return -1
@@ -304,19 +311,26 @@ func LastIndexAny(s []byte, chars string) int {
}
r, size := utf8.DecodeLastRune(s[:i])
i -= size
- if r == utf8.RuneError {
- for _, r = range chars {
- if r == utf8.RuneError {
+ if r != utf8.RuneError {
+ // r is 2 to 4 bytes
+ if len(chars) == size {
+ if chars == string(r) {
return i
}
+ continue
+ }
+ // Use bytealg.IndexString for performance if available.
+ if bytealg.MaxLen >= size {
+ if bytealg.IndexString(chars, string(r)) >= 0 {
+ return i
+ }
+ continue
}
- continue
}
- // r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes
- // package should not import the strings package, use bytealg.IndexString
- // instead. And this does not seem to lose much performance.
- if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 {
- return i
+ for _, ch := range chars {
+ if r == ch {
+ return i
+ }
}
}
return -1
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index f774cbb..37bafcf 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -2459,6 +2459,18 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
tt := *t
tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
tt.Go = c.Ident("struct{}")
+ if dt.Kind == "struct" {
+ // We don't know what the representation of this struct is, so don't let
+ // anyone allocate one on the Go side. As a side effect of this annotation,
+ // pointers to this type will not be considered pointers in Go. They won't
+ // get writebarrier-ed or adjusted during a stack copy. This should handle
+ // all the cases badPointerTypedef used to handle, but hopefully will
+ // continue to work going forward without any more need for cgo changes.
+ tt.NotInHeap = true
+ // TODO: we should probably do the same for unions. Unions can't live
+ // on the Go heap, right? It currently doesn't work for unions because
+ // they are defined as a type alias for struct{}, not a defined type.
+ }
typedef[name.Name] = &tt
break
}
@@ -2529,6 +2541,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
}
t.Go = name
t.BadPointer = sub.BadPointer
+ t.NotInHeap = sub.NotInHeap
if unionWithPointer[sub.Go] {
unionWithPointer[t.Go] = true
}
@@ -2539,6 +2552,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
tt := *t
tt.Go = sub.Go
tt.BadPointer = sub.BadPointer
+ tt.NotInHeap = sub.NotInHeap
typedef[name.Name] = &tt
}
@@ -3047,6 +3061,7 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
// non-pointers in this type.
// TODO: Currently our best solution is to find these manually and list them as
// they come up. A better solution is desired.
+// Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file.
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
if c.badCFType(dt) {
return true
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
index 6de6d69..7fc2508 100644
--- a/libgo/go/cmd/cgo/main.go
+++ b/libgo/go/cmd/cgo/main.go
@@ -151,7 +151,8 @@ type Type struct {
Go ast.Expr
EnumValues map[string]int64
Typedef string
- BadPointer bool
+ BadPointer bool // this pointer type should be represented as a uintptr (deprecated)
+ NotInHeap bool // this type should have a go:notinheap annotation
}
// A FuncType collects information about a function type in both the C and Go worlds.
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
index 1d23fc1..dd03f7d 100644
--- a/libgo/go/cmd/cgo/out.go
+++ b/libgo/go/cmd/cgo/out.go
@@ -113,6 +113,9 @@ func (p *Package) writeDefs() {
sort.Strings(typedefNames)
for _, name := range typedefNames {
def := typedef[name]
+ if def.NotInHeap {
+ fmt.Fprintf(fgo2, "//go:notinheap\n")
+ }
fmt.Fprintf(fgo2, "type %s ", name)
// We don't have source info for these types, so write them out without source info.
// Otherwise types would look like:
diff --git a/libgo/go/cmd/go/internal/base/goflags.go b/libgo/go/cmd/go/internal/base/goflags.go
index 3476613..f29cc3c 100644
--- a/libgo/go/cmd/go/internal/base/goflags.go
+++ b/libgo/go/cmd/go/internal/base/goflags.go
@@ -153,3 +153,20 @@ func SetFromGOFLAGS(flags *flag.FlagSet) {
}
}
}
+
+// InGOFLAGS returns whether GOFLAGS contains the given flag, such as "-mod".
+func InGOFLAGS(flag string) bool {
+ for _, goflag := range GOFLAGS() {
+ name := goflag
+ if strings.HasPrefix(name, "--") {
+ name = name[1:]
+ }
+ if i := strings.Index(name, "="); i >= 0 {
+ name = name[:i]
+ }
+ if name == flag {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
index f69c193b..9a0cd7d 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
@@ -657,11 +657,6 @@ var codeRepoVersionsTests = []struct {
},
{
vcs: "git",
- path: "gopkg.in/russross/blackfriday.v2",
- versions: []string{"v2.0.0", "v2.0.1"},
- },
- {
- vcs: "git",
path: "gopkg.in/natefinch/lumberjack.v2",
versions: []string{"v2.0.0"},
},
diff --git a/libgo/go/cmd/go/internal/version/version.go b/libgo/go/cmd/go/internal/version/version.go
index ac2ae50..a5b1365 100644
--- a/libgo/go/cmd/go/internal/version/version.go
+++ b/libgo/go/cmd/go/internal/version/version.go
@@ -53,7 +53,14 @@ var (
func runVersion(cmd *base.Command, args []string) {
if len(args) == 0 {
- if *versionM || *versionV {
+ // If any of this command's flags were passed explicitly, error
+ // out, because they only make sense with arguments.
+ //
+ // Don't error if the flags came from GOFLAGS, since that can be
+ // a reasonable use case. For example, imagine GOFLAGS=-v to
+ // turn "verbose mode" on for all Go commands, which should not
+ // break "go version".
+ if (!base.InGOFLAGS("-m") && *versionM) || (!base.InGOFLAGS("-v") && *versionV) {
fmt.Fprintf(os.Stderr, "go version: flags can only be used with arguments\n")
base.SetExitStatus(2)
return
diff --git a/libgo/go/cmd/go/internal/work/init.go b/libgo/go/cmd/go/internal/work/init.go
index dad3b10..c168364 100644
--- a/libgo/go/cmd/go/internal/work/init.go
+++ b/libgo/go/cmd/go/internal/work/init.go
@@ -254,34 +254,18 @@ func buildModeInit() {
case "":
// ok
case "readonly", "vendor", "mod":
- if !cfg.ModulesEnabled && !inGOFLAGS("-mod") {
+ if !cfg.ModulesEnabled && !base.InGOFLAGS("-mod") {
base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod)
}
default:
base.Fatalf("-mod=%s not supported (can be '', 'mod', 'readonly', or 'vendor')", cfg.BuildMod)
}
if !cfg.ModulesEnabled {
- if cfg.ModCacheRW && !inGOFLAGS("-modcacherw") {
+ if cfg.ModCacheRW && !base.InGOFLAGS("-modcacherw") {
base.Fatalf("build flag -modcacherw only valid when using modules")
}
- if cfg.ModFile != "" && !inGOFLAGS("-mod") {
+ if cfg.ModFile != "" && !base.InGOFLAGS("-mod") {
base.Fatalf("build flag -modfile only valid when using modules")
}
}
}
-
-func inGOFLAGS(flag string) bool {
- for _, goflag := range base.GOFLAGS() {
- name := goflag
- if strings.HasPrefix(name, "--") {
- name = name[1:]
- }
- if i := strings.Index(name, "="); i >= 0 {
- name = name[:i]
- }
- if name == flag {
- return true
- }
- }
- return false
-}
diff --git a/libgo/go/cmd/go/testdata/script/version.txt b/libgo/go/cmd/go/testdata/script/version.txt
index 0123ac6..87cb6be 100644
--- a/libgo/go/cmd/go/testdata/script/version.txt
+++ b/libgo/go/cmd/go/testdata/script/version.txt
@@ -9,6 +9,12 @@ stderr 'with arguments'
! go version -v
stderr 'with arguments'
+# Neither of the two flags above should be an issue via GOFLAGS.
+env GOFLAGS='-m -v'
+go version
+stdout '^go version'
+env GOFLAGS=
+
env GO111MODULE=on
# Skip the builds below if we are running in short mode.
[short] skip
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index 3362d25..8a22b8e 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -11,6 +11,7 @@ import (
"internal/testenv"
"io"
"io/ioutil"
+ "math/rand"
"reflect"
"runtime/debug"
"sync"
@@ -896,6 +897,62 @@ func TestBestSpeedMaxMatchOffset(t *testing.T) {
}
}
+func TestBestSpeedShiftOffsets(t *testing.T) {
+ // Test if shiftoffsets properly preserves matches and resets out-of-range matches
+ // seen in https://github.com/golang/go/issues/4142
+ enc := newDeflateFast()
+
+ // testData may not generate internal matches.
+ testData := make([]byte, 32)
+ rng := rand.New(rand.NewSource(0))
+ for i := range testData {
+ testData[i] = byte(rng.Uint32())
+ }
+
+ // Encode the testdata with clean state.
+ // Second part should pick up matches from the first block.
+ wantFirstTokens := len(enc.encode(nil, testData))
+ wantSecondTokens := len(enc.encode(nil, testData))
+
+ if wantFirstTokens <= wantSecondTokens {
+ t.Fatalf("test needs matches between inputs to be generated")
+ }
+ // Forward the current indicator to before wraparound.
+ enc.cur = bufferReset - int32(len(testData))
+
+ // Part 1 before wrap, should match clean state.
+ got := len(enc.encode(nil, testData))
+ if wantFirstTokens != got {
+ t.Errorf("got %d, want %d tokens", got, wantFirstTokens)
+ }
+
+ // Verify we are about to wrap.
+ if enc.cur != bufferReset {
+ t.Errorf("got %d, want e.cur to be at bufferReset (%d)", enc.cur, bufferReset)
+ }
+
+ // Part 2 should match clean state as well even if wrapped.
+ got = len(enc.encode(nil, testData))
+ if wantSecondTokens != got {
+ t.Errorf("got %d, want %d token", got, wantSecondTokens)
+ }
+
+ // Verify that we wrapped.
+ if enc.cur >= bufferReset {
+ t.Errorf("want e.cur to be < bufferReset (%d), got %d", bufferReset, enc.cur)
+ }
+
+ // Forward the current buffer, leaving the matches at the bottom.
+ enc.cur = bufferReset
+ enc.shiftOffsets()
+
+ // Ensure that no matches were picked up.
+ got = len(enc.encode(nil, testData))
+ if wantFirstTokens != got {
+ t.Errorf("got %d, want %d tokens", got, wantFirstTokens)
+ }
+}
+
func TestMaxStackSize(t *testing.T) {
// This test must not run in parallel with other tests as debug.SetMaxStack
// affects all goroutines.
diff --git a/libgo/go/compress/flate/deflatefast.go b/libgo/go/compress/flate/deflatefast.go
index 24f8be9..6aa439f 100644
--- a/libgo/go/compress/flate/deflatefast.go
+++ b/libgo/go/compress/flate/deflatefast.go
@@ -270,6 +270,7 @@ func (e *deflateFast) matchLen(s, t int32, src []byte) int32 {
func (e *deflateFast) reset() {
e.prev = e.prev[:0]
// Bump the offset, so all matches will fail distance check.
+ // Nothing should be >= e.cur in the table.
e.cur += maxMatchOffset
// Protect against e.cur wraparound.
@@ -288,17 +289,21 @@ func (e *deflateFast) shiftOffsets() {
for i := range e.table[:] {
e.table[i] = tableEntry{}
}
- e.cur = maxMatchOffset
+ e.cur = maxMatchOffset + 1
return
}
// Shift down everything in the table that isn't already too far away.
for i := range e.table[:] {
- v := e.table[i].offset - e.cur + maxMatchOffset
+ v := e.table[i].offset - e.cur + maxMatchOffset + 1
if v < 0 {
+ // We want to reset e.cur to maxMatchOffset + 1, so we need to shift
+ // all table entries down by (e.cur - (maxMatchOffset + 1)).
+ // Because we ignore matches > maxMatchOffset, we can cap
+ // any negative offsets at 0.
v = 0
}
e.table[i].offset = v
}
- e.cur = maxMatchOffset
+ e.cur = maxMatchOffset + 1
}
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go
index e2ef33f..1b1d07d 100644
--- a/libgo/go/go/internal/gccgoimporter/parser.go
+++ b/libgo/go/go/internal/gccgoimporter/parser.go
@@ -517,6 +517,13 @@ func (p *parser) parseNamedType(nlist []interface{}) types.Type {
p.errorf("%v has nil type", obj)
}
+ if p.tok == scanner.Ident && p.lit == "notinheap" {
+ p.next()
+ // The go/types package has no way of recording that
+ // this type is marked notinheap. Presumably no user
+ // of this package actually cares.
+ }
+
// type alias
if p.tok == '=' {
p.next()
diff --git a/libgo/go/internal/bytealg/index_generic.go b/libgo/go/internal/bytealg/index_generic.go
index 3dc1c6b..c595c23 100644
--- a/libgo/go/internal/bytealg/index_generic.go
+++ b/libgo/go/internal/bytealg/index_generic.go
@@ -17,42 +17,8 @@ func Index(a, b []byte) int {
// IndexString returns the index of the first instance of b in a, or -1 if b is not present in a.
// Requires 2 <= len(b) <= MaxLen.
-func IndexString(s, substr string) int {
- // This is a partial copy of strings.Index, here because bytes.IndexAny and bytes.LastIndexAny
- // call bytealg.IndexString. Some platforms have an optimized assembly version of this function.
- // This implementation is used for those that do not. Although the pure Go implementation here
- // works for the case of len(b) > MaxLen, we do not require that its assembly implementation also
- // supports the case of len(b) > MaxLen. And we do not guarantee that this function supports the
- // case of len(b) > MaxLen.
- n := len(substr)
- c0 := substr[0]
- c1 := substr[1]
- i := 0
- t := len(s) - n + 1
- fails := 0
- for i < t {
- if s[i] != c0 {
- o := IndexByteString(s[i:t], c0)
- if o < 0 {
- return -1
- }
- i += o
- }
- if s[i+1] == c1 && s[i:i+n] == substr {
- return i
- }
- i++
- fails++
- if fails >= 4+i>>4 && i < t {
- // See comment in src/bytes/bytes.go.
- j := IndexRabinKarp(s[i:], substr)
- if j < 0 {
- return -1
- }
- return i + j
- }
- }
- return -1
+func IndexString(a, b string) int {
+ panic("unimplemented")
}
// Cutover reports the number of failures of IndexByte we should tolerate
diff --git a/libgo/go/internal/poll/fd_unix.go b/libgo/go/internal/poll/fd_unix.go
index f177ccf..10cf173 100644
--- a/libgo/go/internal/poll/fd_unix.go
+++ b/libgo/go/internal/poll/fd_unix.go
@@ -152,7 +152,7 @@ func (fd *FD) Read(p []byte) (int, error) {
p = p[:maxRW]
}
for {
- n, err := ignoringEINTR(syscall.Read, fd.Sysfd, p)
+ n, err := ignoringEINTR(func() (int, error) { return syscall.Read(fd.Sysfd, p) })
if err != nil {
n = 0
if err == syscall.EAGAIN && fd.pd.pollable() {
@@ -264,7 +264,7 @@ func (fd *FD) Write(p []byte) (int, error) {
if fd.IsStream && max-nn > maxRW {
max = nn + maxRW
}
- n, err := ignoringEINTR(syscall.Write, fd.Sysfd, p[nn:max])
+ n, err := ignoringEINTR(func() (int, error) { return syscall.Write(fd.Sysfd, p[nn:max]) })
if n > 0 {
nn += n
}
@@ -423,7 +423,7 @@ func (fd *FD) ReadDirent(buf []byte) (int, error) {
}
defer fd.decref()
for {
- n, err := ignoringEINTR(syscall.ReadDirent, fd.Sysfd, buf)
+ n, err := ignoringEINTR(func() (int, error) { return syscall.ReadDirent(fd.Sysfd, buf) })
if err != nil {
n = 0
if err == syscall.EAGAIN && fd.pd.pollable() {
@@ -514,7 +514,7 @@ func (fd *FD) WriteOnce(p []byte) (int, error) {
return 0, err
}
defer fd.writeUnlock()
- return ignoringEINTR(syscall.Write, fd.Sysfd, p)
+ return ignoringEINTR(func() (int, error) { return syscall.Write(fd.Sysfd, p) })
}
// RawRead invokes the user-defined function f for a read operation.
@@ -562,9 +562,9 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error {
// installed without setting SA_RESTART. None of these are the common case,
// but there are enough of them that it seems that we can't avoid
// an EINTR loop.
-func ignoringEINTR(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) {
+func ignoringEINTR(fn func() (int, error)) (int, error) {
for {
- n, err := fn(fd, p)
+ n, err := fn()
if err != syscall.EINTR {
return n, err
}
diff --git a/libgo/go/internal/reflectlite/eqtype.go b/libgo/go/internal/reflectlite/eqtype.go
new file mode 100644
index 0000000..a03cf1c
--- /dev/null
+++ b/libgo/go/internal/reflectlite/eqtype.go
@@ -0,0 +1,12 @@
+// Copyright 2020 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 !aix !gccgo
+
+package reflectlite
+
+// rtypeEqual returns true if both types are identical.
+func rtypeEqual(t1, t2 *rtype) bool {
+ return t1 == t2
+}
diff --git a/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go b/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go
new file mode 100644
index 0000000..38b507f
--- /dev/null
+++ b/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go
@@ -0,0 +1,26 @@
+// Copyright 2020 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 aix,gccgo
+
+// AIX linker isn't able to merge identical type descriptors coming from
+// different objects. Thus, two rtypes might have two different pointers
+// even if they are the same. Thus, instead of pointer equality, string
+// field is checked.
+
+package reflectlite
+
+// rtypeEqual returns true if both types are identical.
+func rtypeEqual(t1, t2 *rtype) bool {
+ switch {
+ case t1 == t2:
+ return true
+ case t1 == nil || t2 == nil:
+ return false
+ case t1.kind != t2.kind || t1.hash != t2.hash:
+ return false
+ default:
+ return t1.String() == t2.String()
+ }
+}
diff --git a/libgo/go/internal/reflectlite/type.go b/libgo/go/internal/reflectlite/type.go
index e700a55..1609a06 100644
--- a/libgo/go/internal/reflectlite/type.go
+++ b/libgo/go/internal/reflectlite/type.go
@@ -539,7 +539,7 @@ func implements(T, V *rtype) bool {
for j := 0; j < len(v.methods); j++ {
tm := &t.methods[i]
vm := &v.methods[j]
- if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() {
+ if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && rtypeEqual(toType(vm.typ).common(), toType(tm.typ).common()) {
if i++; i >= len(t.methods) {
return true
}
@@ -556,7 +556,7 @@ func implements(T, V *rtype) bool {
for j := 0; j < len(v.methods); j++ {
tm := &t.methods[i]
vm := &v.methods[j]
- if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() {
+ if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && rtypeEqual(toType(vm.mtyp).common(), toType(tm.typ).common()) {
if i++; i >= len(t.methods) {
return true
}
@@ -572,7 +572,7 @@ func implements(T, V *rtype) bool {
// and the ideal constant rules (no ideal constants at run time).
func directlyAssignable(T, V *rtype) bool {
// x's type V is identical to T?
- if T == V {
+ if rtypeEqual(T, V) {
return true
}
@@ -599,7 +599,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool {
}
func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
- if T == V {
+ if rtypeEqual(T, V) {
return true
}
diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go
index 863f406..eff67ca 100644
--- a/libgo/go/net/http/cgi/host.go
+++ b/libgo/go/net/http/cgi/host.go
@@ -37,15 +37,15 @@ var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
var osDefaultInheritEnv = func() []string {
switch runtime.GOOS {
- case "darwin":
+ case "darwin", "ios":
return []string{"DYLD_LIBRARY_PATH"}
- case "linux", "freebsd", "openbsd":
+ case "linux", "freebsd", "netbsd", "openbsd":
return []string{"LD_LIBRARY_PATH"}
case "hpux":
return []string{"LD_LIBRARY_PATH", "SHLIB_PATH"}
case "irix":
return []string{"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"}
- case "solaris":
+ case "illumos", "solaris":
return []string{"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"}
case "windows":
return []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"}
diff --git a/libgo/go/net/http/h2_bundle.go b/libgo/go/net/http/h2_bundle.go
index 779da4f..71592e9 100644
--- a/libgo/go/net/http/h2_bundle.go
+++ b/libgo/go/net/http/h2_bundle.go
@@ -5265,6 +5265,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
if len(data) > 0 {
wrote, err := st.body.Write(data)
if err != nil {
+ sc.sendWindowUpdate(nil, int(f.Length)-wrote)
return http2streamError(id, http2ErrCodeStreamClosed)
}
if wrote != len(data) {
@@ -7167,6 +7168,7 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client
cc.inflow.add(http2transportDefaultConnFlow + http2initialWindowSize)
cc.bw.Flush()
if cc.werr != nil {
+ cc.Close()
return nil, cc.werr
}
@@ -7532,6 +7534,15 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
bodyWriter := cc.t.getBodyWriterState(cs, body)
cs.on100 = bodyWriter.on100
+ defer func() {
+ cc.wmu.Lock()
+ werr := cc.werr
+ cc.wmu.Unlock()
+ if werr != nil {
+ cc.Close()
+ }
+ }()
+
cc.wmu.Lock()
endStream := !hasBody && !hasTrailers
werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index fe6b6098..54ec1c5 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -382,7 +382,7 @@ func (r *Request) Clone(ctx context.Context) *Request {
if s := r.TransferEncoding; s != nil {
s2 := make([]string, len(s))
copy(s2, s)
- r2.TransferEncoding = s
+ r2.TransferEncoding = s2
}
r2.Form = cloneURLValues(r.Form)
r2.PostForm = cloneURLValues(r.PostForm)
diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go
index 42c16d0..461d66e 100644
--- a/libgo/go/net/http/request_test.go
+++ b/libgo/go/net/http/request_test.go
@@ -828,6 +828,27 @@ func TestWithContextDeepCopiesURL(t *testing.T) {
}
}
+// Ensure that Request.Clone creates a deep copy of TransferEncoding.
+// See issue 41907.
+func TestRequestCloneTransferEncoding(t *testing.T) {
+ body := strings.NewReader("body")
+ req, _ := NewRequest("POST", "https://example.org/", body)
+ req.TransferEncoding = []string{
+ "encoding1",
+ }
+
+ clonedReq := req.Clone(context.Background())
+ // modify original after deep copy
+ req.TransferEncoding[0] = "encoding2"
+
+ if req.TransferEncoding[0] != "encoding2" {
+ t.Error("expected req.TransferEncoding to be changed")
+ }
+ if clonedReq.TransferEncoding[0] != "encoding1" {
+ t.Error("expected clonedReq.TransferEncoding to be unchanged")
+ }
+}
+
func TestNoPanicOnRoundTripWithBasicAuth_h1(t *testing.T) {
testNoPanicWithBasicAuth(t, h1Mode)
}
diff --git a/libgo/go/os/dir_regfile.go b/libgo/go/os/dir_regfile.go
index 1f18bab..b2e66235 100644
--- a/libgo/go/os/dir_regfile.go
+++ b/libgo/go/os/dir_regfile.go
@@ -15,5 +15,5 @@ package os
import "syscall"
-//extern readdir_r
+//extern-sysinfo readdir_r
func libc_readdir_r(*syscall.DIR, *syscall.Dirent, **syscall.Dirent) syscall.Errno
diff --git a/libgo/go/os/user/decls_unix.go b/libgo/go/os/user/decls_unix.go
index 276468c..6ffaced 100644
--- a/libgo/go/os/user/decls_unix.go
+++ b/libgo/go/os/user/decls_unix.go
@@ -11,17 +11,17 @@ import "syscall"
// Declarations for the libc functions on most Unix systems.
-//extern getpwnam_r
+//extern-sysinfo getpwnam_r
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
-//extern getpwuid_r
+//extern-sysinfo getpwuid_r
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
-//extern getgrnam_r
+//extern-sysinfo getgrnam_r
func libc_getgrnam_r(name *byte, grp *syscall.Group, buf *byte, buflen syscall.Size_t, result **syscall.Group) int
-//extern getgrgid_r
+//extern-sysinfo getgrgid_r
func libc_getgrgid_r(gid syscall.Gid_t, grp *syscall.Group, buf *byte, buflen syscall.Size_t, result **syscall.Group) int
-//extern getgrouplist
+//extern-sysinfo getgrouplist
func libc_getgrouplist(user *byte, group syscall.Gid_t, groups *syscall.Gid_t, ngroups *int32) int
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index 8a2bf8b..b99c345 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -37,7 +37,17 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
// and it's safe and valid to get Value's internal pointer.
hard := func(v1, v2 Value) bool {
switch v1.Kind() {
- case Map, Slice, Ptr, Interface:
+ case Ptr:
+ if v1.typ.ptrdata == 0 {
+ // go:notinheap pointers can't be cyclic.
+ // At least, all of our current uses of go:notinheap have
+ // that property. The runtime ones aren't cyclic (and we don't use
+ // DeepEqual on them anyway), and the cgo-generated ones are
+ // all empty structs.
+ return false
+ }
+ fallthrough
+ case Map, Slice, Interface:
// Nil pointers cannot be cyclic. Avoid putting them in the visited map.
return !v1.IsNil() && !v2.IsNil()
}
diff --git a/libgo/go/reflect/eqtype.go b/libgo/go/reflect/eqtype.go
new file mode 100644
index 0000000..5639bc5
--- /dev/null
+++ b/libgo/go/reflect/eqtype.go
@@ -0,0 +1,24 @@
+// Copyright 2020 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 !aix !gccgo
+
+package reflect
+
+// rtypeEqual returns true if both rtypes are identical.
+func rtypeEqual(t1, t2 *rtype) bool {
+ return t1 == t2
+}
+
+// typeEqual returns true if both Types are identical.
+func typeEqual(t1, t2 Type) bool {
+ return t1 == t2
+}
+
+func toType(p *rtype) Type {
+ if p == nil {
+ return nil
+ }
+ return p
+}
diff --git a/libgo/go/reflect/eqtype_aix_gccgo.go b/libgo/go/reflect/eqtype_aix_gccgo.go
new file mode 100644
index 0000000..7afbf10
--- /dev/null
+++ b/libgo/go/reflect/eqtype_aix_gccgo.go
@@ -0,0 +1,74 @@
+// Copyright 2020 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 aix,gccgo
+
+// AIX linker isn't able to merge identical type descriptors coming from
+// different objects. Thus, two rtypes might have two different pointers
+// even if they are the same. Thus, instead of pointer equality, string
+// field is checked.
+
+package reflect
+
+import (
+ "sync"
+)
+
+// rtypeEqual returns true if both rtypes are identical.
+func rtypeEqual(t1, t2 *rtype) bool {
+ switch {
+ case t1 == t2:
+ return true
+ case t1 == nil || t2 == nil:
+ return false
+ case t1.kind != t2.kind || t1.hash != t2.hash:
+ return false
+ default:
+ return t1.String() == t2.String()
+ }
+}
+
+// typeEqual returns true if both Types are identical.
+func typeEqual(t1, t2 Type) bool {
+ return rtypeEqual(t1.common(), t2.common())
+}
+
+// toType converts from a *rtype to a Type that can be returned
+// to the client of package reflect. The only concern is that
+// a nil *rtype must be replaced by a nil Type.
+// On AIX, as type duplications can occur, it also ensure that
+// multiple *rtype for the same type are coalesced into a single
+// Type.
+
+var canonicalType = make(map[string]Type)
+
+var canonicalTypeLock sync.RWMutex
+
+func canonicalize(t Type) Type {
+ if t == nil {
+ return nil
+ }
+ s := t.rawString()
+ canonicalTypeLock.RLock()
+ if r, ok := canonicalType[s]; ok {
+ canonicalTypeLock.RUnlock()
+ return r
+ }
+ canonicalTypeLock.RUnlock()
+ canonicalTypeLock.Lock()
+ if r, ok := canonicalType[s]; ok {
+ canonicalTypeLock.Unlock()
+ return r
+ }
+ canonicalType[s] = t
+ canonicalTypeLock.Unlock()
+ return t
+}
+
+func toType(p *rtype) Type {
+ if p == nil {
+ return nil
+ }
+ return canonicalize(p)
+}
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 2ce1901f..73c09d4 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -1129,7 +1129,7 @@ func (t *rtype) ptrTo() *rtype {
// Look in known types.
s := "*" + *t.string
if tt := lookupType(s); tt != nil {
- p := (*ptrType)(unsafe.Pointer(tt))
+ p := (*ptrType)(unsafe.Pointer(toType(tt).(*rtype)))
if p.elem == t {
pi, _ := ptrMap.LoadOrStore(t, p)
return &pi.(*ptrType).rtype
@@ -1158,7 +1158,9 @@ func (t *rtype) ptrTo() *rtype {
pp.ptrToThis = nil
pp.elem = t
- pi, _ := ptrMap.LoadOrStore(t, &pp)
+ q := toType(&pp.rtype).(*rtype)
+ p := (*ptrType)(unsafe.Pointer(q))
+ pi, _ := ptrMap.LoadOrStore(t, p)
return &pi.(*ptrType).rtype
}
@@ -1273,7 +1275,7 @@ func specialChannelAssignability(T, V *rtype) bool {
// and the ideal constant rules (no ideal constants at run time).
func directlyAssignable(T, V *rtype) bool {
// x's type V is identical to T?
- if T == V {
+ if rtypeEqual(T, V) {
return true
}
@@ -1304,7 +1306,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool {
}
func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
- if T == V {
+ if rtypeEqual(T, V) {
return true
}
@@ -1449,7 +1451,7 @@ func ChanOf(dir ChanDir, t Type) Type {
s = "chan " + *typ.string
}
if tt := lookupType(s); tt != nil {
- ch := (*chanType)(unsafe.Pointer(tt))
+ ch := (*chanType)(unsafe.Pointer(toType(tt).(*rtype)))
if ch.elem == typ && ch.dir == uintptr(dir) {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
@@ -1481,7 +1483,7 @@ func ChanOf(dir ChanDir, t Type) Type {
ch.uncommonType = nil
ch.ptrToThis = nil
- ti, _ := lookupCache.LoadOrStore(ckey, &ch.rtype)
+ ti, _ := lookupCache.LoadOrStore(ckey, toType(&ch.rtype).(*rtype))
return ti.(Type)
}
@@ -1508,7 +1510,7 @@ func MapOf(key, elem Type) Type {
// Look in known types.
s := "map[" + *ktyp.string + "]" + *etyp.string
if tt := lookupType(s); tt != nil {
- mt := (*mapType)(unsafe.Pointer(tt))
+ mt := (*mapType)(unsafe.Pointer(toType(tt).(*rtype)))
if mt.key == ktyp && mt.elem == etyp {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
@@ -1559,7 +1561,7 @@ func MapOf(key, elem Type) Type {
mt.flags |= 16
}
- ti, _ := lookupCache.LoadOrStore(ckey, &mt.rtype)
+ ti, _ := lookupCache.LoadOrStore(ckey, toType(&mt.rtype).(*rtype))
return ti.(Type)
}
@@ -1648,7 +1650,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
ft.string = &str
ft.uncommonType = nil
ft.ptrToThis = nil
- return addToCache(&ft.rtype)
+ return addToCache(toType(&ft.rtype).(*rtype))
}
// funcStr builds a string representation of a funcType.
@@ -1909,7 +1911,7 @@ func SliceOf(t Type) Type {
// Look in known types.
s := "[]" + *typ.string
if tt := lookupType(s); tt != nil {
- slice := (*sliceType)(unsafe.Pointer(tt))
+ slice := (*sliceType)(unsafe.Pointer(toType(tt).(*rtype)))
if slice.elem == typ {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
@@ -1930,7 +1932,7 @@ func SliceOf(t Type) Type {
slice.uncommonType = nil
slice.ptrToThis = nil
- ti, _ := lookupCache.LoadOrStore(ckey, &slice.rtype)
+ ti, _ := lookupCache.LoadOrStore(ckey, toType(&slice.rtype).(*rtype))
return ti.(Type)
}
@@ -2234,7 +2236,7 @@ func StructOf(fields []StructField) Type {
typ.uncommonType = nil
typ.ptrToThis = nil
- return addToCache(&typ.rtype)
+ return addToCache(toType(&typ.rtype).(*rtype))
}
// runtimeStructField takes a StructField value passed to StructOf and
@@ -2330,7 +2332,7 @@ func ArrayOf(count int, elem Type) Type {
// Look in known types.
s := "[" + strconv.Itoa(count) + "]" + *typ.string
if tt := lookupType(s); tt != nil {
- array := (*arrayType)(unsafe.Pointer(tt))
+ array := (*arrayType)(unsafe.Pointer(toType(tt).(*rtype)))
if array.elem == typ {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
@@ -2446,7 +2448,7 @@ func ArrayOf(count int, elem Type) Type {
array.kind &^= kindDirectIface
}
- ti, _ := lookupCache.LoadOrStore(ckey, &array.rtype)
+ ti, _ := lookupCache.LoadOrStore(ckey, toType(&array.rtype).(*rtype))
return ti.(Type)
}
@@ -2458,16 +2460,6 @@ func appendVarint(x []byte, v uintptr) []byte {
return x
}
-// toType converts from a *rtype to a Type that can be returned
-// to the client of package reflect. The only concern is that
-// a nil *rtype must be replaced by a nil Type.
-func toType(p *rtype) Type {
- if p == nil {
- return nil
- }
- return p
-}
-
// Look up a compiler-generated type descriptor.
// Implemented in runtime.
func lookupType(s string) *rtype
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index e60f84f..1394dd3 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -91,6 +91,7 @@ func (f flag) ro() flag {
// pointer returns the underlying pointer represented by v.
// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
+// if v.Kind() == Ptr, the base type must not be go:notinheap.
func (v Value) pointer() unsafe.Pointer {
if v.typ.size != ptrSize || !v.typ.pointers() {
panic("can't call pointer on a non-pointer Value")
@@ -1263,7 +1264,16 @@ func (v Value) Pointer() uintptr {
// TODO: deprecate
k := v.kind()
switch k {
- case Chan, Map, Ptr, UnsafePointer:
+ case Ptr:
+ if v.typ.ptrdata == 0 {
+ // Handle pointers to go:notinheap types directly,
+ // so we never materialize such pointers as an
+ // unsafe.Pointer. (Such pointers are always indirect.)
+ // See issue 42076.
+ return *(*uintptr)(v.ptr)
+ }
+ fallthrough
+ case Chan, Map, UnsafePointer:
return uintptr(v.pointer())
case Func:
p := v.pointer()
@@ -1785,7 +1795,7 @@ type SliceHeader struct {
}
func typesMustMatch(what string, t1, t2 Type) {
- if t1 != t2 {
+ if !typeEqual(t1, t2) {
panic(what + ": " + t1.String() + " != " + t2.String())
}
}
diff --git a/libgo/go/runtime/chan.go b/libgo/go/runtime/chan.go
index de1d80a..b909d47 100644
--- a/libgo/go/runtime/chan.go
+++ b/libgo/go/runtime/chan.go
@@ -267,6 +267,11 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
gp.waiting = mysg
gp.param = nil
c.sendq.enqueue(mysg)
+ // Signal to anyone trying to shrink our stack that we're about
+ // to park on a channel. The window between when this G's status
+ // changes and when we set gp.activeStackChans is not safe for
+ // stack shrinking.
+ atomic.Store8(&gp.parkingOnChan, 1)
gopark(chanparkcommit, unsafe.Pointer(&c.lock), waitReasonChanSend, traceEvGoBlockSend, 2)
// Ensure the value being sent is kept alive until the
// receiver copies it out. The sudog has a pointer to the
@@ -586,6 +591,11 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
mysg.c = c
gp.param = nil
c.recvq.enqueue(mysg)
+ // Signal to anyone trying to shrink our stack that we're about
+ // to park on a channel. The window between when this G's status
+ // changes and when we set gp.activeStackChans is not safe for
+ // stack shrinking.
+ atomic.Store8(&gp.parkingOnChan, 1)
gopark(chanparkcommit, unsafe.Pointer(&c.lock), waitReasonChanReceive, traceEvGoBlockRecv, 2)
// someone woke us up
@@ -663,7 +673,19 @@ func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
func chanparkcommit(gp *g, chanLock unsafe.Pointer) bool {
// There are unlocked sudogs that point into gp's stack. Stack
// copying must lock the channels of those sudogs.
+ // Set activeStackChans here instead of before we try parking
+ // because we could self-deadlock in stack growth on the
+ // channel lock.
gp.activeStackChans = true
+ // Mark that it's safe for stack shrinking to occur now,
+ // because any thread acquiring this G's stack for shrinking
+ // is guaranteed to observe activeStackChans after this store.
+ atomic.Store8(&gp.parkingOnChan, 0)
+ // Make sure we unlock after setting activeStackChans and
+ // unsetting parkingOnChan. The moment we unlock chanLock
+ // we risk gp getting readied by a channel operation and
+ // so gp could continue running before everything before
+ // the unlock is visible (even to gp itself).
unlock((*mutex)(chanLock))
return true
}
diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go
index ac81d40..85d3e04 100644
--- a/libgo/go/runtime/chan_test.go
+++ b/libgo/go/runtime/chan_test.go
@@ -628,6 +628,62 @@ func TestShrinkStackDuringBlockedSend(t *testing.T) {
<-done
}
+func TestNoShrinkStackWhileParking(t *testing.T) {
+ // The goal of this test is to trigger a "racy sudog adjustment"
+ // throw. Basically, there's a window between when a goroutine
+ // becomes available for preemption for stack scanning (and thus,
+ // stack shrinking) but before the goroutine has fully parked on a
+ // channel. See issue 40641 for more details on the problem.
+ //
+ // The way we try to induce this failure is to set up two
+ // goroutines: a sender and a reciever that communicate across
+ // a channel. We try to set up a situation where the sender
+ // grows its stack temporarily then *fully* blocks on a channel
+ // often. Meanwhile a GC is triggered so that we try to get a
+ // mark worker to shrink the sender's stack and race with the
+ // sender parking.
+ //
+ // Unfortunately the race window here is so small that we
+ // either need a ridiculous number of iterations, or we add
+ // "usleep(1000)" to park_m, just before the unlockf call.
+ const n = 10
+ send := func(c chan<- int, done chan struct{}) {
+ for i := 0; i < n; i++ {
+ c <- i
+ // Use lots of stack briefly so that
+ // the GC is going to want to shrink us
+ // when it scans us. Make sure not to
+ // do any function calls otherwise
+ // in order to avoid us shrinking ourselves
+ // when we're preempted.
+ stackGrowthRecursive(20)
+ }
+ done <- struct{}{}
+ }
+ recv := func(c <-chan int, done chan struct{}) {
+ for i := 0; i < n; i++ {
+ // Sleep here so that the sender always
+ // fully blocks.
+ time.Sleep(10 * time.Microsecond)
+ <-c
+ }
+ done <- struct{}{}
+ }
+ for i := 0; i < n*20; i++ {
+ c := make(chan int)
+ done := make(chan struct{})
+ go recv(c, done)
+ go send(c, done)
+ // Wait a little bit before triggering
+ // the GC to make sure the sender and
+ // reciever have gotten into their groove.
+ time.Sleep(50 * time.Microsecond)
+ runtime.GC()
+ <-done
+ <-done
+ }
+}
+
func TestSelectDuplicateChannel(t *testing.T) {
// This test makes sure we can queue a G on
// the same channel multiple times.
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go
index 482d014..369230a 100644
--- a/libgo/go/runtime/export_test.go
+++ b/libgo/go/runtime/export_test.go
@@ -355,7 +355,11 @@ func ReadMemStatsSlow() (base, slow MemStats) {
}
for i := mheap_.pages.start; i < mheap_.pages.end; i++ {
- pg := mheap_.pages.chunkOf(i).scavenged.popcntRange(0, pallocChunkPages)
+ chunk := mheap_.pages.tryChunkOf(i)
+ if chunk == nil {
+ continue
+ }
+ pg := chunk.scavenged.popcntRange(0, pallocChunkPages)
slow.HeapReleased += uint64(pg) * pageSize
}
for _, p := range allp {
@@ -752,11 +756,7 @@ func (p *PageAlloc) InUse() []AddrRange {
// Returns nil if the PallocData's L2 is missing.
func (p *PageAlloc) PallocData(i ChunkIdx) *PallocData {
ci := chunkIdx(i)
- l2 := (*pageAlloc)(p).chunks[ci.l1()]
- if l2 == nil {
- return nil
- }
- return (*PallocData)(&l2[ci.l2()])
+ return (*PallocData)((*pageAlloc)(p).tryChunkOf(ci))
}
// AddrRange represents a range over addresses.
@@ -896,7 +896,10 @@ func CheckScavengedBitsCleared(mismatches []BitsMismatch) (n int, ok bool) {
lock(&mheap_.lock)
chunkLoop:
for i := mheap_.pages.start; i < mheap_.pages.end; i++ {
- chunk := mheap_.pages.chunkOf(i)
+ chunk := mheap_.pages.tryChunkOf(i)
+ if chunk == nil {
+ continue
+ }
for j := 0; j < pallocChunkPages/64; j++ {
// Run over each 64-bit bitmap section and ensure
// scavenged is being cleared properly on allocation.
@@ -977,10 +980,9 @@ func MapHashCheck(m interface{}, k interface{}) (uintptr, uintptr) {
}
func MSpanCountAlloc(bits []byte) int {
- s := mspan{
- nelems: uintptr(len(bits) * 8),
- gcmarkBits: (*gcBits)(unsafe.Pointer(&bits[0])),
- }
+ s := (*mspan)(mheap_.spanalloc.alloc())
+ s.nelems = uintptr(len(bits) * 8)
+ s.gcmarkBits = (*gcBits)(unsafe.Pointer(&bits[0]))
return s.countAlloc()
}
diff --git a/libgo/go/runtime/internal/atomic/atomic_test.go b/libgo/go/runtime/internal/atomic/atomic_test.go
index 0c1125c..b0a8fa0 100644
--- a/libgo/go/runtime/internal/atomic/atomic_test.go
+++ b/libgo/go/runtime/internal/atomic/atomic_test.go
@@ -220,3 +220,13 @@ func TestBitwiseContended(t *testing.T) {
}
}
}
+
+func TestStorepNoWB(t *testing.T) {
+ var p [2]*int
+ for i := range p {
+ atomic.StorepNoWB(unsafe.Pointer(&p[i]), unsafe.Pointer(new(int)))
+ }
+ if p[0] == p[1] {
+ t.Error("Bad escape analysis of StorepNoWB")
+ }
+}
diff --git a/libgo/go/runtime/mpagealloc.go b/libgo/go/runtime/mpagealloc.go
index 8b3c62c..c90a637 100644
--- a/libgo/go/runtime/mpagealloc.go
+++ b/libgo/go/runtime/mpagealloc.go
@@ -326,7 +326,20 @@ func (s *pageAlloc) init(mheapLock *mutex, sysStat *uint64) {
s.scav.scavLWM = maxSearchAddr
}
+// tryChunkOf returns the bitmap data for the given chunk.
+//
+// Returns nil if the chunk data has not been mapped.
+func (s *pageAlloc) tryChunkOf(ci chunkIdx) *pallocData {
+ l2 := s.chunks[ci.l1()]
+ if l2 == nil {
+ return nil
+ }
+ return &l2[ci.l2()]
+}
+
// chunkOf returns the chunk at the given chunk index.
+//
+// The chunk index must be valid or this method may throw.
func (s *pageAlloc) chunkOf(ci chunkIdx) *pallocData {
return &s.chunks[ci.l1()][ci.l2()]
}
diff --git a/libgo/go/runtime/netpoll.go b/libgo/go/runtime/netpoll.go
index 5157e4d..72a136d 100644
--- a/libgo/go/runtime/netpoll.go
+++ b/libgo/go/runtime/netpoll.go
@@ -82,16 +82,17 @@ type pollDesc struct {
lock mutex // protects the following fields
fd uintptr
closing bool
- everr bool // marks event scanning error happened
- user uint32 // user settable cookie
- rseq uintptr // protects from stale read timers
- rg uintptr // pdReady, pdWait, G waiting for read or nil
- rt timer // read deadline timer (set if rt.f != nil)
- rd int64 // read deadline
- wseq uintptr // protects from stale write timers
- wg uintptr // pdReady, pdWait, G waiting for write or nil
- wt timer // write deadline timer
- wd int64 // write deadline
+ everr bool // marks event scanning error happened
+ user uint32 // user settable cookie
+ rseq uintptr // protects from stale read timers
+ rg uintptr // pdReady, pdWait, G waiting for read or nil
+ rt timer // read deadline timer (set if rt.f != nil)
+ rd int64 // read deadline
+ wseq uintptr // protects from stale write timers
+ wg uintptr // pdReady, pdWait, G waiting for write or nil
+ wt timer // write deadline timer
+ wd int64 // write deadline
+ self *pollDesc // storage for indirect interface. See (*pollDesc).makeArg.
}
type pollCache struct {
@@ -160,6 +161,7 @@ func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
pd.wseq++
pd.wg = 0
pd.wd = 0
+ pd.self = pd
unlock(&pd.lock)
var errno int32
@@ -279,14 +281,14 @@ func poll_runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
// Copy current seq into the timer arg.
// Timer func will check the seq against current descriptor seq,
// if they differ the descriptor was reused or timers were reset.
- pd.rt.arg = pd
+ pd.rt.arg = pd.makeArg()
pd.rt.seq = pd.rseq
resettimer(&pd.rt, pd.rd)
}
} else if pd.rd != rd0 || combo != combo0 {
pd.rseq++ // invalidate current timers
if pd.rd > 0 {
- modtimer(&pd.rt, pd.rd, 0, rtf, pd, pd.rseq)
+ modtimer(&pd.rt, pd.rd, 0, rtf, pd.makeArg(), pd.rseq)
} else {
deltimer(&pd.rt)
pd.rt.f = nil
@@ -295,14 +297,14 @@ func poll_runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
if pd.wt.f == nil {
if pd.wd > 0 && !combo {
pd.wt.f = netpollWriteDeadline
- pd.wt.arg = pd
+ pd.wt.arg = pd.makeArg()
pd.wt.seq = pd.wseq
resettimer(&pd.wt, pd.wd)
}
} else if pd.wd != wd0 || combo != combo0 {
pd.wseq++ // invalidate current timers
if pd.wd > 0 && !combo {
- modtimer(&pd.wt, pd.wd, 0, netpollWriteDeadline, pd, pd.wseq)
+ modtimer(&pd.wt, pd.wd, 0, netpollWriteDeadline, pd.makeArg(), pd.wseq)
} else {
deltimer(&pd.wt)
pd.wt.f = nil
@@ -556,3 +558,21 @@ func (c *pollCache) alloc() *pollDesc {
unlock(&c.lock)
return pd
}
+
+// makeArg converts pd to an interface{}.
+// makeArg does not do any allocation. Normally, such
+// a conversion requires an allocation because pointers to
+// go:notinheap types (which pollDesc is) must be stored
+// in interfaces indirectly. See issue 42076.
+func (pd *pollDesc) makeArg() (i interface{}) {
+ x := (*eface)(unsafe.Pointer(&i))
+ x._type = pdType
+ // For gccgo, we still use pd.self here, not &pd.self.
+ x.data = unsafe.Pointer(pd.self)
+ return
+}
+
+var (
+ pdEface interface{} = (*pollDesc)(nil)
+ pdType *_type = efaceOf(&pdEface)._type
+)
diff --git a/libgo/go/runtime/netpoll_kqueue.go b/libgo/go/runtime/netpoll_kqueue.go
index c41a7d0..1724f37 100644
--- a/libgo/go/runtime/netpoll_kqueue.go
+++ b/libgo/go/runtime/netpoll_kqueue.go
@@ -13,11 +13,11 @@ import (
"unsafe"
)
-//extern kqueue
+//extern-sysinfo kqueue
func kqueue() int32
//go:noescape
-//extern kevent
+//extern-sysinfo kevent
func kevent(kq int32, ch *keventt, nch uintptr, ev *keventt, nev uintptr, ts *timespec) int32
var (
diff --git a/libgo/go/runtime/os_aix.go b/libgo/go/runtime/os_aix.go
index 951aeb6..f49b83c 100644
--- a/libgo/go/runtime/os_aix.go
+++ b/libgo/go/runtime/os_aix.go
@@ -21,6 +21,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
+func getProcID() uint64 {
+ return uint64(gettid())
+}
+
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer
diff --git a/libgo/go/runtime/os_gccgo.go b/libgo/go/runtime/os_gccgo.go
index ab19022..79331c5 100644
--- a/libgo/go/runtime/os_gccgo.go
+++ b/libgo/go/runtime/os_gccgo.go
@@ -27,8 +27,7 @@ func mpreinit(mp *m) {
func minit() {
minitSignals()
- // FIXME: only works on linux for now.
- getg().m.procid = uint64(gettid())
+ getg().m.procid = getProcID()
}
// Called from dropm to undo the effect of an minit.
@@ -53,7 +52,7 @@ func getRandomData(r []byte) {
}
//go:noescape
-//extern pipe
+//extern-sysinfo pipe
func libcPipe(*[2]int32) int32
func pipe() (r, w int32, e int32) {
@@ -66,7 +65,7 @@ func pipe() (r, w int32, e int32) {
}
//go:noescape
-//extern pipe2
+//extern-sysinfo pipe2
func libcPipe2(*[2]int32, int32) int32
func pipe2(flags int32) (r, w int32, e int32) {
diff --git a/libgo/go/runtime/os_hurd.go b/libgo/go/runtime/os_hurd.go
index b3c6f80..1613b41 100644
--- a/libgo/go/runtime/os_hurd.go
+++ b/libgo/go/runtime/os_hurd.go
@@ -18,6 +18,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
+func getProcID() uint64 {
+ return uint64(gettid())
+}
+
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer
diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go
index 5d55064..627b6d6 100644
--- a/libgo/go/runtime/os_linux.go
+++ b/libgo/go/runtime/os_linux.go
@@ -13,6 +13,10 @@ type mOS struct {
unused byte
}
+func getProcID() uint64 {
+ return uint64(gettid())
+}
+
func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 {
return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
}
diff --git a/libgo/go/runtime/os_netbsd.go b/libgo/go/runtime/os_netbsd.go
index 69d2c71..00c3285 100644
--- a/libgo/go/runtime/os_netbsd.go
+++ b/libgo/go/runtime/os_netbsd.go
@@ -14,25 +14,25 @@ type mOS struct {
waitsemacount uint32
}
+func getProcID() uint64 {
+ return uint64(lwp_self())
+}
+
+//extern-sysinfo _lwp_self
+func lwp_self() int32
+
//go:noescape
-//extern lwp_park
+//extern-sysinfo _lwp_park
func lwp_park(ts int32, rel int32, abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
//go:noescape
-//extern lwp_unpark
+//extern-sysinfo _lwp_unpark
func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
//go:noescape
-//extern sysctl
+//extern-sysinfo sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
-// From NetBSD's <sys/sysctl.h>
-const (
- _CTL_HW = 6
- _HW_NCPU = 3
- _HW_PAGESIZE = 7
-)
-
func getncpu() int32 {
mib := [2]uint32{_CTL_HW, _HW_NCPU}
out := uint32(0)
@@ -88,7 +88,7 @@ func semasleep(ns int64) int32 {
tsp = &ts
}
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
- if ret == _ETIMEDOUT {
+ if ret != 0 && errno() == _ETIMEDOUT {
return -1
}
}
@@ -101,10 +101,10 @@ func semawakeup(mp *m) {
// "If the target LWP is not currently waiting, it will return
// immediately upon the next call to _lwp_park()."
ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
- if ret != 0 && ret != _ESRCH {
+ if ret != 0 && errno() != _ESRCH {
// semawakeup can be called on signal stack.
systemstack(func() {
- print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
+ print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " errno=", errno(), "\n")
})
}
}
diff --git a/libgo/go/runtime/os_solaris.go b/libgo/go/runtime/os_solaris.go
index 63b5cd7..c568629 100644
--- a/libgo/go/runtime/os_solaris.go
+++ b/libgo/go/runtime/os_solaris.go
@@ -10,6 +10,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
+func getProcID() uint64 {
+ return uint64(gettid())
+}
+
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index 84070e4..0ca6c02 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1258,6 +1258,14 @@ found:
checkdead()
unlock(&sched.lock)
+ if GOOS == "darwin" {
+ // Make sure pendingPreemptSignals is correct when an M exits.
+ // For #41702.
+ if atomic.Load(&m.signalPending) != 0 {
+ atomic.Xadd(&pendingPreemptSignals, -1)
+ }
+ }
+
if osStack {
// Return from mstart and let the system thread
// library free the g0 stack and terminate the thread.
@@ -3349,11 +3357,24 @@ func syscall_runtime_AfterForkInChild() {
inForkedChild = false
}
+// pendingPreemptSignals is the number of preemption signals
+// that have been sent but not received. This is only used on Darwin.
+// For #41702.
+var pendingPreemptSignals uint32
+
// Called from syscall package before Exec.
//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
func syscall_runtime_BeforeExec() {
// Prevent thread creation during exec.
execLock.lock()
+
+ // On Darwin, wait for all pending preemption signals to
+ // be received. See issue #41702.
+ if GOOS == "darwin" {
+ for int32(atomic.Load(&pendingPreemptSignals)) > 0 {
+ osyield()
+ }
+ }
}
// Called from syscall package after Exec.
diff --git a/libgo/go/runtime/proc_test.go b/libgo/go/runtime/proc_test.go
index b9828d9..a8f0dc3 100644
--- a/libgo/go/runtime/proc_test.go
+++ b/libgo/go/runtime/proc_test.go
@@ -529,9 +529,17 @@ func BenchmarkPingPongHog(b *testing.B) {
<-done
}
+var padData [128]uint64
+
func stackGrowthRecursive(i int) {
var pad [128]uint64
- if i != 0 && pad[0] == 0 {
+ pad = padData
+ for j := range pad {
+ if pad[j] != 0 {
+ return
+ }
+ }
+ if i != 0 {
stackGrowthRecursive(i - 1)
}
}
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index 5029dba..bf3fbac 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -450,6 +450,10 @@ type g struct {
// copying needs to acquire channel locks to protect these
// areas of the stack.
activeStackChans bool
+ // parkingOnChan indicates that the goroutine is about to
+ // park on a chansend or chanrecv. Used to signal an unsafe point
+ // for stack shrinking. It's a boolean value, but is updated atomically.
+ parkingOnChan uint8
raceignore int8 // ignore race detection events
sysblocktraced bool // StartTrace has emitted EvGoInSyscall about this goroutine
@@ -940,11 +944,6 @@ type _defer struct {
// panics
// This is the gccgo version.
-//
-// This is marked go:notinheap because _panic values must only ever
-// live on the stack.
-//
-//go:notinheap
type _panic struct {
// The next entry in the stack.
link *_panic
diff --git a/libgo/go/runtime/select.go b/libgo/go/runtime/select.go
index cf5d0c7..c8910b8 100644
--- a/libgo/go/runtime/select.go
+++ b/libgo/go/runtime/select.go
@@ -7,6 +7,7 @@ package runtime
// This file contains the implementation of Go select statements.
import (
+ "runtime/internal/atomic"
"unsafe"
)
@@ -72,7 +73,20 @@ func selunlock(scases []scase, lockorder []uint16) {
func selparkcommit(gp *g, _ unsafe.Pointer) bool {
// There are unlocked sudogs that point into gp's stack. Stack
// copying must lock the channels of those sudogs.
+ // Set activeStackChans here instead of before we try parking
+ // because we could self-deadlock in stack growth on a
+ // channel lock.
gp.activeStackChans = true
+ // Mark that it's safe for stack shrinking to occur now,
+ // because any thread acquiring this G's stack for shrinking
+ // is guaranteed to observe activeStackChans after this store.
+ atomic.Store8(&gp.parkingOnChan, 0)
+ // Make sure we unlock after setting activeStackChans and
+ // unsetting parkingOnChan. The moment we unlock any of the
+ // channel locks we risk gp getting readied by a channel operation
+ // and so gp could continue running before everything before the
+ // unlock is visible (even to gp itself).
+
// This must not access gp's stack (see gopark). In
// particular, it must not access the *hselect. That's okay,
// because by the time this is called, gp.waiting has all
@@ -313,6 +327,11 @@ loop:
// wait for someone to wake us up
gp.param = nil
+ // Signal to anyone trying to shrink our stack that we're about
+ // to park on a channel. The window between when this G's status
+ // changes and when we set gp.activeStackChans is not safe for
+ // stack shrinking.
+ atomic.Store8(&gp.parkingOnChan, 1)
gopark(selparkcommit, nil, waitReasonSelect, traceEvGoBlockSelect, 1)
gp.activeStackChans = false
diff --git a/libgo/go/runtime/signal_gccgo.go b/libgo/go/runtime/signal_gccgo.go
index c555712..2eece68 100644
--- a/libgo/go/runtime/signal_gccgo.go
+++ b/libgo/go/runtime/signal_gccgo.go
@@ -14,44 +14,44 @@ import (
// these are written in OS-specific files and in assembler.
//go:noescape
-//extern sigaction
+//extern-sysinfo sigaction
func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32
//go:noescape
-//extern sigprocmask
+//extern-sysinfo sigprocmask
func sigprocmask(how int32, set *sigset, oldset *sigset) int32
//go:noescape
-//extern sigfillset
+//extern-sysinfo sigfillset
func sigfillset(set *sigset) int32
//go:noescape
-//extern sigemptyset
+//extern-sysinfo sigemptyset
func sigemptyset(set *sigset) int32
//go:noescape
-//extern sigaddset
+//extern-sysinfo sigaddset
func c_sigaddset(set *sigset, signum uint32) int32
//go:noescape
-//extern sigdelset
+//extern-sysinfo sigdelset
func c_sigdelset(set *sigset, signum uint32) int32
//go:noescape
-//extern sigaltstack
+//extern-sysinfo sigaltstack
func sigaltstack(ss *_stack_t, oss *_stack_t) int32
-//extern raise
+//extern-sysinfo raise
func raise(sig uint32) int32
-//extern getpid
+//extern-sysinfo getpid
func getpid() _pid_t
-//extern kill
+//extern-sysinfo kill
func kill(pid _pid_t, sig uint32) int32
//go:noescape
-//extern setitimer
+//extern-sysinfo setitimer
func setitimer(which int32, new *_itimerval, old *_itimerval) int32
type sigctxt struct {
diff --git a/libgo/go/runtime/signal_unix.go b/libgo/go/runtime/signal_unix.go
index 17c15c5..6b69dcf 100644
--- a/libgo/go/runtime/signal_unix.go
+++ b/libgo/go/runtime/signal_unix.go
@@ -347,6 +347,10 @@ func doSigPreempt(gp *g, ctxt *sigctxt, sigpc uintptr) {
// Acknowledge the preemption.
atomic.Xadd(&gp.m.preemptGen, 1)
atomic.Store(&gp.m.signalPending, 0)
+
+ if GOOS == "darwin" {
+ atomic.Xadd(&pendingPreemptSignals, -1)
+ }
}
// This is false for gccgo.
@@ -404,6 +408,9 @@ func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
// no non-Go signal handler for sigPreempt.
// The default behavior for sigPreempt is to ignore
// the signal, so badsignal will be a no-op anyway.
+ if GOOS == "darwin" {
+ atomic.Xadd(&pendingPreemptSignals, -1)
+ }
return
}
badsignal(uintptr(sig), &c)
diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go
index 454afee..0aaed29 100644
--- a/libgo/go/runtime/stubs2.go
+++ b/libgo/go/runtime/stubs2.go
@@ -17,7 +17,7 @@ func read(fd int32, p unsafe.Pointer, n int32) int32
func closefd(fd int32) int32
-//extern exit
+//extern-sysinfo exit
func exit(code int32)
func usleep(usec uint32)
diff --git a/libgo/go/runtime/trace/trace_stack_test.go b/libgo/go/runtime/trace/trace_stack_test.go
index cfc0419..f856fdc 100644
--- a/libgo/go/runtime/trace/trace_stack_test.go
+++ b/libgo/go/runtime/trace/trace_stack_test.go
@@ -252,6 +252,7 @@ func TestTraceSymbolize(t *testing.T) {
{trace.EvGoSysCall, []frame{
{"syscall.read", 0},
{"syscall.Read", 0},
+ {"internal/poll.(*FD).Read.func1", 0},
{"internal/poll.ignoringEINTR", 0},
{"internal/poll.(*FD).Read", 0},
{"os.(*File).read", 0},
diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go
index 7e06943..ca7fdc0 100644
--- a/libgo/go/syscall/exec_bsd.go
+++ b/libgo/go/syscall/exec_bsd.go
@@ -93,7 +93,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Enable tracing if requested.
if sys.Ptrace {
- err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+ err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0)
if err1 != 0 {
goto childerror
}
diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go
index 2f0a34f..3897581 100644
--- a/libgo/go/syscall/exec_linux.go
+++ b/libgo/go/syscall/exec_linux.go
@@ -538,7 +538,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
// Do this right before exec so that we don't unnecessarily trace the runtime
// setting up after the fork. See issue #21428.
if sys.Ptrace {
- err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+ err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0)
if err1 != 0 {
goto childerror
}
diff --git a/libgo/go/syscall/exec_stubs.go b/libgo/go/syscall/exec_stubs.go
index e95b415..c837cf7 100644
--- a/libgo/go/syscall/exec_stubs.go
+++ b/libgo/go/syscall/exec_stubs.go
@@ -30,6 +30,6 @@ func (w WaitStatus) Signal() int { return 0 }
func (w WaitStatus) StopSignal() int { return 0 }
func (w WaitStatus) TrapCause() int { return 0 }
-func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno {
return ENOSYS
}
diff --git a/libgo/go/syscall/exec_unix_test.go b/libgo/go/syscall/exec_unix_test.go
index fab80e7..1399149 100644
--- a/libgo/go/syscall/exec_unix_test.go
+++ b/libgo/go/syscall/exec_unix_test.go
@@ -9,12 +9,14 @@ package syscall_test
import (
"internal/testenv"
"io"
+ "math/rand"
"os"
"os/exec"
"os/signal"
"runtime"
"syscall"
"testing"
+ "time"
"unsafe"
)
@@ -245,3 +247,46 @@ func TestInvalidExec(t *testing.T) {
}
})
}
+
+// TestExec is for issue #41702.
+func TestExec(t *testing.T) {
+ testenv.MustHaveExec(t)
+ cmd := exec.Command(os.Args[0], "-test.run=TestExecHelper")
+ cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=2")
+ o, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("%s\n%v", o, err)
+ }
+}
+
+// TestExecHelper is used by TestExec. It does nothing by itself.
+// In testing on macOS 10.14, this used to fail with
+// "signal: illegal instruction" more than half the time.
+func TestExecHelper(t *testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") != "2" {
+ return
+ }
+
+ // We don't have to worry about restoring these values.
+ // We are in a child process that only runs this test,
+ // and we are going to call syscall.Exec anyhow.
+ runtime.GOMAXPROCS(50)
+ os.Setenv("GO_WANT_HELPER_PROCESS", "3")
+
+ stop := time.Now().Add(time.Second)
+ for i := 0; i < 100; i++ {
+ go func(i int) {
+ r := rand.New(rand.NewSource(int64(i)))
+ for time.Now().Before(stop) {
+ r.Uint64()
+ }
+ }(i)
+ }
+
+ time.Sleep(10 * time.Millisecond)
+
+ argv := []string{os.Args[0], "-test.run=TestExecHelper"}
+ syscall.Exec(os.Args[0], argv, os.Environ())
+
+ t.Error("syscall.Exec returned")
+}
diff --git a/libgo/go/syscall/libcall_aix.go b/libgo/go/syscall/libcall_aix.go
index 27b469e..92c7f3c 100644
--- a/libgo/go/syscall/libcall_aix.go
+++ b/libgo/go/syscall/libcall_aix.go
@@ -19,7 +19,7 @@ const SYS_EXECVE = 0
//sys ptrace64(request int, id int64, addr int64, data int, buff uintptr) (err error)
//ptrace64(request _C_int, id int64, addr int64, data _C_int, buff *byte) _C_int
-func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno {
if request == _PTRACE_TRACEME {
// Convert to AIX ptrace call.
err := ptrace64(_PT_TRACE_ME, 0, 0, 0, 0)
diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd.go
index 93f5710..1dd957c 100644
--- a/libgo/go/syscall/libcall_bsd.go
+++ b/libgo/go/syscall/libcall_bsd.go
@@ -1,31 +1,113 @@
-// Copyright 2015 The Go Authors. All rights reserved.
+// Copyright 2020 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 darwin dragonfly freebsd netbsd openbsd solaris
+// +build darwin dragonfly freebsd netbsd openbsd
// BSD library calls.
package syscall
import (
- "internal/race"
"unsafe"
)
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
+//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
+//sysctl(mib *_C_int, miblen uintptr, old *byte, oldlen *uintptr, new *byte, newlen uintptr) _C_int
+
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data _C_int) _C_int
+
+//sys paccept(fd int, rsa *RawSockaddrAny, addrlen *Socklen_t, sigmask *_sigset_t, flags int) (nfd int, err error)
+//paccept(s _C_int, rsa *RawSockaddrAny, addrlen *Socklen_t, sigmask *_sigset_t, flags int) _C_int
+
+//sys Flock(fd int, how int) (err error)
+//flock(fd _C_int, how _C_int) _C_int
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+ // Final argument is (basep *uintptr) and the syscall doesn't take nil.
+ // 64 bits should be enough. (32 bits isn't even on 386). Since the
+ // actual system call is getdirentries64, 64 is a good guess.
+ // TODO(rsc): Can we use a single global basep for all calls?
+ var base = (*uintptr)(unsafe.Pointer(new(uint64)))
+ return Getdirentries(fd, buf, base)
+}
+
+func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ nfd, err = paccept(fd, &rsa, &len, nil, flags)
+ if err != nil {
+ return
}
- var soff Offset_t
- var psoff *Offset_t
- if offset != nil {
- soff = Offset_t(*offset)
- psoff = &soff
+ if len > SizeofSockaddrAny {
+ panic("RawSockaddrAny too small")
}
- written, err = sendfile(outfd, infd, psoff, count)
- if offset != nil {
- *offset = int64(soff)
+ sa, err = anyToSockaddr(&rsa)
+ if err != nil {
+ Close(nfd)
+ nfd = 0
}
return
}
+
+//sysnb pipe2(p *[2]_C_int, flags int) (err error)
+//pipe2(p *[2]_C_int, flags _C_int) _C_int
+func Pipe2(p []int, flags int) (err error) {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]_C_int
+ err = pipe2(&pp, flags)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return
+}
+
+func Sysctl(name string) (value string, err error) {
+ // Translate name to mib number.
+ mib, err := nametomib(name)
+ if err != nil {
+ return "", err
+ }
+
+ // Find size.
+ n := uintptr(0)
+ if err = sysctl(mib, nil, &n, nil, 0); err != nil {
+ return "", err
+ }
+ if n == 0 {
+ return "", nil
+ }
+
+ // Read into buffer of that size.
+ buf := make([]byte, n)
+ if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+ return "", err
+ }
+
+ // Throw away terminating NUL.
+ if n > 0 && buf[n-1] == '\x00' {
+ n--
+ }
+ return string(buf[0:n]), nil
+}
+
+func SysctlUint32(name string) (value uint32, err error) {
+ // Translate name to mib number.
+ mib, err := nametomib(name)
+ if err != nil {
+ return 0, err
+ }
+
+ // Read into buffer of that size.
+ n := uintptr(4)
+ buf := make([]byte, 4)
+ if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+ return 0, err
+ }
+ if n != 4 {
+ return 0, EIO
+ }
+ return *(*uint32)(unsafe.Pointer(&buf[0])), nil
+}
diff --git a/libgo/go/syscall/libcall_bsd_regfile.go b/libgo/go/syscall/libcall_bsd_regfile.go
index 388c8a7..0b9d01f 100644
--- a/libgo/go/syscall/libcall_bsd_regfile.go
+++ b/libgo/go/syscall/libcall_bsd_regfile.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd netbsd openbsd solaris,amd64 solaris,sparc64
+// +build darwin dragonfly freebsd openbsd solaris,amd64 solaris,sparc64
package syscall
diff --git a/libgo/go/syscall/libcall_bsd_sendfile.go b/libgo/go/syscall/libcall_bsd_sendfile.go
new file mode 100644
index 0000000..295a1f4
--- /dev/null
+++ b/libgo/go/syscall/libcall_bsd_sendfile.go
@@ -0,0 +1,31 @@
+// Copyright 2015 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 darwin dragonfly freebsd openbsd solaris
+
+// BSD sendfile support.
+
+package syscall
+
+import (
+ "internal/race"
+ "unsafe"
+)
+
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ if race.Enabled {
+ race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ var soff Offset_t
+ var psoff *Offset_t
+ if offset != nil {
+ soff = Offset_t(*offset)
+ psoff = &soff
+ }
+ written, err = sendfile(outfd, infd, psoff, count)
+ if offset != nil {
+ *offset = int64(soff)
+ }
+ return
+}
diff --git a/libgo/go/syscall/libcall_glibc.go b/libgo/go/syscall/libcall_glibc.go
index 823343d..a32d696 100644
--- a/libgo/go/syscall/libcall_glibc.go
+++ b/libgo/go/syscall/libcall_glibc.go
@@ -31,9 +31,6 @@ func Futimes(fd int, tv []Timeval) (err error) {
return Utimes("/proc/self/fd/"+itoa(fd), tv)
}
-//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
-//__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
-
//sys accept4(fd int, sa *RawSockaddrAny, len *Socklen_t, flags int) (nfd int, err error)
//accept4(fd _C_int, sa *RawSockaddrAny, len *Socklen_t, flags _C_int) _C_int
diff --git a/libgo/go/syscall/libcall_hurd.go b/libgo/go/syscall/libcall_hurd.go
index f0e038c..44ff46d 100644
--- a/libgo/go/syscall/libcall_hurd.go
+++ b/libgo/go/syscall/libcall_hurd.go
@@ -7,7 +7,7 @@
package syscall
// Dummy function
-func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno {
return ENOSYS
}
diff --git a/libgo/go/syscall/libcall_irix.go b/libgo/go/syscall/libcall_irix.go
index 9b6cdcc..9880766 100644
--- a/libgo/go/syscall/libcall_irix.go
+++ b/libgo/go/syscall/libcall_irix.go
@@ -6,5 +6,5 @@
package syscall
-//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
index 78fda0e..96974bd 100644
--- a/libgo/go/syscall/libcall_linux.go
+++ b/libgo/go/syscall/libcall_linux.go
@@ -10,7 +10,10 @@ import (
"unsafe"
)
-//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
+//__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
+
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
//__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
diff --git a/libgo/go/syscall/libcall_solaris_386.go b/libgo/go/syscall/libcall_solaris_386.go
index 20eba22..ef86f09 100644
--- a/libgo/go/syscall/libcall_solaris_386.go
+++ b/libgo/go/syscall/libcall_solaris_386.go
@@ -8,5 +8,5 @@ package syscall
//sysnb Uname(buf *Utsname) (err error)
//_nuname(buf *Utsname) _C_int
-//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_solaris_amd64.go b/libgo/go/syscall/libcall_solaris_amd64.go
index 69b11ba..f44025e 100644
--- a/libgo/go/syscall/libcall_solaris_amd64.go
+++ b/libgo/go/syscall/libcall_solaris_amd64.go
@@ -5,6 +5,6 @@
package syscall
// 64-bit ptrace(3C) doesn't exist
-func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno {
return ENOSYS
}
diff --git a/libgo/go/syscall/libcall_solaris_sparc.go b/libgo/go/syscall/libcall_solaris_sparc.go
index 50863fa..3d50309 100644
--- a/libgo/go/syscall/libcall_solaris_sparc.go
+++ b/libgo/go/syscall/libcall_solaris_sparc.go
@@ -4,5 +4,5 @@
package syscall
-//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_solaris_sparc64.go b/libgo/go/syscall/libcall_solaris_sparc64.go
index 69b11ba..f44025e 100644
--- a/libgo/go/syscall/libcall_solaris_sparc64.go
+++ b/libgo/go/syscall/libcall_solaris_sparc64.go
@@ -5,6 +5,6 @@
package syscall
// 64-bit ptrace(3C) doesn't exist
-func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno {
return ENOSYS
}
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
index 50802d9..5f46727 100644
--- a/libgo/go/syscall/mksyscall.awk
+++ b/libgo/go/syscall/mksyscall.awk
@@ -28,7 +28,7 @@
# type, without a name.
BEGIN {
- print "// This file was automatically generated by mksyscall.awk"
+ print "// Code generated by mksyscall.awk. DO NOT EDIT."
print ""
print "package syscall"
print ""
@@ -99,7 +99,7 @@ BEGIN {
if (!(cfnname in cfns)) {
cfns[cfnname] = 1
printf("//go:noescape\n")
- printf("//extern %s\n", cfnname)
+ printf("//extern-sysinfo %s\n", cfnname)
printf("func c_%s(%s) %s\n", cfnname, cfnparams, cfnresult)
}
printf("func %s(%s) %s%s%s%s{\n",
diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go
index b364eea..0c32594 100644
--- a/libgo/go/syscall/route_bsd.go
+++ b/libgo/go/syscall/route_bsd.go
@@ -18,7 +18,7 @@ var (
// Round the length of a raw sockaddr up to align it properly.
func rsaAlignOf(salen int) int {
- salign := sizeofPtr
+ salign := int(sizeofPtr)
if darwin64Bit {
// Darwin kernels require 32-bit aligned access to
// routing facilities.
diff --git a/libgo/go/syscall/socket_bsd.go b/libgo/go/syscall/socket_bsd.go
index f62457f..b230a32 100644
--- a/libgo/go/syscall/socket_bsd.go
+++ b/libgo/go/syscall/socket_bsd.go
@@ -13,6 +13,7 @@ import "unsafe"
const SizeofSockaddrInet4 = 16
const SizeofSockaddrInet6 = 28
const SizeofSockaddrUnix = 110
+const SizeofSockaddrDatalink = 20
type RawSockaddrInet4 struct {
Len uint8
@@ -52,13 +53,19 @@ func (sa *RawSockaddrUnix) setLen(n int) {
}
func (sa *RawSockaddrUnix) getLen() (int, error) {
- if sa.Len < 3 || sa.Len > SizeofSockaddrUnix {
+ if sa.Len < 2 || sa.Len > SizeofSockaddrUnix {
return 0, EINVAL
}
- n := int(sa.Len) - 3 // subtract leading Family, Len, terminating NUL.
+
+ // Some BSDs include the trailing NUL in the length, whereas
+ // others do not. Work around this by subtracting the leading
+ // family and len. The path is then scanned to see if a NUL
+ // terminator still exists within the length.
+ n := int(sa.Len) - 2 // subtract leading Family, Len
for i := 0; i < n; i++ {
if sa.Path[i] == 0 {
- // found early NUL; assume Len is overestimating.
+ // found early NUL; assume Len included the NUL
+ // or was overestimating.
n = i
break
}
@@ -70,6 +77,46 @@ func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
return sl
}
+type SockaddrDatalink struct {
+ Len uint8
+ Family uint8
+ Index uint16
+ Type uint8
+ Nlen uint8
+ Alen uint8
+ Slen uint8
+ Data [12]int8
+ raw RawSockaddrDatalink
+}
+
+func (sa *SockaddrDatalink) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+ if sa.Index == 0 {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Len = sa.Len
+ sa.raw.Family = AF_LINK
+ sa.raw.Index = sa.Index
+ sa.raw.Type = sa.Type
+ sa.raw.Nlen = sa.Nlen
+ sa.raw.Alen = sa.Alen
+ sa.raw.Slen = sa.Slen
+ for i := 0; i < len(sa.raw.Data); i++ {
+ sa.raw.Data[i] = sa.Data[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrDatalink, nil
+}
+
+type RawSockaddrDatalink struct {
+ Len uint8
+ Family uint8
+ Index uint16
+ Type uint8
+ Nlen uint8
+ Alen uint8
+ Slen uint8
+ Data [12]int8
+}
+
type RawSockaddr struct {
Len uint8
Family uint8
diff --git a/libgo/go/syscall/syscall_netbsd.go b/libgo/go/syscall/syscall_netbsd.go
index c67550a..c3a79e3 100644
--- a/libgo/go/syscall/syscall_netbsd.go
+++ b/libgo/go/syscall/syscall_netbsd.go
@@ -17,3 +17,92 @@ func direntReclen(buf []byte) (uint64, bool) {
func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
+
+//sys Getdents(fd int, buf []byte) (n int, err error)
+//getdents(fd _C_int, buf *byte, nbytes uintptr) _C_int
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ n, err = Getdents(fd, buf)
+ if err != nil || basep == nil {
+ return
+ }
+
+ var off int64
+ off, err = Seek(fd, 0, 1 /* SEEK_CUR */)
+ if err != nil {
+ *basep = ^uintptr(0)
+ return
+ }
+ *basep = uintptr(off)
+ if unsafe.Sizeof(*basep) == 8 {
+ return
+ }
+ if off>>32 != 0 {
+ // We can't stuff the offset back into a uintptr, so any
+ // future calls would be suspect. Generate an error.
+ // EIO is allowed by getdirentries.
+ err = EIO
+ }
+ return
+}
+
+func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
+ var olen uintptr
+
+ // Get a list of all sysctl nodes below the given MIB by performing
+ // a sysctl for the given MIB with CTL_QUERY appended.
+ mib = append(mib, CTL_QUERY)
+ qnode := Sysctlnode{Flags: SYSCTL_VERS_1}
+ qp := (*byte)(unsafe.Pointer(&qnode))
+ sz := unsafe.Sizeof(qnode)
+ if err = sysctl(mib, nil, &olen, qp, sz); err != nil {
+ return nil, err
+ }
+
+ // Now that we know the size, get the actual nodes.
+ nodes = make([]Sysctlnode, olen/sz)
+ np := (*byte)(unsafe.Pointer(&nodes[0]))
+ if err = sysctl(mib, np, &olen, qp, sz); err != nil {
+ return nil, err
+ }
+
+ return nodes, nil
+}
+
+func nametomib(name string) (mib []_C_int, err error) {
+ // Split name into components.
+ var parts []string
+ last := 0
+ for i := 0; i < len(name); i++ {
+ if name[i] == '.' {
+ parts = append(parts, name[last:i])
+ last = i + 1
+ }
+ }
+ parts = append(parts, name[last:])
+
+ // Discover the nodes and construct the MIB OID.
+ for partno, part := range parts {
+ nodes, err := sysctlNodes(mib)
+ if err != nil {
+ return nil, err
+ }
+ for _, node := range nodes {
+ n := make([]byte, 0)
+ for i := range node.Name {
+ if node.Name[i] != 0 {
+ n = append(n, byte(node.Name[i]))
+ }
+ }
+ if string(n) == part {
+ mib = append(mib, _C_int(node.Num))
+ break
+ }
+ }
+ if len(mib) != partno+1 {
+ return nil, EINVAL
+ }
+ }
+
+ return mib, nil
+}
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 5276600..e9687bf 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -242,7 +242,7 @@ func (b *B) run1() bool {
if b.skipped {
tag = "SKIP"
}
- if b.chatty && (len(b.output) > 0 || b.finished) {
+ if b.chatty != nil && (len(b.output) > 0 || b.finished) {
b.trimOutput()
fmt.Fprintf(b.w, "--- %s: %s\n%s", tag, b.name, b.output)
}
@@ -523,10 +523,9 @@ func runBenchmarks(importPath string, matchString func(pat, str string) (bool, e
}
main := &B{
common: common{
- name: "Main",
- w: os.Stdout,
- chatty: *chatty,
- bench: true,
+ name: "Main",
+ w: os.Stdout,
+ bench: true,
},
importPath: importPath,
benchFunc: func(b *B) {
@@ -537,6 +536,9 @@ func runBenchmarks(importPath string, matchString func(pat, str string) (bool, e
benchTime: benchTime,
context: ctx,
}
+ if Verbose() {
+ main.chatty = newChattyPrinter(main.w)
+ }
main.runN(1)
return !main.failed
}
@@ -549,7 +551,7 @@ func (ctx *benchContext) processBench(b *B) {
benchName := benchmarkName(b.name, procs)
// If it's chatty, we've already printed this information.
- if !b.chatty {
+ if b.chatty == nil {
fmt.Fprintf(b.w, "%-*s\t", ctx.maxLen, benchName)
}
// Recompute the running time for all but the first iteration.
@@ -576,7 +578,7 @@ func (ctx *benchContext) processBench(b *B) {
continue
}
results := r.String()
- if b.chatty {
+ if b.chatty != nil {
fmt.Fprintf(b.w, "%-*s\t", ctx.maxLen, benchName)
}
if *benchmarkMemory || b.showAllocResult {
@@ -639,7 +641,7 @@ func (b *B) Run(name string, f func(b *B)) bool {
atomic.StoreInt32(&sub.hasSub, 1)
}
- if b.chatty {
+ if b.chatty != nil {
labelsOnce.Do(func() {
fmt.Printf("goos: %s\n", runtime.GOOS)
fmt.Printf("goarch: %s\n", runtime.GOARCH)
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 8eb0084..5ed3fc4 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -483,10 +483,12 @@ func TestTRun(t *T) {
signal: make(chan bool),
name: "Test",
w: buf,
- chatty: tc.chatty,
},
context: ctx,
}
+ if tc.chatty {
+ root.chatty = newChattyPrinter(root.w)
+ }
ok := root.Run(tc.desc, tc.f)
ctx.release()
@@ -665,11 +667,13 @@ func TestBRun(t *T) {
signal: make(chan bool),
name: "root",
w: buf,
- chatty: tc.chatty,
},
benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure.
benchTime: benchTimeFlag{d: 1 * time.Microsecond},
}
+ if tc.chatty {
+ root.chatty = newChattyPrinter(root.w)
+ }
root.runN(1)
if ok != !tc.failed {
t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed)
@@ -741,9 +745,13 @@ func TestParallelSub(t *T) {
}
}
-type funcWriter func([]byte) (int, error)
+type funcWriter struct {
+ write func([]byte) (int, error)
+}
-func (fw funcWriter) Write(b []byte) (int, error) { return fw(b) }
+func (fw *funcWriter) Write(b []byte) (int, error) {
+ return fw.write(b)
+}
func TestRacyOutput(t *T) {
var runs int32 // The number of running Writes
@@ -761,9 +769,10 @@ func TestRacyOutput(t *T) {
var wg sync.WaitGroup
root := &T{
- common: common{w: funcWriter(raceDetector), chatty: true},
+ common: common{w: &funcWriter{raceDetector}},
context: newTestContext(1, newMatcher(regexp.MatchString, "", "")),
}
+ root.chatty = newChattyPrinter(root.w)
root.Run("", func(t *T) {
for i := 0; i < 100; i++ {
wg.Add(1)
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index fe6929d..80282fc 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -325,7 +325,6 @@ var (
cpuListStr *string
parallel *int
testlog *string
- printer *testPrinter
haveExamples bool // are there examples?
@@ -335,55 +334,45 @@ var (
numFailed uint32 // number of test failures
)
-type testPrinter struct {
- chatty bool
-
+type chattyPrinter struct {
+ w io.Writer
lastNameMu sync.Mutex // guards lastName
lastName string // last printed test name in chatty mode
}
-func newTestPrinter(chatty bool) *testPrinter {
- return &testPrinter{
- chatty: chatty,
- }
+func newChattyPrinter(w io.Writer) *chattyPrinter {
+ return &chattyPrinter{w: w}
}
-func (p *testPrinter) Print(testName, out string) {
- p.Fprint(os.Stdout, testName, out)
+// Updatef prints a message about the status of the named test to w.
+//
+// The formatted message must include the test name itself.
+func (p *chattyPrinter) Updatef(testName, format string, args ...interface{}) {
+ p.lastNameMu.Lock()
+ defer p.lastNameMu.Unlock()
+
+ // Since the message already implies an association with a specific new test,
+ // we don't need to check what the old test name was or log an extra CONT line
+ // for it. (We're updating it anyway, and the current message already includes
+ // the test name.)
+ p.lastName = testName
+ fmt.Fprintf(p.w, format, args...)
}
-func (p *testPrinter) Fprint(w io.Writer, testName, out string) {
+// Printf prints a message, generated by the named test, that does not
+// necessarily mention that tests's name itself.
+func (p *chattyPrinter) Printf(testName, format string, args ...interface{}) {
p.lastNameMu.Lock()
defer p.lastNameMu.Unlock()
- if !p.chatty ||
- strings.HasPrefix(out, "--- PASS: ") ||
- strings.HasPrefix(out, "--- FAIL: ") ||
- strings.HasPrefix(out, "--- SKIP: ") ||
- strings.HasPrefix(out, "=== RUN ") ||
- strings.HasPrefix(out, "=== CONT ") ||
- strings.HasPrefix(out, "=== PAUSE ") {
- // If we're buffering test output (!p.chatty), we don't really care which
- // test is emitting which line so long as they are serialized.
- //
- // If the message already implies an association with a specific new test,
- // we don't need to check what the old test name was or log an extra CONT
- // line for it. (We're updating it anyway, and the current message already
- // includes the test name.)
- p.lastName = testName
- fmt.Fprint(w, out)
- return
- }
-
if p.lastName == "" {
p.lastName = testName
} else if p.lastName != testName {
- // Always printed as-is, with 0 decoration or indentation. So, we skip
- // printing to w.
- fmt.Printf("=== CONT %s\n", testName)
+ fmt.Fprintf(p.w, "=== CONT %s\n", testName)
p.lastName = testName
}
- fmt.Fprint(w, out)
+
+ fmt.Fprintf(p.w, format, args...)
}
// The maximum number of stack frames to go through when skipping helper functions for
@@ -405,12 +394,12 @@ type common struct {
cleanupName string // Name of the cleanup function.
cleanupPc []uintptr // The stack trace at the point where Cleanup was called.
- chatty bool // A copy of the chatty flag.
- bench bool // Whether the current test is a benchmark.
- finished bool // Test function has completed.
- hasSub int32 // Written atomically.
- raceErrors int // Number of races detected during test.
- runner string // Function name of tRunner running the test.
+ chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set.
+ bench bool // Whether the current test is a benchmark.
+ finished bool // Test function has completed.
+ hasSub int32 // Written atomically.
+ raceErrors int // Number of races detected during test.
+ runner string // Function name of tRunner running the test.
parent *common
level int // Nesting depth of test or benchmark.
@@ -572,12 +561,31 @@ func (c *common) flushToParent(testName, format string, args ...interface{}) {
p.mu.Lock()
defer p.mu.Unlock()
- printer.Fprint(p.w, testName, fmt.Sprintf(format, args...))
-
c.mu.Lock()
defer c.mu.Unlock()
- io.Copy(p.w, bytes.NewReader(c.output))
- c.output = c.output[:0]
+
+ if len(c.output) > 0 {
+ format += "%s"
+ args = append(args[:len(args):len(args)], c.output)
+ c.output = c.output[:0] // but why?
+ }
+
+ if c.chatty != nil && p.w == c.chatty.w {
+ // We're flushing to the actual output, so track that this output is
+ // associated with a specific test (and, specifically, that the next output
+ // is *not* associated with that test).
+ //
+ // Moreover, if c.output is non-empty it is important that this write be
+ // atomic with respect to the output of other tests, so that we don't end up
+ // with confusing '=== CONT' lines in the middle of our '--- PASS' block.
+ // Neither humans nor cmd/test2json can parse those easily.
+ // (See https://golang.org/issue/40771.)
+ c.chatty.Updatef(testName, format, args...)
+ } else {
+ // We're flushing to the output buffer of the parent test, which will
+ // itself follow a test-name header when it is finally flushed to stdout.
+ fmt.Fprintf(p.w, format, args...)
+ }
}
type indenter struct {
@@ -746,13 +754,13 @@ func (c *common) logDepth(s string, depth int) {
}
panic("Log in goroutine after " + c.name + " has completed")
} else {
- if c.chatty {
+ if c.chatty != nil {
if c.bench {
// Benchmarks don't print === CONT, so we should skip the test
// printer and just print straight to stdout.
fmt.Print(c.decorate(s, depth+1))
} else {
- printer.Print(c.name, c.decorate(s, depth+1))
+ c.chatty.Printf(c.name, "%s", c.decorate(s, depth+1))
}
return
@@ -1019,34 +1027,22 @@ func (t *T) Parallel() {
t.parent.sub = append(t.parent.sub, t)
t.raceErrors += race.Errors()
- if t.chatty {
- // Print directly to root's io.Writer so there is no delay.
- root := t.parent
- for ; root.parent != nil; root = root.parent {
- }
- root.mu.Lock()
+ if t.chatty != nil {
// Unfortunately, even though PAUSE indicates that the named test is *no
// longer* running, cmd/test2json interprets it as changing the active test
// for the purpose of log parsing. We could fix cmd/test2json, but that
// won't fix existing deployments of third-party tools that already shell
// out to older builds of cmd/test2json — so merely fixing cmd/test2json
// isn't enough for now.
- printer.Fprint(root.w, t.name, fmt.Sprintf("=== PAUSE %s\n", t.name))
- root.mu.Unlock()
+ t.chatty.Updatef(t.name, "=== PAUSE %s\n", t.name)
}
t.signal <- true // Release calling test.
<-t.parent.barrier // Wait for the parent test to complete.
t.context.waitParallel()
- if t.chatty {
- // Print directly to root's io.Writer so there is no delay.
- root := t.parent
- for ; root.parent != nil; root = root.parent {
- }
- root.mu.Lock()
- printer.Fprint(root.w, t.name, fmt.Sprintf("=== CONT %s\n", t.name))
- root.mu.Unlock()
+ if t.chatty != nil {
+ t.chatty.Updatef(t.name, "=== CONT %s\n", t.name)
}
t.start = time.Now()
@@ -1197,14 +1193,8 @@ func (t *T) Run(name string, f func(t *T)) bool {
}
t.w = indenter{&t.common}
- if t.chatty {
- // Print directly to root's io.Writer so there is no delay.
- root := t.parent
- for ; root.parent != nil; root = root.parent {
- }
- root.mu.Lock()
- printer.Fprint(root.w, t.name, fmt.Sprintf("=== RUN %s\n", t.name))
- root.mu.Unlock()
+ if t.chatty != nil {
+ t.chatty.Updatef(t.name, "=== RUN %s\n", t.name)
}
// Instead of reducing the running count of this test before calling the
// tRunner and increasing it afterwards, we rely on tRunner keeping the
@@ -1369,8 +1359,6 @@ func (m *M) Run() (code int) {
flag.Parse()
}
- printer = newTestPrinter(Verbose())
-
if *parallel < 1 {
fmt.Fprintln(os.Stderr, "testing: -parallel can only be given a positive integer")
flag.Usage()
@@ -1415,7 +1403,7 @@ func (t *T) report() {
format := "--- %s: %s (%s)\n"
if t.Failed() {
t.flushToParent(t.name, format, "FAIL", t.name, dstr)
- } else if t.chatty {
+ } else if t.chatty != nil {
if t.Skipped() {
t.flushToParent(t.name, format, "SKIP", t.name, dstr)
} else {
@@ -1476,10 +1464,12 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT
signal: make(chan bool),
barrier: make(chan bool),
w: os.Stdout,
- chatty: *chatty,
},
context: ctx,
}
+ if Verbose() {
+ t.chatty = newChattyPrinter(t.w)
+ }
tRunner(t, func(t *T) {
for _, test := range tests {
t.Run(test.Name, test.F)
diff --git a/libgo/go/time/zoneinfo_read.go b/libgo/go/time/zoneinfo_read.go
index c242972..1e3586f 100644
--- a/libgo/go/time/zoneinfo_read.go
+++ b/libgo/go/time/zoneinfo_read.go
@@ -325,10 +325,27 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
l.cacheStart = tx[i].when
l.cacheEnd = omega
+ zoneIdx := tx[i].index
if i+1 < len(tx) {
l.cacheEnd = tx[i+1].when
+ } else if l.extend != "" {
+ // If we're at the end of the known zone transitions,
+ // try the extend string.
+ if name, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok {
+ l.cacheStart = estart
+ l.cacheEnd = eend
+ // Find the zone that is returned by tzset,
+ // the last transition is not always the correct zone.
+ for i, z := range l.zone {
+ if z.name == name {
+ zoneIdx = uint8(i)
+ break
+ }
+ }
+ }
}
- l.cacheZone = &l.zone[tx[i].index]
+ l.cacheZone = &l.zone[zoneIdx]
+ break
}
}
diff --git a/libgo/go/time/zoneinfo_test.go b/libgo/go/time/zoneinfo_test.go
index dac05e0..d543f93e 100644
--- a/libgo/go/time/zoneinfo_test.go
+++ b/libgo/go/time/zoneinfo_test.go
@@ -189,6 +189,25 @@ func TestMalformedTZData(t *testing.T) {
}
}
+func TestLoadLocationFromTZDataSlim(t *testing.T) {
+ // A 2020b slim tzdata for Europe/Berlin
+ tzData := "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n"
+
+ reference, err := time.LoadLocationFromTZData("Europe/Berlin", []byte(tzData))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference)
+ tzName, tzOffset := d.Zone()
+ if want := "CET"; tzName != want {
+ t.Errorf("Zone name == %s, want %s", tzName, want)
+ }
+ if want := 3600; tzOffset != want {
+ t.Errorf("Zone offset == %d, want %d", tzOffset, want)
+ }
+}
+
func TestTzset(t *testing.T) {
for _, test := range []struct {
inStr string
diff --git a/libgo/misc/cgo/test/testdata/issue41761.go b/libgo/misc/cgo/test/testdata/issue41761.go
new file mode 100644
index 0000000..919c749
--- /dev/null
+++ b/libgo/misc/cgo/test/testdata/issue41761.go
@@ -0,0 +1,20 @@
+// Copyright 2020 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 cgotest
+
+/*
+ typedef struct S S;
+*/
+import "C"
+
+import (
+ "cgotest/issue41761a"
+ "testing"
+)
+
+func test41761(t *testing.T) {
+ var x issue41761a.T
+ _ = (*C.struct_S)(x.X)
+}
diff --git a/libgo/misc/cgo/test/testdata/issue41761a/a.go b/libgo/misc/cgo/test/testdata/issue41761a/a.go
new file mode 100644
index 0000000..ca5c181
--- /dev/null
+++ b/libgo/misc/cgo/test/testdata/issue41761a/a.go
@@ -0,0 +1,14 @@
+// Copyright 2020 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 issue41761a
+
+/*
+ typedef struct S S;
+*/
+import "C"
+
+type T struct {
+ X *C.S
+}
diff --git a/libgo/mklinknames.awk b/libgo/mklinknames.awk
new file mode 100644
index 0000000..71cb3be
--- /dev/null
+++ b/libgo/mklinknames.awk
@@ -0,0 +1,46 @@
+# Copyright 2020 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.
+
+# This AWK script reads a Go file with special //extern-sysinfo
+# comments annotating functions which should be linked to libc
+# functions. It generates a Go file containing the appropriate
+# //go:linkname directives.
+#
+# For each annotated function, the script searches gen-sysinfo.go
+# to see if a different assembly name is known for the function.
+# For example, on NetBSD, the timegm symbol is renamed to
+# __timegm50 by an __asm__ annotation on its declaration in time.h.
+
+BEGIN {
+ print "// Code generated by mklinknames.awk. DO NOT EDIT."
+ print ""
+ print "package", package
+ print ""
+ print "import _ \"unsafe\""
+ print ""
+}
+
+/^\/\/extern-sysinfo/ {
+ cfnname = $2
+ getline
+ if ($1 != "func") {
+ printf("mklinknames.awk: error: %s:%d: unattached extern-sysinfo directive\n", FILENAME, FNR) | "cat 1>&2"
+ exit 1
+ }
+ split($2, a, "(")
+ gofnname = a[1]
+ def = sprintf("grep '^func _%s[ (]' gen-sysinfo.go", cfnname)
+ # def looks like one of the following:
+ # func _timegm (*_tm) int64 __asm__("__timegm50")
+ # func _timegm (*_tm) int64 __asm__("*__timegm50")
+ # The goal is to extract "__timegm50".
+ if ((def | getline fndef) > 0 && match(fndef, "__asm__\\(\"\\*?")) {
+ asmname = substr(fndef, RSTART + RLENGTH)
+ asmname = substr(asmname, 0, length(asmname) - 2)
+ printf("//go:linkname %s %s\n", gofnname, asmname)
+ } else {
+ # Assume the asm name is the same as the declared C name.
+ printf("//go:linkname %s %s\n", gofnname, cfnname)
+ }
+}
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 9671e39..deac5ce 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -225,6 +225,22 @@ if ! grep '^const _AT_FDCWD = ' ${OUT} >/dev/null 2>&1; then
echo "const _AT_FDCWD = -100" >> ${OUT}
fi
+# sysctl constants.
+grep '^const _CTL' gen-sysinfo.go |
+ sed -e 's/^\(const \)_\(CTL[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+ grep '^const _SYSCTL' gen-sysinfo.go |
+ sed -e 's/^\(const \)_\(SYSCTL[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+ grep '^const _NET_RT' gen-sysinfo.go |
+ sed -e 's/^\(const \)_\(NET_RT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The sysctlnode struct.
+grep '^type _sysctlnode ' gen-sysinfo.go | \
+ sed -e 's/_sysctlnode/Sysctlnode/' \
+ -e 's/sysctl_flags/Flags/' \
+ -e 's/sysctl_name/Name/' \
+ -e 's/sysctl_num/Num/' \
+ >> ${OUT}
+
# sysconf constants.
grep '^const __SC' gen-sysinfo.go |
sed -e 's/^\(const \)__\(SC[^= ]*\)\(.*\)$/\1\2 = __\2/' >> ${OUT}
@@ -491,6 +507,13 @@ if grep 'define st_dev st_fsid' gen-sysinfo.go > /dev/null 2>&1; then
st_dev='-e s/st_fsid/Dev/'
fi
+# For historical reasons Go uses the suffix "timespec" instead of "tim" for
+# stat_t's time fields on NetBSD.
+st_times='-e s/st_atim/Atim/ -e s/st_mtim/Mtim/ -e s/st_ctim/Ctim/'
+if test "${GOOS}" = "netbsd"; then
+ st_times='-e s/st_atim/Atimespec/ -e s/st_mtim/Mtimespec/ -e s/st_ctim/Ctimespec/'
+fi
+
# The stat type.
# Prefer largefile variant if available.
stat=`grep '^type _stat64 ' gen-sysinfo.go || true`
@@ -501,6 +524,7 @@ else
fi | sed -e 's/type _stat64/type Stat_t/' \
-e 's/type _stat/type Stat_t/' \
${st_dev} \
+ ${st_times} \
-e 's/st_ino/Ino/g' \
-e 's/st_nlink/Nlink/' \
-e 's/st_mode/Mode/' \
@@ -510,9 +534,6 @@ fi | sed -e 's/type _stat64/type Stat_t/' \
-e 's/st_size/Size/' \
-e 's/st_blksize/Blksize/' \
-e 's/st_blocks/Blocks/' \
- -e 's/st_atim/Atim/' \
- -e 's/st_mtim/Mtim/' \
- -e 's/st_ctim/Ctim/' \
-e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1Timeval\2/g' \
-e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \
-e 's/\([^a-zA-Z0-9_]\)_st_timespec_t\([^a-zA-Z0-9_]\)/\1StTimespec\2/g' \
@@ -533,6 +554,7 @@ fi | sed -e 's/type _dirent64/type Dirent/' \
-e 's/d_name \[0+1\]/d_name [0+256]/' \
-e 's/d_name/Name/' \
-e 's/]int8/]byte/' \
+ -e 's/d_fileno/Fileno/' \
-e 's/d_ino/Ino/' \
-e 's/d_namlen/Namlen/' \
-e 's/d_off/Off/' \
@@ -994,6 +1016,39 @@ grep '^type _rtgenmsg ' gen-sysinfo.go | \
-e 's/rtgen_family/Family/' \
>> ${OUT}
+# The rt_msghdr struct.
+grep '^type _rt_msghdr ' gen-sysinfo.go | \
+ sed -e 's/_rt_msghdr/RtMsghdr/g' \
+ -e 's/rtm_msglen/Msglen/' \
+ -e 's/rtm_version/Version/' \
+ -e 's/rtm_type/Type/' \
+ -e 's/rtm_index/Index/' \
+ -e 's/rtm_flags/Flags/' \
+ -e 's/rtm_addrs/Addrs/' \
+ -e 's/rtm_pid/Pid/' \
+ -e 's/rtm_seq/Seq/' \
+ -e 's/rtm_errno/Errno/' \
+ -e 's/rtm_use/Use/' \
+ -e 's/rtm_inits/Inits/' \
+ -e 's/rtm_rmx/Rmx/' \
+ -e 's/_rt_metrics/RtMetrics/' \
+ >> ${OUT}
+
+# The rt_metrics struct.
+grep '^type _rt_metrics ' gen-sysinfo.go | \
+ sed -e 's/_rt_metrics/RtMetrics/g' \
+ -e 's/rmx_locks/Locks/' \
+ -e 's/rmx_mtu/Mtu/' \
+ -e 's/rmx_hopcount/Hopcount/' \
+ -e 's/rmx_recvpipe/Recvpipe/' \
+ -e 's/rmx_sendpipe/Sendpipe/' \
+ -e 's/rmx_ssthresh/Ssthresh/' \
+ -e 's/rmx_rtt/Rtt/' \
+ -e 's/rmx_rttvar/Rttvar/' \
+ -e 's/rmx_expire/Expire/' \
+ -e 's/rmx_pksent/Pksent/' \
+ >> ${OUT}
+
# The routing message flags.
grep '^const _RT_' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(RT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
@@ -1005,6 +1060,13 @@ grep '^const _RTCF' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(RTCF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
grep '^const _RTM' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(RTM[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+if test "${GOOS}" = "netbsd"; then
+ if ! grep "RTM_RESOLVE" ${OUT} >/dev/null 2>&1; then
+ # NetBSD 8.0 removed RTM_RESOLVE, but it is part of the syscall package's
+ # stable API, so add it manually.
+ echo "const RTM_RESOLVE = 0xb" >> ${OUT}
+ fi
+fi
grep '^const _RTN' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(RTN[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
grep '^const _RTPROT' gen-sysinfo.go | \
@@ -1020,9 +1082,14 @@ grep '^type _ifinfomsg ' gen-sysinfo.go | \
-e 's/ifi_change/Change/' \
>> ${OUT}
-# The if_msghdr struct.
+# The if_msghdr struct. Upstream uses inconsistent capitalization for this type
+# on AIX, so we do too.
+ifmsghdr_name=IfMsghdr
+if test "${GOOS}" = "aix"; then
+ ifmsghdr_name=IfMsgHdr
+fi
grep '^type _if_msghdr ' gen-sysinfo.go | \
- sed -e 's/_if_msghdr/IfMsgHdr/' \
+ sed -e "s/_if_msghdr/${ifmsghdr_name}/" \
-e 's/ifm_msglen/Msglen/' \
-e 's/ifm_version/Version/' \
-e 's/ifm_type/Type/' \
@@ -1032,6 +1099,17 @@ grep '^type _if_msghdr ' gen-sysinfo.go | \
-e 's/ifm_addrlen/Addrlen/' \
>> ${OUT}
+# The if_announcemsghdr struct.
+grep '^type _if_announcemsghdr ' gen-sysinfo.go | \
+ sed -e 's/_if_announcemsghdr/IfAnnounceMsghdr/g' \
+ -e 's/ifan_msglen/Msglen/' \
+ -e 's/ifan_version/Version/' \
+ -e 's/ifan_type/Type/' \
+ -e 's/ifan_index/Index/' \
+ -e 's/ifan_name/Name/' \
+ -e 's/ifan_what/What/' \
+ >> ${OUT}
+
# The interface information types and flags.
grep '^const _IFA' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(IFA[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
@@ -1061,6 +1139,18 @@ grep '^type _ifaddrmsg ' gen-sysinfo.go | \
-e 's/ifa_index/Index/' \
>> ${OUT}
+# The ifa_msghdr struct.
+grep '^type _ifa_msghdr ' gen-sysinfo.go | \
+ sed -e 's/_ifa_msghdr/IfaMsghdr/g' \
+ -e 's/ifam_msglen/Msglen/' \
+ -e 's/ifam_version/Version/' \
+ -e 's/ifam_type/Type/' \
+ -e 's/ifam_addrs/Addrs/' \
+ -e 's/ifam_flags/Flags/' \
+ -e 's/ifam_metric/Metric/' \
+ -e 's/ifam_index/Index/' \
+ >> ${OUT}
+
# The rtattr struct.
grep '^type _rtattr ' gen-sysinfo.go | \
sed -e 's/_rtattr/RtAttr/' \
@@ -1068,6 +1158,54 @@ grep '^type _rtattr ' gen-sysinfo.go | \
-e 's/rta_type/Type/' \
>> ${OUT}
+# The bpf_version struct.
+grep '^type _bpf_version ' gen-sysinfo.go | \
+ sed -e 's/_bpf_version/BpfVersion/g' \
+ -e 's/bv_major/Major/' \
+ -e 's/bv_minor/Minor/' \
+ >> ${OUT}
+
+# The bpf_stat struct.
+grep '^type _bpf_stat ' gen-sysinfo.go | \
+ sed -e 's/_bpf_stat/BpfStat/g' \
+ -e 's/bs_recv/Recv/' \
+ -e 's/bs_drop/Drop/' \
+ -e 's/bs_capt/Capt/' \
+ -e 's/bs_padding/Padding/' \
+ >> ${OUT}
+
+# The bpf_insn struct.
+grep '^type _bpf_insn ' gen-sysinfo.go | \
+ sed -e 's/_bpf_insn/BpfInsn/g' \
+ -e 's/code/Code/' \
+ -e 's/jt/Jt/' \
+ -e 's/jf/Jf/' \
+ -e 's/k/K/' \
+ >> ${OUT}
+
+# The bpf_program struct.
+grep '^type _bpf_program ' gen-sysinfo.go | \
+ sed -e 's/_bpf_program/BpfProgram/g' \
+ -e 's/bf_len/Len/' \
+ -e 's/bf_insns/Insns/' \
+ -e 's/_bpf_insn/BpfInsn/' \
+ >> ${OUT}
+
+# The BPF ioctl constants.
+grep '^const _BIOC' gen-sysinfo.go | \
+ grep -v '_val =' | \
+ sed -e 's/^\(const \)_\(BIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+for c in BIOCFLUSH BIOCGBLEN BIOCGDLT BIOCGETIF BIOCGHDRCMPLT BIOCGRTIMEOUT \
+ BIOCGSTATS BIOCIMMEDIATE BIOCPROMISC BIOCSBLEN BIOCSDLT BIOCSETF \
+ BIOCSETIF BIOCSHDRCMPLT BIOCSRTIMEOUT BIOCVERSION
+do
+ if ! grep "^const ${c}" ${OUT} >/dev/null 2>&1; then
+ if grep "^const _${c}_val" ${OUT} >/dev/null 2>&1; then
+ echo "const ${c} = _${c}_val" >> ${OUT}
+ fi
+ fi
+done
+
# The in_pktinfo struct.
grep '^type _in_pktinfo ' gen-sysinfo.go | \
sed -e 's/_in_pktinfo/Inet4Pktinfo/' \
@@ -1344,10 +1482,11 @@ fi
# Struct sizes.
set cmsghdr Cmsghdr ip_mreq IPMreq ip_mreqn IPMreqn ipv6_mreq IPv6Mreq \
- ifaddrmsg IfAddrmsg ifinfomsg IfInfomsg in_pktinfo Inet4Pktinfo \
- in6_pktinfo Inet6Pktinfo inotify_event InotifyEvent linger Linger \
- msghdr Msghdr nlattr NlAttr nlmsgerr NlMsgerr nlmsghdr NlMsghdr \
- rtattr RtAttr rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \
+ ifaddrmsg IfAddrmsg ifa_msghdr IfaMsghdr ifinfomsg IfInfomsg \
+ if_msghdr IfMsghdr in_pktinfo Inet4Pktinfo in6_pktinfo Inet6Pktinfo \
+ inotify_event InotifyEvent linger Linger msghdr Msghdr nlattr NlAttr \
+ nlmsgerr NlMsgerr nlmsghdr NlMsghdr rtattr RtAttr rt_msghdr RtMsghdr \
+ rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \
sock_filter SockFilter sock_fprog SockFprog ucred Ucred \
icmp6_filter ICMPv6Filter ip6_mtuinfo IPv6MTUInfo
while test $# != 0; do
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index b429fdb..d30d160 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -229,6 +229,8 @@ getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar;
#elif defined(__aarch64__) && defined(__linux__)
ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc;
+#elif defined(__NetBSD__)
+ ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context)));
#endif
if (ret.sigpc == 0) {
diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c
index ad3142c..16e0525 100644
--- a/libgo/runtime/go-unwind.c
+++ b/libgo/runtime/go-unwind.c
@@ -59,20 +59,22 @@ void
rethrowException ()
{
struct _Unwind_Exception *hdr;
+ _Unwind_Reason_Code reason;
hdr = (struct _Unwind_Exception *) runtime_g()->exception;
#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_Resume_or_Rethrow (hdr);
+ reason = _Unwind_SjLj_Resume_or_Rethrow (hdr);
#else
#if defined(_LIBUNWIND_STD_ABI)
- _Unwind_RaiseException (hdr);
+ reason = _Unwind_RaiseException (hdr);
#else
- _Unwind_Resume_or_Rethrow (hdr);
+ reason = _Unwind_Resume_or_Rethrow (hdr);
#endif
#endif
/* Rethrowing the exception should not return. */
+ runtime_printf ("failed to rethrow unwind exception (reason=%d)\n", reason);
abort();
}
@@ -105,6 +107,7 @@ throwException ()
{
struct _Unwind_Exception *hdr;
uintptr align;
+ _Unwind_Reason_Code reason;
hdr = (struct _Unwind_Exception *)runtime_g ()->exception;
@@ -119,12 +122,13 @@ throwException ()
hdr->exception_cleanup = NULL;
#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException (hdr);
+ reason = _Unwind_SjLj_RaiseException (hdr);
#else
- _Unwind_RaiseException (hdr);
+ reason = _Unwind_RaiseException (hdr);
#endif
/* Raising an exception should not return. */
+ runtime_printf ("failed to throw unwind exception (reason=%d)\n", reason);
abort ();
}
diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c
index 9cb4a7e..f848608 100644
--- a/libgo/runtime/go-varargs.c
+++ b/libgo/runtime/go-varargs.c
@@ -114,15 +114,14 @@ __go_syscall6(uintptr_t flag, uintptr_t a1, uintptr_t a2, uintptr_t a3,
#endif
-// AIX ptrace is really different from Linux ptrace. Let syscall
-// package handles it.
-#if defined(HAVE_SYS_PTRACE_H) && !defined(_AIX)
+
+#if defined(HAVE_SYS_PTRACE_H) && defined(__linux__)
// Despite documented appearances, this is actually implemented as
-// a variadic function within glibc.
+// a variadic function within glibc on Linux.
long
-__go_ptrace(int request, pid_t pid, uintptr_t addr, uintptr_t data)
+__go_ptrace(int request, pid_t pid, void *addr, void *data)
{
return ptrace (request, pid, addr, data);
}
diff --git a/libgo/sysinfo.c b/libgo/sysinfo.c
index 6ea990f..7086381 100644
--- a/libgo/sysinfo.c
+++ b/libgo/sysinfo.c
@@ -10,6 +10,7 @@
#include "config.h"
#include <stddef.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
@@ -47,6 +48,9 @@
#if defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h>
#endif
+#if defined(HAVE_SYS_SYSCTL_H)
+#include <sys/sysctl.h>
+#endif
#if defined(HAVE_SYS_EPOLL_H)
#include <sys/epoll.h>
#endif
@@ -117,6 +121,9 @@
#if defined(HAVE_LINUX_RTNETLINK_H)
#include <linux/rtnetlink.h>
#endif
+#if defined(HAVE_NET_BPF_H)
+#include <net/bpf.h>
+#endif
#if defined(HAVE_NET_IF_H)
#include <net/if.h>
#endif
@@ -171,6 +178,9 @@
#if defined(HAVE_PORT_H)
#include <port.h>
#endif
+#if defined(HAVE_LWP_H)
+#include <lwp.h>
+#endif
#ifdef USE_LIBFFI
#include "ffi.h"
@@ -279,6 +289,54 @@ enum {
#ifdef NLA_HDRLEN
NLA_HDRLEN_val = NLA_HDRLEN,
#endif
+#ifdef BIOCFLUSH
+ BIOCFLUSH_val = BIOCFLUSH,
+#endif
+#ifdef BIOCGBLEN
+ BIOCGBLEN_val = BIOCGBLEN,
+#endif
+#ifdef BIOCGDLT
+ BIOCGDLT_val = BIOCGDLT,
+#endif
+#ifdef BIOCGETIF
+ BIOCGETIF_val = BIOCGETIF,
+#endif
+#ifdef BIOCGHDRCMPLT
+ BIOCGHDRCMPLT_val = BIOCGHDRCMPLT,
+#endif
+#ifdef BIOCGRTIMEOUT
+ BIOCGRTIMEOUT_val = BIOCGRTIMEOUT,
+#endif
+#ifdef BIOCGSTATS
+ BIOCGSTATS_val = BIOCGSTATS,
+#endif
+#ifdef BIOCIMMEDIATE
+ BIOCIMMEDIATE_val = BIOCIMMEDIATE,
+#endif
+#ifdef BIOCPROMISC
+ BIOCPROMISC_val = BIOCPROMISC,
+#endif
+#ifdef BIOCSBLEN
+ BIOCSBLEN_val = BIOCSBLEN,
+#endif
+#ifdef BIOCSDLT
+ BIOCSDLT_val = BIOCSDLT,
+#endif
+#ifdef BIOCSETF
+ BIOCSETF_val = BIOCSETF,
+#endif
+#ifdef BIOCSETIF
+ BIOCSETIF_val = BIOCSETIF,
+#endif
+#ifdef BIOCSHDRCMPLT
+ BIOCSHDRCMPLT_val = BIOCSHDRCMPLT,
+#endif
+#ifdef BIOCSRTIMEOUT
+ BIOCSRTIMEOUT_val = BIOCSRTIMEOUT,
+#endif
+#ifdef BIOCVERSION
+ BIOCVERSION_val = BIOCVERSION,
+#endif
};
// SIOCGIFMTU can't be added in the above enum as it might