mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 19:03:59 +08:00
libgo: update to 1.15.6 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/276153
This commit is contained in:
parent
570c312c03
commit
5ea350d1d7
@ -1,4 +1,4 @@
|
|||||||
f4069d94a25893afc9f2fcf641359366f3ede017
|
0d0b423739b2fee9788cb6cb8af9ced29375e545
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
c53315d6cf1b4bfea6ff356b4a1524778c683bb9
|
9b955d2d3fcff6a5bc8bce7bafdc4c634a28e95b
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the
|
The first line of this file holds the git revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
@ -1 +1 @@
|
|||||||
go1.15.5
|
go1.15.6
|
||||||
|
@ -2778,6 +2778,21 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
|||||||
idx = bytes.Index(src, []byte(cgoLdflag))
|
idx = bytes.Index(src, []byte(cgoLdflag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We expect to find the contents of cgoLDFLAGS in flags.
|
||||||
|
if len(cgoLDFLAGS) > 0 {
|
||||||
|
outer:
|
||||||
|
for i := range flags {
|
||||||
|
for j, f := range cgoLDFLAGS {
|
||||||
|
if f != flags[i+j] {
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags = append(flags[:i], flags[i+len(cgoLDFLAGS):]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
|
if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,61 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
var copyFileRangeSupported int32 = 1 // accessed atomically
|
var copyFileRangeSupported int32 = -1 // accessed atomically
|
||||||
|
|
||||||
const maxCopyFileRangeRound = 1 << 30
|
const maxCopyFileRangeRound = 1 << 30
|
||||||
|
|
||||||
|
func kernelVersion() (major int, minor int) {
|
||||||
|
var uname syscall.Utsname
|
||||||
|
if err := syscall.Uname(&uname); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rl := uname.Release
|
||||||
|
var values [2]int
|
||||||
|
vi := 0
|
||||||
|
value := 0
|
||||||
|
for _, c := range rl {
|
||||||
|
if '0' <= c && c <= '9' {
|
||||||
|
value = (value * 10) + int(c-'0')
|
||||||
|
} else {
|
||||||
|
// Note that we're assuming N.N.N here. If we see anything else we are likely to
|
||||||
|
// mis-parse it.
|
||||||
|
values[vi] = value
|
||||||
|
vi++
|
||||||
|
if vi >= len(values) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch vi {
|
||||||
|
case 0:
|
||||||
|
return 0, 0
|
||||||
|
case 1:
|
||||||
|
return values[0], 0
|
||||||
|
case 2:
|
||||||
|
return values[0], values[1]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// CopyFileRange copies at most remain bytes of data from src to dst, using
|
// CopyFileRange copies at most remain bytes of data from src to dst, using
|
||||||
// the copy_file_range system call. dst and src must refer to regular files.
|
// the copy_file_range system call. dst and src must refer to regular files.
|
||||||
func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err error) {
|
func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err error) {
|
||||||
if atomic.LoadInt32(©FileRangeSupported) == 0 {
|
if supported := atomic.LoadInt32(©FileRangeSupported); supported == 0 {
|
||||||
return 0, false, nil
|
return 0, false, nil
|
||||||
|
} else if supported == -1 {
|
||||||
|
major, minor := kernelVersion()
|
||||||
|
if major > 5 || (major == 5 && minor >= 3) {
|
||||||
|
atomic.StoreInt32(©FileRangeSupported, 1)
|
||||||
|
} else {
|
||||||
|
// copy_file_range(2) is broken in various ways on kernels older than 5.3,
|
||||||
|
// see issue #42400 and
|
||||||
|
// https://man7.org/linux/man-pages/man2/copy_file_range.2.html#VERSIONS
|
||||||
|
atomic.StoreInt32(©FileRangeSupported, 0)
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for remain > 0 {
|
for remain > 0 {
|
||||||
max := remain
|
max := remain
|
||||||
@ -41,7 +87,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
|
|||||||
// use copy_file_range(2) again.
|
// use copy_file_range(2) again.
|
||||||
atomic.StoreInt32(©FileRangeSupported, 0)
|
atomic.StoreInt32(©FileRangeSupported, 0)
|
||||||
return 0, false, nil
|
return 0, false, nil
|
||||||
case syscall.EXDEV, syscall.EINVAL, syscall.EOPNOTSUPP, syscall.EPERM:
|
case syscall.EXDEV, syscall.EINVAL, syscall.EIO, syscall.EOPNOTSUPP, syscall.EPERM:
|
||||||
// Prior to Linux 5.3, it was not possible to
|
// Prior to Linux 5.3, it was not possible to
|
||||||
// copy_file_range across file systems. Similarly to
|
// copy_file_range across file systems. Similarly to
|
||||||
// the ENOSYS case above, if we see EXDEV, we have
|
// the ENOSYS case above, if we see EXDEV, we have
|
||||||
@ -53,6 +99,9 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
|
|||||||
// file. This is another case where no data has been
|
// file. This is another case where no data has been
|
||||||
// transfered, so we consider it unhandled.
|
// transfered, so we consider it unhandled.
|
||||||
//
|
//
|
||||||
|
// If src and dst are on CIFS, we can see EIO.
|
||||||
|
// See issue #42334.
|
||||||
|
//
|
||||||
// If the file is on NFS, we can see EOPNOTSUPP.
|
// If the file is on NFS, we can see EOPNOTSUPP.
|
||||||
// See issue #40731.
|
// See issue #40731.
|
||||||
//
|
//
|
||||||
|
@ -612,3 +612,16 @@ func TestEINTR(t *testing.T) {
|
|||||||
t.Fatalf("want %s, got %s\n", want, output)
|
t.Fatalf("want %s, got %s\n", want, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #42207.
|
||||||
|
func TestNeedmDeadlock(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "plan9", "windows":
|
||||||
|
t.Skipf("no signals on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
|
||||||
|
want := "OK\n"
|
||||||
|
if output != want {
|
||||||
|
t.Fatalf("want %s, got %s\n", want, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -59,7 +59,7 @@ func mpreinit(mp *m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func msigsave(mp *m) {
|
func sigsave(p *sigset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
|
@ -571,7 +571,7 @@ func schedinit() {
|
|||||||
cpuinit() // must run before alginit
|
cpuinit() // must run before alginit
|
||||||
alginit() // maps must not be used before this call
|
alginit() // maps must not be used before this call
|
||||||
|
|
||||||
msigsave(_g_.m)
|
sigsave(&_g_.m.sigmask)
|
||||||
initSigmask = _g_.m.sigmask
|
initSigmask = _g_.m.sigmask
|
||||||
|
|
||||||
goargs()
|
goargs()
|
||||||
@ -1496,6 +1496,18 @@ func needm(x byte) {
|
|||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save and block signals before getting an M.
|
||||||
|
// The signal handler may call needm itself,
|
||||||
|
// and we must avoid a deadlock. Also, once g is installed,
|
||||||
|
// any incoming signals will try to execute,
|
||||||
|
// but we won't have the sigaltstack settings and other data
|
||||||
|
// set up appropriately until the end of minit, which will
|
||||||
|
// unblock the signals. This is the same dance as when
|
||||||
|
// starting a new m to run Go code via newosproc.
|
||||||
|
var sigmask sigset
|
||||||
|
sigsave(&sigmask)
|
||||||
|
sigblock()
|
||||||
|
|
||||||
// Lock extra list, take head, unlock popped list.
|
// Lock extra list, take head, unlock popped list.
|
||||||
// nilokay=false is safe here because of the invariant above,
|
// nilokay=false is safe here because of the invariant above,
|
||||||
// that the extra list always contains or will soon contain
|
// that the extra list always contains or will soon contain
|
||||||
@ -1513,14 +1525,8 @@ func needm(x byte) {
|
|||||||
extraMCount--
|
extraMCount--
|
||||||
unlockextra(mp.schedlink.ptr())
|
unlockextra(mp.schedlink.ptr())
|
||||||
|
|
||||||
// Save and block signals before installing g.
|
// Store the original signal mask for use by minit.
|
||||||
// Once g is installed, any incoming signals will try to execute,
|
mp.sigmask = sigmask
|
||||||
// but we won't have the sigaltstack settings and other data
|
|
||||||
// set up appropriately until the end of minit, which will
|
|
||||||
// unblock the signals. This is the same dance as when
|
|
||||||
// starting a new m to run Go code via newosproc.
|
|
||||||
msigsave(mp)
|
|
||||||
sigblock()
|
|
||||||
|
|
||||||
// Install g (= m->curg).
|
// Install g (= m->curg).
|
||||||
setg(mp.curg)
|
setg(mp.curg)
|
||||||
@ -3300,7 +3306,7 @@ func beforefork() {
|
|||||||
// a signal handler before exec if a signal is sent to the process
|
// a signal handler before exec if a signal is sent to the process
|
||||||
// group. See issue #18600.
|
// group. See issue #18600.
|
||||||
gp.m.locks++
|
gp.m.locks++
|
||||||
msigsave(gp.m)
|
sigsave(&gp.m.sigmask)
|
||||||
sigblock()
|
sigblock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,15 +956,15 @@ func sigfwdgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// msigsave saves the current thread's signal mask into mp.sigmask.
|
// sigsave saves the current thread's signal mask into *p.
|
||||||
// This is used to preserve the non-Go signal mask when a non-Go
|
// This is used to preserve the non-Go signal mask when a non-Go
|
||||||
// thread calls a Go function.
|
// thread calls a Go function.
|
||||||
// This is nosplit and nowritebarrierrec because it is called by needm
|
// This is nosplit and nowritebarrierrec because it is called by needm
|
||||||
// which may be called on a non-Go thread with no g available.
|
// which may be called on a non-Go thread with no g available.
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
//go:nowritebarrierrec
|
//go:nowritebarrierrec
|
||||||
func msigsave(mp *m) {
|
func sigsave(p *sigset) {
|
||||||
sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
|
sigprocmask(_SIG_SETMASK, nil, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// msigrestore sets the current thread's signal mask to sigmask.
|
// msigrestore sets the current thread's signal mask to sigmask.
|
||||||
@ -1038,7 +1038,7 @@ func minitSignalStack() {
|
|||||||
// thread's signal mask. When this is called all signals have been
|
// thread's signal mask. When this is called all signals have been
|
||||||
// blocked for the thread. This starts with m.sigmask, which was set
|
// blocked for the thread. This starts with m.sigmask, which was set
|
||||||
// either from initSigmask for a newly created thread or by calling
|
// either from initSigmask for a newly created thread or by calling
|
||||||
// msigsave if this is a non-Go thread calling a Go function. It
|
// sigsave if this is a non-Go thread calling a Go function. It
|
||||||
// removes all essential signals from the mask, thus causing those
|
// removes all essential signals from the mask, thus causing those
|
||||||
// signals to not be blocked. Then it sets the thread's signal mask.
|
// signals to not be blocked. Then it sets the thread's signal mask.
|
||||||
// After this is called the thread can receive signals.
|
// After this is called the thread can receive signals.
|
||||||
|
95
libgo/go/runtime/testdata/testprogcgo/needmdeadlock.go
vendored
Normal file
95
libgo/go/runtime/testdata/testprogcgo/needmdeadlock.go
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// 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 !plan9,!windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// This is for issue #42207.
|
||||||
|
// During a call to needm we could get a SIGCHLD signal
|
||||||
|
// which would itself call needm, causing a deadlock.
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern void GoNeedM();
|
||||||
|
|
||||||
|
#define SIGNALERS 10
|
||||||
|
|
||||||
|
static void* needmSignalThread(void* p) {
|
||||||
|
pthread_t* pt = (pthread_t*)(p);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 100; i++) {
|
||||||
|
if (pthread_kill(*pt, SIGCHLD) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
usleep(1);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't need many calls, as the deadlock is only likely
|
||||||
|
// to occur the first couple of times that needm is called.
|
||||||
|
// After that there will likely be an extra M available.
|
||||||
|
#define CALLS 10
|
||||||
|
|
||||||
|
static void* needmCallbackThread(void* p) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIGNALERS; i++) {
|
||||||
|
sched_yield(); // Help the signal threads get started.
|
||||||
|
}
|
||||||
|
for (i = 0; i < CALLS; i++) {
|
||||||
|
GoNeedM();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runNeedmSignalThread() {
|
||||||
|
int i;
|
||||||
|
pthread_t caller;
|
||||||
|
pthread_t s[SIGNALERS];
|
||||||
|
|
||||||
|
pthread_create(&caller, NULL, needmCallbackThread, NULL);
|
||||||
|
for (i = 0; i < SIGNALERS; i++) {
|
||||||
|
pthread_create(&s[i], NULL, needmSignalThread, &caller);
|
||||||
|
}
|
||||||
|
for (i = 0; i < SIGNALERS; i++) {
|
||||||
|
pthread_join(s[i], NULL);
|
||||||
|
}
|
||||||
|
pthread_join(caller, NULL);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register("NeedmDeadlock", NeedmDeadlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export GoNeedM
|
||||||
|
func GoNeedM() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NeedmDeadlock() {
|
||||||
|
// The failure symptom is that the program hangs because of a
|
||||||
|
// deadlock in needm, so set an alarm.
|
||||||
|
go func() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
fmt.Println("Hung for 5 seconds")
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
C.runNeedmSignalThread()
|
||||||
|
fmt.Println("OK")
|
||||||
|
}
|
@ -222,6 +222,9 @@ runtime_m(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set g.
|
// Set g.
|
||||||
|
|
||||||
|
void runtime_setg(G*) __attribute__ ((no_split_stack));
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime_setg(G* gp)
|
runtime_setg(G* gp)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user