mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
runtime: fix plan9 monotonic time, crypto randomness
Open /dev/bintime at process start on Plan 9, marked close-on-exec, hold it open for the duration of the process, and use it for obtaining time. The change to using /dev/bintime also sets up for an upcoming Plan 9 change to add monotonic time to that file. If the monotonic field is available, then nanotime1 and time.now use that field. Otherwise they fall back to using Unix nanoseconds as "monotonic", as they always have. Before this CL, monotonic time went backward any time aux/timesync decided to adjust the system's time-of-day backward. Also use /dev/random for randomness (once at startup). Before this CL, there was no real randomness in the runtime on Plan 9 (the crypto/rand package still had some). Now there will be. Change-Id: I0c20ae79d3d96eff1a5f839a56cec5c4bc517e61 Reviewed-on: https://go-review.googlesource.com/c/go/+/656755 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Bypass: Russ Cox <rsc@golang.org> Reviewed-by: Carlos Amedee <carlos@golang.org>
This commit is contained in:
parent
6d418096b2
commit
4c32b1cc75
@ -30,7 +30,7 @@ const (
|
|||||||
func goenvs() {
|
func goenvs() {
|
||||||
buf := make([]byte, envBufSize)
|
buf := make([]byte, envBufSize)
|
||||||
copy(buf, envDir)
|
copy(buf, envDir)
|
||||||
dirfd := open(&buf[0], _OREAD, 0)
|
dirfd := open(&buf[0], _OREAD|_OCEXEC, 0)
|
||||||
if dirfd < 0 {
|
if dirfd < 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ func goenvs() {
|
|||||||
buf = buf[:len(envDir)]
|
buf = buf[:len(envDir)]
|
||||||
copy(buf, envDir)
|
copy(buf, envDir)
|
||||||
buf = append(buf, name...)
|
buf = append(buf, name...)
|
||||||
fd := open(&buf[0], _OREAD, 0)
|
fd := open(&buf[0], _OREAD|_OCEXEC, 0)
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ type mOS struct {
|
|||||||
ignoreHangup bool
|
ignoreHangup bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dupfd(old, new int32) int32
|
||||||
func closefd(fd int32) int32
|
func closefd(fd int32) int32
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -226,7 +227,7 @@ var sysstat = []byte("/dev/sysstat\x00")
|
|||||||
|
|
||||||
func getproccount() int32 {
|
func getproccount() int32 {
|
||||||
var buf [2048]byte
|
var buf [2048]byte
|
||||||
fd := open(&sysstat[0], _OREAD, 0)
|
fd := open(&sysstat[0], _OREAD|_OCEXEC, 0)
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -255,7 +256,7 @@ var pagesize = []byte(" pagesize\n")
|
|||||||
func getPageSize() uintptr {
|
func getPageSize() uintptr {
|
||||||
var buf [2048]byte
|
var buf [2048]byte
|
||||||
var pos int
|
var pos int
|
||||||
fd := open(&devswap[0], _OREAD, 0)
|
fd := open(&devswap[0], _OREAD|_OCEXEC, 0)
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
// There's not much we can do if /dev/swap doesn't
|
// There's not much we can do if /dev/swap doesn't
|
||||||
// exist. However, nothing in the memory manager uses
|
// exist. However, nothing in the memory manager uses
|
||||||
@ -314,11 +315,36 @@ func getpid() uint64 {
|
|||||||
return uint64(_atoi(c))
|
return uint64(_atoi(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
bintimeFD int32 = -1
|
||||||
|
|
||||||
|
bintimeDev = []byte("/dev/bintime\x00")
|
||||||
|
randomDev = []byte("/dev/random\x00")
|
||||||
|
)
|
||||||
|
|
||||||
func osinit() {
|
func osinit() {
|
||||||
physPageSize = getPageSize()
|
physPageSize = getPageSize()
|
||||||
initBloc()
|
initBloc()
|
||||||
ncpu = getproccount()
|
ncpu = getproccount()
|
||||||
getg().m.procid = getpid()
|
getg().m.procid = getpid()
|
||||||
|
|
||||||
|
fd := open(&bintimeDev[0], _OREAD|_OCEXEC, 0)
|
||||||
|
if fd < 0 {
|
||||||
|
fatal("cannot open /dev/bintime")
|
||||||
|
}
|
||||||
|
bintimeFD = fd
|
||||||
|
|
||||||
|
// Move fd high up, to avoid conflicts with smaller ones
|
||||||
|
// that programs might hard code, and to make exec's job easier.
|
||||||
|
// Plan 9 allocates chunks of DELTAFD=20 fds in a row,
|
||||||
|
// so 18 is near the top of what's possible.
|
||||||
|
if bintimeFD < 18 {
|
||||||
|
if dupfd(bintimeFD, 18) < 0 {
|
||||||
|
fatal("cannot dup /dev/bintime onto 18")
|
||||||
|
}
|
||||||
|
closefd(bintimeFD)
|
||||||
|
bintimeFD = 18
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
@ -329,7 +355,13 @@ func crash() {
|
|||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func readRandom(r []byte) int {
|
func readRandom(r []byte) int {
|
||||||
return 0
|
fd := open(&randomDev[0], _OREAD|_OCEXEC, 0)
|
||||||
|
if fd < 0 {
|
||||||
|
fatal("cannot open /dev/random")
|
||||||
|
}
|
||||||
|
n := int(read(fd, unsafe.Pointer(&r[0]), int32(len(r))))
|
||||||
|
closefd(fd)
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func initsig(preinit bool) {
|
func initsig(preinit bool) {
|
||||||
@ -362,17 +394,6 @@ func usleep_no_g(usec uint32) {
|
|||||||
usleep(usec)
|
usleep(usec)
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func nanotime1() int64 {
|
|
||||||
var scratch int64
|
|
||||||
ns := nsec(&scratch)
|
|
||||||
// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
|
|
||||||
if ns == 0 {
|
|
||||||
return scratch
|
|
||||||
}
|
|
||||||
return ns
|
|
||||||
}
|
|
||||||
|
|
||||||
var goexits = []byte("go: exit ")
|
var goexits = []byte("go: exit ")
|
||||||
var emptystatus = []byte("\x00")
|
var emptystatus = []byte("\x00")
|
||||||
var exiting uint32
|
var exiting uint32
|
||||||
@ -530,3 +551,59 @@ func preemptM(mp *m) {
|
|||||||
//
|
//
|
||||||
// TODO: Use a note like we use signals on POSIX OSes
|
// TODO: Use a note like we use signals on POSIX OSes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func readtime(t *uint64, min, n int) int {
|
||||||
|
if bintimeFD < 0 {
|
||||||
|
fatal("/dev/bintime not opened")
|
||||||
|
}
|
||||||
|
const uint64size = 8
|
||||||
|
r := pread(bintimeFD, unsafe.Pointer(t), int32(n*uint64size), 0)
|
||||||
|
if int(r) < min*uint64size {
|
||||||
|
fatal("cannot read /dev/bintime")
|
||||||
|
}
|
||||||
|
return int(r) / uint64size
|
||||||
|
}
|
||||||
|
|
||||||
|
// timesplit returns u/1e9, u%1e9
|
||||||
|
func timesplit(u uint64) (sec int64, nsec int32)
|
||||||
|
|
||||||
|
func frombe(u uint64) uint64 {
|
||||||
|
b := (*[8]byte)(unsafe.Pointer(&u))
|
||||||
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func nanotime1() int64 {
|
||||||
|
var t [4]uint64
|
||||||
|
if readtime(&t[0], 1, 4) == 4 {
|
||||||
|
// long read indicates new kernel sending monotonic time
|
||||||
|
// (https://github.com/rsc/plan9/commit/baf076425).
|
||||||
|
return int64(frombe(t[3]))
|
||||||
|
}
|
||||||
|
// fall back to unix time
|
||||||
|
return int64(frombe(t[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func walltime() (sec int64, nsec int32) {
|
||||||
|
var t [1]uint64
|
||||||
|
readtime(&t[0], 1, 1)
|
||||||
|
return timesplit(frombe(t[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not remove or change the type signature.
|
||||||
|
// See comment in timestub.go.
|
||||||
|
//
|
||||||
|
//go:linkname time_now time.now
|
||||||
|
func time_now() (sec int64, nsec int32, mono int64) {
|
||||||
|
var t [4]uint64
|
||||||
|
if readtime(&t[0], 1, 4) == 4 {
|
||||||
|
mono = int64(frombe(t[3])) // new kernel, use monotonic time
|
||||||
|
} else {
|
||||||
|
mono = int64(frombe(t[0])) // old kernel, fall back to unix time
|
||||||
|
}
|
||||||
|
sec, nsec = timesplit(frombe(t[0]))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -58,6 +58,12 @@ TEXT runtime·closefd(SB),NOSPLIT,$0
|
|||||||
MOVL AX, ret+4(FP)
|
MOVL AX, ret+4(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·dupfd(SB),NOSPLIT,$0
|
||||||
|
MOVL $5, AX
|
||||||
|
INT $64
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT runtime·exits(SB),NOSPLIT,$0
|
TEXT runtime·exits(SB),NOSPLIT,$0
|
||||||
MOVL $8, AX
|
MOVL $8, AX
|
||||||
INT $64
|
INT $64
|
||||||
@ -87,32 +93,15 @@ TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0
|
|||||||
MOVL AX, ret+8(FP)
|
MOVL AX, ret+8(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT nsec<>(SB),NOSPLIT,$0
|
// func timesplit(u uint64) (sec int64, nsec int32)
|
||||||
MOVL $53, AX
|
TEXT runtime·timesplit(SB),NOSPLIT,$0
|
||||||
INT $64
|
MOVL u_lo+0(FP), AX
|
||||||
RET
|
MOVL u_hi+4(FP), DX
|
||||||
|
|
||||||
TEXT runtime·nsec(SB),NOSPLIT,$8
|
|
||||||
LEAL ret+4(FP), AX
|
|
||||||
MOVL AX, 0(SP)
|
|
||||||
CALL nsec<>(SB)
|
|
||||||
CMPL AX, $0
|
|
||||||
JGE 3(PC)
|
|
||||||
MOVL $-1, ret_lo+4(FP)
|
|
||||||
MOVL $-1, ret_hi+8(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func walltime() (sec int64, nsec int32)
|
|
||||||
TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
|
||||||
CALL runtime·nanotime1(SB)
|
|
||||||
MOVL 0(SP), AX
|
|
||||||
MOVL 4(SP), DX
|
|
||||||
|
|
||||||
MOVL $1000000000, CX
|
MOVL $1000000000, CX
|
||||||
DIVL CX
|
DIVL CX
|
||||||
MOVL AX, sec_lo+0(FP)
|
MOVL AX, sec_lo+8(FP)
|
||||||
MOVL $0, sec_hi+4(FP)
|
MOVL $0, sec_hi+12(FP)
|
||||||
MOVL DX, nsec+8(FP)
|
MOVL DX, nsec+16(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·notify(SB),NOSPLIT,$0
|
TEXT runtime·notify(SB),NOSPLIT,$0
|
||||||
|
@ -53,6 +53,17 @@ TEXT runtime·closefd(SB),NOSPLIT,$0
|
|||||||
MOVL AX, ret+8(FP)
|
MOVL AX, ret+8(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·dupfd(SB),NOSPLIT,$0
|
||||||
|
MOVQ $5, BP
|
||||||
|
// Kernel expects each int32 arg to be 64-bit-aligned.
|
||||||
|
// The return value slot is where the kernel
|
||||||
|
// expects to find the second argument, so copy it there.
|
||||||
|
MOVL new+4(FP), AX
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
SYSCALL
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT runtime·exits(SB),NOSPLIT,$0
|
TEXT runtime·exits(SB),NOSPLIT,$0
|
||||||
MOVQ $8, BP
|
MOVQ $8, BP
|
||||||
SYSCALL
|
SYSCALL
|
||||||
@ -82,17 +93,9 @@ TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0
|
|||||||
MOVL AX, ret+16(FP)
|
MOVL AX, ret+16(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·nsec(SB),NOSPLIT,$0
|
// func timesplit(u uint64) (sec int64, nsec int32)
|
||||||
MOVQ $53, BP
|
TEXT runtime·timesplit(SB),NOSPLIT,$0
|
||||||
SYSCALL
|
MOVQ u+0(FP), AX
|
||||||
MOVQ AX, ret+8(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func walltime() (sec int64, nsec int32)
|
|
||||||
TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
|
||||||
CALL runtime·nanotime1(SB)
|
|
||||||
MOVQ 0(SP), AX
|
|
||||||
|
|
||||||
// generated code for
|
// generated code for
|
||||||
// func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 }
|
// func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 }
|
||||||
// adapted to reduce duplication
|
// adapted to reduce duplication
|
||||||
@ -102,10 +105,10 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
|||||||
ADDQ CX, DX
|
ADDQ CX, DX
|
||||||
RCRQ $1, DX
|
RCRQ $1, DX
|
||||||
SHRQ $29, DX
|
SHRQ $29, DX
|
||||||
MOVQ DX, sec+0(FP)
|
MOVQ DX, sec+8(FP)
|
||||||
IMULQ $1000000000, DX
|
IMULQ $1000000000, DX
|
||||||
SUBQ DX, CX
|
SUBQ DX, CX
|
||||||
MOVL CX, nsec+8(FP)
|
MOVL CX, nsec+16(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·notify(SB),NOSPLIT,$0
|
TEXT runtime·notify(SB),NOSPLIT,$0
|
||||||
|
@ -93,6 +93,13 @@ TEXT runtime·closefd(SB),NOSPLIT,$0-8
|
|||||||
MOVW R0, ret+4(FP)
|
MOVW R0, ret+4(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
//func dupfd(old, new int32) int32
|
||||||
|
TEXT runtime·dupfd(SB),NOSPLIT,$0-12
|
||||||
|
MOVW $SYS_DUP, R0
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
//func exits(msg *byte)
|
//func exits(msg *byte)
|
||||||
TEXT runtime·exits(SB),NOSPLIT,$0-4
|
TEXT runtime·exits(SB),NOSPLIT,$0-4
|
||||||
MOVW $SYS_EXITS, R0
|
MOVW $SYS_EXITS, R0
|
||||||
@ -127,26 +134,10 @@ TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-12
|
|||||||
MOVW R0, ret+8(FP)
|
MOVW R0, ret+8(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
//func nsec(*int64) int64
|
// func timesplit(u uint64) (sec int64, nsec int32)
|
||||||
TEXT runtime·nsec(SB),NOSPLIT|NOFRAME,$0-12
|
TEXT runtime·timesplit(SB),NOSPLIT,$0
|
||||||
MOVW $SYS_NSEC, R0
|
MOVW u_lo+0(FP), R1 // R1:R2 = nsec
|
||||||
SWI $0
|
MOVW u_hi+4(FP), R2
|
||||||
MOVW arg+0(FP), R1
|
|
||||||
MOVW 0(R1), R0
|
|
||||||
MOVW R0, ret_lo+4(FP)
|
|
||||||
MOVW 4(R1), R0
|
|
||||||
MOVW R0, ret_hi+8(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func walltime() (sec int64, nsec int32)
|
|
||||||
TEXT runtime·walltime(SB),NOSPLIT,$12-12
|
|
||||||
// use nsec system call to get current time in nanoseconds
|
|
||||||
MOVW $sysnsec_lo-8(SP), R0 // destination addr
|
|
||||||
MOVW R0,res-12(SP)
|
|
||||||
MOVW $SYS_NSEC, R0
|
|
||||||
SWI $0
|
|
||||||
MOVW sysnsec_lo-8(SP), R1 // R1:R2 = nsec
|
|
||||||
MOVW sysnsec_hi-4(SP), R2
|
|
||||||
|
|
||||||
// multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61)
|
// multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61)
|
||||||
// to get seconds (96 bit scaled result)
|
// to get seconds (96 bit scaled result)
|
||||||
@ -173,9 +164,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$12-12
|
|||||||
SUB.HS R5,R1 // remainder -= 10**9
|
SUB.HS R5,R1 // remainder -= 10**9
|
||||||
ADD.HS $1,R6 // sec += 1
|
ADD.HS $1,R6 // sec += 1
|
||||||
|
|
||||||
MOVW R6,sec_lo+0(FP)
|
MOVW R6,sec_lo+8(FP)
|
||||||
MOVW R7,sec_hi+4(FP)
|
MOVW R7,sec_hi+12(FP)
|
||||||
MOVW R1,nsec+8(FP)
|
MOVW R1,nsec+16(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
//func notify(fn unsafe.Pointer) int32
|
//func notify(fn unsafe.Pointer) int32
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Declarations for operating systems implementing time.now
|
// Declarations for operating systems implementing time.now
|
||||||
// indirectly, in terms of walltime and nanotime assembly.
|
// indirectly, in terms of walltime and nanotime assembly.
|
||||||
|
|
||||||
//go:build !faketime && !windows && !(linux && amd64)
|
//go:build !faketime && !windows && !(linux && amd64) && !plan9
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !wasip1 && !windows && !(linux && amd64)
|
//go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !wasip1 && !windows && !(linux && amd64) && !plan9
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user