mirror of
https://github.com/golang/go
synced 2024-11-27 00:21:21 -07:00
[dev.boringcrypto.go1.15] all: merge go1.15.15 into dev.boringcrypto.go1.15
Change-Id: I3b20c90322a0c0deec68a161b8fcbab9188fb6b2
This commit is contained in:
commit
dd96ded6c8
@ -498,13 +498,14 @@ func init() {
|
|||||||
// auxint = offset into duffzero code to start executing
|
// auxint = offset into duffzero code to start executing
|
||||||
// returns mem
|
// returns mem
|
||||||
// R20 changed as side effect
|
// R20 changed as side effect
|
||||||
|
// R16 and R17 may be clobbered by linker trampoline.
|
||||||
{
|
{
|
||||||
name: "DUFFZERO",
|
name: "DUFFZERO",
|
||||||
aux: "Int64",
|
aux: "Int64",
|
||||||
argLength: 2,
|
argLength: 2,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("R20")},
|
inputs: []regMask{buildReg("R20")},
|
||||||
clobbers: buildReg("R20 R30"),
|
clobbers: buildReg("R16 R17 R20 R30"),
|
||||||
},
|
},
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
},
|
},
|
||||||
@ -537,13 +538,14 @@ func init() {
|
|||||||
// auxint = offset into duffcopy code to start executing
|
// auxint = offset into duffcopy code to start executing
|
||||||
// returns mem
|
// returns mem
|
||||||
// R20, R21 changed as side effect
|
// R20, R21 changed as side effect
|
||||||
|
// R16 and R17 may be clobbered by linker trampoline.
|
||||||
{
|
{
|
||||||
name: "DUFFCOPY",
|
name: "DUFFCOPY",
|
||||||
aux: "Int64",
|
aux: "Int64",
|
||||||
argLength: 3,
|
argLength: 3,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("R21"), buildReg("R20")},
|
inputs: []regMask{buildReg("R21"), buildReg("R20")},
|
||||||
clobbers: buildReg("R20 R21 R26 R30"),
|
clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
|
||||||
},
|
},
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
faultOnNilArg1: true,
|
faultOnNilArg1: true,
|
||||||
@ -664,7 +666,8 @@ func init() {
|
|||||||
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
||||||
// It saves all GP registers if necessary,
|
// It saves all GP registers if necessary,
|
||||||
// but clobbers R30 (LR) because it's a call.
|
// but clobbers R30 (LR) because it's a call.
|
||||||
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R30")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
|
// R16 and R17 may be clobbered by linker trampoline.
|
||||||
|
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R16 R17 R30")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
|
||||||
|
|
||||||
// There are three of these functions so that they can have three different register inputs.
|
// There are three of these functions so that they can have three different register inputs.
|
||||||
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
|
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
|
||||||
|
@ -20738,7 +20738,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1048576}, // R20
|
{0, 1048576}, // R20
|
||||||
},
|
},
|
||||||
clobbers: 537919488, // R20 R30
|
clobbers: 538116096, // R16 R17 R20 R30
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -20765,7 +20765,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
{0, 2097152}, // R21
|
{0, 2097152}, // R21
|
||||||
{1, 1048576}, // R20
|
{1, 1048576}, // R20
|
||||||
},
|
},
|
||||||
clobbers: 607125504, // R20 R21 R26 R30
|
clobbers: 607322112, // R16 R17 R20 R21 R26 R30
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -21090,7 +21090,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
{0, 4}, // R2
|
{0, 4}, // R2
|
||||||
{1, 8}, // R3
|
{1, 8}, // R3
|
||||||
},
|
},
|
||||||
clobbers: 9223372035244163072, // R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
clobbers: 9223372035244359680, // R16 R17 R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1286,6 +1286,11 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
|
|||||||
Err: errors.New("import cycle not allowed"),
|
Err: errors.New("import cycle not allowed"),
|
||||||
IsImportCycle: true,
|
IsImportCycle: true,
|
||||||
}
|
}
|
||||||
|
} else if !p.Error.IsImportCycle {
|
||||||
|
// If the error is already set, but it does not indicate that
|
||||||
|
// we are in an import cycle, set IsImportCycle so that we don't
|
||||||
|
// end up stuck in a loop down the road.
|
||||||
|
p.Error.IsImportCycle = true
|
||||||
}
|
}
|
||||||
p.Incomplete = true
|
p.Incomplete = true
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -192,7 +193,7 @@ func copyMetadata(modPath, pkg, dst, src string) {
|
|||||||
if modPath == pkg {
|
if modPath == pkg {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pkg = filepath.Dir(pkg)
|
pkg = path.Dir(pkg)
|
||||||
dst = filepath.Dir(dst)
|
dst = filepath.Dir(dst)
|
||||||
src = filepath.Dir(src)
|
src = filepath.Dir(src)
|
||||||
}
|
}
|
||||||
|
15
src/cmd/go/testdata/script/list_err_cycle.txt
vendored
Normal file
15
src/cmd/go/testdata/script/list_err_cycle.txt
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Check that we don't get infinite recursion when loading a package with
|
||||||
|
# an import cycle and another error. Verifies #25830.
|
||||||
|
! go list
|
||||||
|
stderr 'found packages a \(a.go\) and b \(b.go\)'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module errcycle
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
-- a.go --
|
||||||
|
package a
|
||||||
|
|
||||||
|
import _ "errcycle"
|
||||||
|
-- b.go --
|
||||||
|
package b
|
@ -234,6 +234,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
if req.ContentLength == 0 {
|
if req.ContentLength == 0 {
|
||||||
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
||||||
}
|
}
|
||||||
|
if outreq.Body != nil {
|
||||||
|
// Reading from the request body after returning from a handler is not
|
||||||
|
// allowed, and the RoundTrip goroutine that reads the Body can outlive
|
||||||
|
// this handler. This can lead to a crash if the handler panics (see
|
||||||
|
// Issue 46866). Although calling Close doesn't guarantee there isn't
|
||||||
|
// any Read in flight after the handle returns, in practice it's safe to
|
||||||
|
// read after closing it.
|
||||||
|
defer outreq.Body.Close()
|
||||||
|
}
|
||||||
if outreq.Header == nil {
|
if outreq.Header == nil {
|
||||||
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
|
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
|
||||||
}
|
}
|
||||||
|
@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
|
|||||||
rproxy.ServeHTTP(httptest.NewRecorder(), req)
|
rproxy.ServeHTTP(httptest.NewRecorder(), req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #46866: panic without closing incoming request body causes a panic
|
||||||
|
func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
|
||||||
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
out := "this call was relayed by the reverse proxy"
|
||||||
|
// Coerce a wrong content length to induce io.ErrUnexpectedEOF
|
||||||
|
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
|
||||||
|
fmt.Fprintln(w, out)
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
backendURL, err := url.Parse(backend.URL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
proxyHandler := NewSingleHostReverseProxy(backendURL)
|
||||||
|
proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
|
||||||
|
frontend := httptest.NewServer(proxyHandler)
|
||||||
|
defer frontend.Close()
|
||||||
|
frontendClient := frontend.Client()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
const reqLen = 6 * 1024 * 1024
|
||||||
|
req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
|
||||||
|
req.ContentLength = reqLen
|
||||||
|
resp, _ := frontendClient.Transport.RoundTrip(req)
|
||||||
|
if resp != nil {
|
||||||
|
io.Copy(ioutil.Discard, resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
func TestSelectFlushInterval(t *testing.T) {
|
func TestSelectFlushInterval(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -6290,10 +6290,11 @@ func TestTransportRejectsSignInContentLength(t *testing.T) {
|
|||||||
// Test that a new request which uses the connection of an active request
|
// Test that a new request which uses the connection of an active request
|
||||||
// cannot cause it to be canceled as well.
|
// cannot cause it to be canceled as well.
|
||||||
func TestCancelRequestWhenSharingConnection(t *testing.T) {
|
func TestCancelRequestWhenSharingConnection(t *testing.T) {
|
||||||
if testing.Short() {
|
reqc := make(chan chan struct{}, 2)
|
||||||
t.Skip("skipping in short mode")
|
|
||||||
}
|
|
||||||
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) {
|
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) {
|
||||||
|
ch := make(chan struct{}, 1)
|
||||||
|
reqc <- ch
|
||||||
|
<-ch
|
||||||
w.Header().Add("Content-Length", "0")
|
w.Header().Add("Content-Length", "0")
|
||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
@ -6305,34 +6306,58 @@ func TestCancelRequestWhenSharingConnection(t *testing.T) {
|
|||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
wg.Add(1)
|
||||||
|
putidlec := make(chan chan struct{})
|
||||||
for i := 0; i < 10; i++ {
|
go func() {
|
||||||
wg.Add(1)
|
defer wg.Done()
|
||||||
go func() {
|
ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
|
||||||
defer wg.Done()
|
PutIdleConn: func(error) {
|
||||||
for ctx.Err() == nil {
|
// Signal that the idle conn has been returned to the pool,
|
||||||
reqctx, reqcancel := context.WithCancel(ctx)
|
// and wait for the order to proceed.
|
||||||
go reqcancel()
|
ch := make(chan struct{})
|
||||||
req, _ := NewRequestWithContext(reqctx, "GET", ts.URL, nil)
|
putidlec <- ch
|
||||||
res, err := client.Do(req)
|
<-ch
|
||||||
if err == nil {
|
},
|
||||||
res.Body.Close()
|
})
|
||||||
}
|
req, _ := NewRequestWithContext(ctx, "GET", ts.URL, nil)
|
||||||
}
|
res, err := client.Do(req)
|
||||||
}()
|
if err == nil {
|
||||||
}
|
|
||||||
|
|
||||||
for ctx.Err() == nil {
|
|
||||||
req, _ := NewRequest("GET", ts.URL, nil)
|
|
||||||
if res, err := client.Do(req); err != nil {
|
|
||||||
t.Errorf("unexpected: %p %v", req, err)
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
}
|
}
|
||||||
}
|
if err != nil {
|
||||||
|
t.Errorf("request 1: got err %v, want nil", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for the first request to receive a response and return the
|
||||||
|
// connection to the idle pool.
|
||||||
|
r1c := <-reqc
|
||||||
|
close(r1c)
|
||||||
|
idlec := <-putidlec
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
cancelctx, cancel := context.WithCancel(context.Background())
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
req, _ := NewRequestWithContext(cancelctx, "GET", ts.URL, nil)
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err == nil {
|
||||||
|
res.Body.Close()
|
||||||
|
}
|
||||||
|
if !errors.Is(err, context.Canceled) {
|
||||||
|
t.Errorf("request 2: got err %v, want Canceled", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for the second request to arrive at the server, and then cancel
|
||||||
|
// the request context.
|
||||||
|
r2c := <-reqc
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
|
// Give the cancelation a moment to take effect, and then unblock the first request.
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
close(idlec)
|
||||||
|
|
||||||
|
close(r2c)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
@ -1161,10 +1161,10 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1
|
|||||||
// It does not clobber any general-purpose registers,
|
// It does not clobber any general-purpose registers,
|
||||||
// but may clobber others (e.g., floating point registers)
|
// but may clobber others (e.g., floating point registers)
|
||||||
// The act of CALLing gcWriteBarrier will clobber R30 (LR).
|
// The act of CALLing gcWriteBarrier will clobber R30 (LR).
|
||||||
TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216
|
TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$200
|
||||||
// Save the registers clobbered by the fast path.
|
// Save the registers clobbered by the fast path.
|
||||||
MOVD R0, 200(RSP)
|
MOVD R0, 184(RSP)
|
||||||
MOVD R1, 208(RSP)
|
MOVD R1, 192(RSP)
|
||||||
MOVD g_m(g), R0
|
MOVD g_m(g), R0
|
||||||
MOVD m_p(R0), R0
|
MOVD m_p(R0), R0
|
||||||
MOVD (p_wbBuf+wbBuf_next)(R0), R1
|
MOVD (p_wbBuf+wbBuf_next)(R0), R1
|
||||||
@ -1180,8 +1180,8 @@ TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216
|
|||||||
// Is the buffer full? (flags set in CMP above)
|
// Is the buffer full? (flags set in CMP above)
|
||||||
BEQ flush
|
BEQ flush
|
||||||
ret:
|
ret:
|
||||||
MOVD 200(RSP), R0
|
MOVD 184(RSP), R0
|
||||||
MOVD 208(RSP), R1
|
MOVD 192(RSP), R1
|
||||||
// Do the write.
|
// Do the write.
|
||||||
MOVD R3, (R2)
|
MOVD R3, (R2)
|
||||||
RET
|
RET
|
||||||
@ -1205,17 +1205,16 @@ flush:
|
|||||||
MOVD R13, 96(RSP)
|
MOVD R13, 96(RSP)
|
||||||
MOVD R14, 104(RSP)
|
MOVD R14, 104(RSP)
|
||||||
MOVD R15, 112(RSP)
|
MOVD R15, 112(RSP)
|
||||||
MOVD R16, 120(RSP)
|
// R16, R17 may be clobbered by linker trampoline
|
||||||
MOVD R17, 128(RSP)
|
|
||||||
// R18 is unused.
|
// R18 is unused.
|
||||||
MOVD R19, 136(RSP)
|
MOVD R19, 120(RSP)
|
||||||
MOVD R20, 144(RSP)
|
MOVD R20, 128(RSP)
|
||||||
MOVD R21, 152(RSP)
|
MOVD R21, 136(RSP)
|
||||||
MOVD R22, 160(RSP)
|
MOVD R22, 144(RSP)
|
||||||
MOVD R23, 168(RSP)
|
MOVD R23, 152(RSP)
|
||||||
MOVD R24, 176(RSP)
|
MOVD R24, 160(RSP)
|
||||||
MOVD R25, 184(RSP)
|
MOVD R25, 168(RSP)
|
||||||
MOVD R26, 192(RSP)
|
MOVD R26, 176(RSP)
|
||||||
// R27 is temp register.
|
// R27 is temp register.
|
||||||
// R28 is g.
|
// R28 is g.
|
||||||
// R29 is frame pointer (unused).
|
// R29 is frame pointer (unused).
|
||||||
@ -1239,16 +1238,14 @@ flush:
|
|||||||
MOVD 96(RSP), R13
|
MOVD 96(RSP), R13
|
||||||
MOVD 104(RSP), R14
|
MOVD 104(RSP), R14
|
||||||
MOVD 112(RSP), R15
|
MOVD 112(RSP), R15
|
||||||
MOVD 120(RSP), R16
|
MOVD 120(RSP), R19
|
||||||
MOVD 128(RSP), R17
|
MOVD 128(RSP), R20
|
||||||
MOVD 136(RSP), R19
|
MOVD 136(RSP), R21
|
||||||
MOVD 144(RSP), R20
|
MOVD 144(RSP), R22
|
||||||
MOVD 152(RSP), R21
|
MOVD 152(RSP), R23
|
||||||
MOVD 160(RSP), R22
|
MOVD 160(RSP), R24
|
||||||
MOVD 168(RSP), R23
|
MOVD 168(RSP), R25
|
||||||
MOVD 176(RSP), R24
|
MOVD 176(RSP), R26
|
||||||
MOVD 184(RSP), R25
|
|
||||||
MOVD 192(RSP), R26
|
|
||||||
JMP ret
|
JMP ret
|
||||||
|
|
||||||
// Note: these functions use a special calling convention to save generated code space.
|
// Note: these functions use a special calling convention to save generated code space.
|
||||||
|
@ -393,7 +393,7 @@ func preemptM(mp *m) {
|
|||||||
//go:nosplit
|
//go:nosplit
|
||||||
func sigFetchG(c *sigctxt) *g {
|
func sigFetchG(c *sigctxt) *g {
|
||||||
switch GOARCH {
|
switch GOARCH {
|
||||||
case "arm", "arm64":
|
case "arm", "arm64", "ppc64", "ppc64le":
|
||||||
if !iscgo && inVDSOPage(c.sigpc()) {
|
if !iscgo && inVDSOPage(c.sigpc()) {
|
||||||
// When using cgo, we save the g on TLS and load it from there
|
// When using cgo, we save the g on TLS and load it from there
|
||||||
// in sigtramp. Just use that.
|
// in sigtramp. Just use that.
|
||||||
|
@ -215,15 +215,45 @@ TEXT runtime·walltime1(SB),NOSPLIT,$16-12
|
|||||||
MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
|
MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
|
||||||
|
|
||||||
noswitch:
|
noswitch:
|
||||||
SUB $16, R1 // Space for results
|
SUB $16, R1 // Space for results
|
||||||
RLDICR $0, R1, $59, R1 // Align for C code
|
RLDICR $0, R1, $59, R1 // Align for C code
|
||||||
MOVD R12, CTR
|
MOVD R12, CTR
|
||||||
MOVD R1, R4
|
MOVD R1, R4
|
||||||
BL (CTR) // Call from VDSO
|
|
||||||
MOVD $0, R0 // Restore R0
|
// Store g on gsignal's stack, so if we receive a signal
|
||||||
MOVD 0(R1), R3 // sec
|
// during VDSO code we can find the g.
|
||||||
MOVD 8(R1), R5 // nsec
|
// If we don't have a signal stack, we won't receive signal,
|
||||||
MOVD R15, R1 // Restore SP
|
// so don't bother saving g.
|
||||||
|
// When using cgo, we already saved g on TLS, also don't save
|
||||||
|
// g here.
|
||||||
|
// Also don't save g if we are already on the signal stack.
|
||||||
|
// We won't get a nested signal.
|
||||||
|
MOVBZ runtime·iscgo(SB), R22
|
||||||
|
CMP R22, $0
|
||||||
|
BNE nosaveg
|
||||||
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
||||||
|
CMP R22, $0
|
||||||
|
BEQ nosaveg
|
||||||
|
|
||||||
|
CMP g, R22
|
||||||
|
BEQ nosaveg
|
||||||
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
||||||
|
MOVD g, (R22)
|
||||||
|
|
||||||
|
BL (CTR) // Call from VDSO
|
||||||
|
|
||||||
|
MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
|
||||||
|
|
||||||
|
JMP finish
|
||||||
|
|
||||||
|
nosaveg:
|
||||||
|
BL (CTR) // Call from VDSO
|
||||||
|
|
||||||
|
finish:
|
||||||
|
MOVD $0, R0 // Restore R0
|
||||||
|
MOVD 0(R1), R3 // sec
|
||||||
|
MOVD 8(R1), R5 // nsec
|
||||||
|
MOVD R15, R1 // Restore SP
|
||||||
|
|
||||||
// Restore vdsoPC, vdsoSP
|
// Restore vdsoPC, vdsoSP
|
||||||
// We don't worry about being signaled between the two stores.
|
// We don't worry about being signaled between the two stores.
|
||||||
@ -235,7 +265,7 @@ noswitch:
|
|||||||
MOVD 32(R1), R6
|
MOVD 32(R1), R6
|
||||||
MOVD R6, m_vdsoPC(R21)
|
MOVD R6, m_vdsoPC(R21)
|
||||||
|
|
||||||
finish:
|
return:
|
||||||
MOVD R3, sec+0(FP)
|
MOVD R3, sec+0(FP)
|
||||||
MOVW R5, nsec+8(FP)
|
MOVW R5, nsec+8(FP)
|
||||||
RET
|
RET
|
||||||
@ -246,7 +276,7 @@ fallback:
|
|||||||
SYSCALL $SYS_clock_gettime
|
SYSCALL $SYS_clock_gettime
|
||||||
MOVD 32(R1), R3
|
MOVD 32(R1), R3
|
||||||
MOVD 40(R1), R5
|
MOVD 40(R1), R5
|
||||||
JMP finish
|
JMP return
|
||||||
|
|
||||||
TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
|
TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
|
||||||
MOVD $1, R3 // CLOCK_MONOTONIC
|
MOVD $1, R3 // CLOCK_MONOTONIC
|
||||||
@ -282,7 +312,37 @@ noswitch:
|
|||||||
RLDICR $0, R1, $59, R1 // Align for C code
|
RLDICR $0, R1, $59, R1 // Align for C code
|
||||||
MOVD R12, CTR
|
MOVD R12, CTR
|
||||||
MOVD R1, R4
|
MOVD R1, R4
|
||||||
BL (CTR) // Call from VDSO
|
|
||||||
|
// Store g on gsignal's stack, so if we receive a signal
|
||||||
|
// during VDSO code we can find the g.
|
||||||
|
// If we don't have a signal stack, we won't receive signal,
|
||||||
|
// so don't bother saving g.
|
||||||
|
// When using cgo, we already saved g on TLS, also don't save
|
||||||
|
// g here.
|
||||||
|
// Also don't save g if we are already on the signal stack.
|
||||||
|
// We won't get a nested signal.
|
||||||
|
MOVBZ runtime·iscgo(SB), R22
|
||||||
|
CMP R22, $0
|
||||||
|
BNE nosaveg
|
||||||
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
||||||
|
CMP R22, $0
|
||||||
|
BEQ nosaveg
|
||||||
|
|
||||||
|
CMP g, R22
|
||||||
|
BEQ nosaveg
|
||||||
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
||||||
|
MOVD g, (R22)
|
||||||
|
|
||||||
|
BL (CTR) // Call from VDSO
|
||||||
|
|
||||||
|
MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
|
||||||
|
|
||||||
|
JMP finish
|
||||||
|
|
||||||
|
nosaveg:
|
||||||
|
BL (CTR) // Call from VDSO
|
||||||
|
|
||||||
|
finish:
|
||||||
MOVD $0, R0 // Restore R0
|
MOVD $0, R0 // Restore R0
|
||||||
MOVD 0(R1), R3 // sec
|
MOVD 0(R1), R3 // sec
|
||||||
MOVD 8(R1), R5 // nsec
|
MOVD 8(R1), R5 // nsec
|
||||||
@ -298,7 +358,7 @@ noswitch:
|
|||||||
MOVD 32(R1), R6
|
MOVD 32(R1), R6
|
||||||
MOVD R6, m_vdsoPC(R21)
|
MOVD R6, m_vdsoPC(R21)
|
||||||
|
|
||||||
finish:
|
return:
|
||||||
// sec is in R3, nsec in R5
|
// sec is in R3, nsec in R5
|
||||||
// return nsec in R3
|
// return nsec in R3
|
||||||
MOVD $1000000000, R4
|
MOVD $1000000000, R4
|
||||||
@ -313,7 +373,7 @@ fallback:
|
|||||||
SYSCALL $SYS_clock_gettime
|
SYSCALL $SYS_clock_gettime
|
||||||
MOVD 32(R1), R3
|
MOVD 32(R1), R3
|
||||||
MOVD 40(R1), R5
|
MOVD 40(R1), R5
|
||||||
JMP finish
|
JMP return
|
||||||
|
|
||||||
TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
|
TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
|
||||||
MOVW how+0(FP), R3
|
MOVW how+0(FP), R3
|
||||||
@ -366,7 +426,7 @@ TEXT sigtramp<>(SB),NOSPLIT,$64
|
|||||||
// this might be called in external code context,
|
// this might be called in external code context,
|
||||||
// where g is not set.
|
// where g is not set.
|
||||||
MOVBZ runtime·iscgo(SB), R6
|
MOVBZ runtime·iscgo(SB), R6
|
||||||
CMP R6, $0
|
CMP R6, $0
|
||||||
BEQ 2(PC)
|
BEQ 2(PC)
|
||||||
BL runtime·load_g(SB)
|
BL runtime·load_g(SB)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user