Commit a2f37b7f authored by Mike Appleby's avatar Mike Appleby Committed by Chris Broadfoot

[release-branch.go1.7] runtime: sleep on CLOCK_MONOTONIC in futexsleep1 on freebsd

In FreeBSD 10.0, the _umtx_op syscall was changed to allow sleeping on
any supported clock, but the default clock was switched from a monotonic
clock to CLOCK_REALTIME.

Prior to 10.0, the __umtx_op_wait* functions ignored the fourth argument
to _umtx_op (uaddr1), expected the fifth argument (uaddr2) to be a
struct timespec pointer, and used a monotonic clock (nanouptime(9)) for
timeout calculations.

Since 10.0, if callers want a clock other than CLOCK_REALTIME, they must
call _umtx_op with uaddr1 set to a value greater than sizeof(struct
timespec), and with uaddr2 as pointer to a struct _umtx_time, rather
than a timespec. Callers can set the _clockid field of the struct
_umtx_time to request the clock they want.

The relevant FreeBSD commit:
    https://svnweb.freebsd.org/base?view=revision&revision=232144

Fixes #17168

Change-Id: I3dd7b32b683622b8d7b4a6a8f9eb56401bed6bdf
Reviewed-on: https://go-review.googlesource.com/30154Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/31269
parent ca0b97e8
...@@ -23,6 +23,7 @@ package runtime ...@@ -23,6 +23,7 @@ package runtime
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ucontext.h> #include <sys/ucontext.h>
#include <sys/umtx.h> #include <sys/umtx.h>
#include <sys/_umtx.h>
#include <sys/rtprio.h> #include <sys/rtprio.h>
#include <sys/thr.h> #include <sys/thr.h>
#include <sys/_sigset.h> #include <sys/_sigset.h>
...@@ -49,6 +50,8 @@ const ( ...@@ -49,6 +50,8 @@ const (
SA_RESTART = C.SA_RESTART SA_RESTART = C.SA_RESTART
SA_ONSTACK = C.SA_ONSTACK SA_ONSTACK = C.SA_ONSTACK
CLOCK_MONOTONIC = C.CLOCK_MONOTONIC
UMTX_OP_WAIT_UINT = C.UMTX_OP_WAIT_UINT UMTX_OP_WAIT_UINT = C.UMTX_OP_WAIT_UINT
UMTX_OP_WAIT_UINT_PRIVATE = C.UMTX_OP_WAIT_UINT_PRIVATE UMTX_OP_WAIT_UINT_PRIVATE = C.UMTX_OP_WAIT_UINT_PRIVATE
UMTX_OP_WAKE = C.UMTX_OP_WAKE UMTX_OP_WAKE = C.UMTX_OP_WAKE
...@@ -130,4 +133,6 @@ type Timespec C.struct_timespec ...@@ -130,4 +133,6 @@ type Timespec C.struct_timespec
type Timeval C.struct_timeval type Timeval C.struct_timeval
type Itimerval C.struct_itimerval type Itimerval C.struct_itimerval
type Umtx_time C.struct__umtx_time
type Kevent C.struct_kevent type Kevent C.struct_kevent
...@@ -24,6 +24,8 @@ const ( ...@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2 _SA_RESTART = 0x2
_SA_ONSTACK = 0x1 _SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb _UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3 _UMTX_OP_WAKE = 0x3
...@@ -203,6 +205,12 @@ type itimerval struct { ...@@ -203,6 +205,12 @@ type itimerval struct {
it_value timeval it_value timeval
} }
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct { type keventt struct {
ident uint32 ident uint32
filter int16 filter int16
......
...@@ -24,6 +24,8 @@ const ( ...@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2 _SA_RESTART = 0x2
_SA_ONSTACK = 0x1 _SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb _UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3 _UMTX_OP_WAKE = 0x3
...@@ -214,6 +216,12 @@ type itimerval struct { ...@@ -214,6 +216,12 @@ type itimerval struct {
it_value timeval it_value timeval
} }
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct { type keventt struct {
ident uint64 ident uint64
filter int16 filter int16
......
...@@ -24,6 +24,8 @@ const ( ...@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2 _SA_RESTART = 0x2
_SA_ONSTACK = 0x1 _SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb _UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3 _UMTX_OP_WAKE = 0x3
...@@ -176,6 +178,12 @@ type itimerval struct { ...@@ -176,6 +178,12 @@ type itimerval struct {
it_value timeval it_value timeval
} }
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct { type keventt struct {
ident uint32 ident uint32
filter int16 filter int16
......
...@@ -35,7 +35,7 @@ func raise(sig int32) ...@@ -35,7 +35,7 @@ func raise(sig int32)
func raiseproc(sig int32) func raiseproc(sig int32)
//go:noescape //go:noescape
func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32 func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
func osyield() func osyield()
...@@ -70,14 +70,14 @@ func futexsleep(addr *uint32, val uint32, ns int64) { ...@@ -70,14 +70,14 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
} }
func futexsleep1(addr *uint32, val uint32, ns int64) { func futexsleep1(addr *uint32, val uint32, ns int64) {
var tsp *timespec var utp *umtx_time
if ns >= 0 { if ns >= 0 {
var ts timespec var ut umtx_time
ts.tv_nsec = 0 ut._clockid = _CLOCK_MONOTONIC
ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec))))) ut._timeout.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ut._timeout.tv_nsec)))))
tsp = &ts utp = &ut
} }
ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp) ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp)
if ret >= 0 || ret == -_EINTR { if ret >= 0 || ret == -_EINTR {
return return
} }
...@@ -87,7 +87,7 @@ func futexsleep1(addr *uint32, val uint32, ns int64) { ...@@ -87,7 +87,7 @@ func futexsleep1(addr *uint32, val uint32, ns int64) {
//go:nosplit //go:nosplit
func futexwakeup(addr *uint32, cnt uint32) { func futexwakeup(addr *uint32, cnt uint32) {
ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil) ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil)
if ret >= 0 { if ret >= 0 {
return return
} }
......
...@@ -14,8 +14,8 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0 ...@@ -14,8 +14,8 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI MOVQ addr+0(FP), DI
MOVL mode+8(FP), SI MOVL mode+8(FP), SI
MOVL val+12(FP), DX MOVL val+12(FP), DX
MOVQ ptr2+16(FP), R10 MOVQ uaddr1+16(FP), R10
MOVQ ts+24(FP), R8 MOVQ ut+24(FP), R8
MOVL $454, AX MOVL $454, AX
SYSCALL SYSCALL
MOVL AX, ret+32(FP) MOVL AX, ret+32(FP)
......
...@@ -45,7 +45,7 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0 ...@@ -45,7 +45,7 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
MOVW addr+0(FP), R0 MOVW addr+0(FP), R0
MOVW mode+4(FP), R1 MOVW mode+4(FP), R1
MOVW val+8(FP), R2 MOVW val+8(FP), R2
MOVW ptr2+12(FP), R3 MOVW uaddr1+12(FP), R3
ADD $20, R13 // arg 5 is passed on stack ADD $20, R13 // arg 5 is passed on stack
MOVW $SYS__umtx_op, R7 MOVW $SYS__umtx_op, R7
SWI $0 SWI $0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment