import "unsafe"
type mOS struct {
- initialized bool
- mutex pthreadmutex
- cond pthreadcond
- count int
+ sema uintptr
}
func unimplemented(name string) {
//go:nosplit
func semacreate(mp *m) {
- if mp.initialized {
- return
- }
- mp.initialized = true
- if err := pthread_mutex_init(&mp.mutex, nil); err != 0 {
- throw("pthread_mutex_init")
- }
- if err := pthread_cond_init(&mp.cond, nil); err != 0 {
- throw("pthread_cond_init")
+ if mp.sema == 0 {
+ mp.sema = dispatch_semaphore_create(0)
}
}
+const (
+ _DISPATCH_TIME_NOW = uint64(0)
+ _DISPATCH_TIME_FOREVER = ^uint64(0)
+)
+
//go:nosplit
func semasleep(ns int64) int32 {
- var start int64
+ mp := getg().m
+ t := _DISPATCH_TIME_FOREVER
if ns >= 0 {
- start = nanotime()
+ t = dispatch_time(_DISPATCH_TIME_NOW, ns)
}
- mp := getg().m
- pthread_mutex_lock(&mp.mutex)
- for {
- if mp.count > 0 {
- mp.count--
- pthread_mutex_unlock(&mp.mutex)
- return 0
- }
- if ns >= 0 {
- spent := nanotime() - start
- if spent >= ns {
- pthread_mutex_unlock(&mp.mutex)
- return -1
- }
- var t timespec
- t.setNsec(ns - spent)
- err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
- if err == _ETIMEDOUT {
- pthread_mutex_unlock(&mp.mutex)
- return -1
- }
- } else {
- pthread_cond_wait(&mp.cond, &mp.mutex)
- }
+ if dispatch_semaphore_wait(mp.sema, t) != 0 {
+ return -1
}
+ return 0
}
//go:nosplit
func semawakeup(mp *m) {
- pthread_mutex_lock(&mp.mutex)
- mp.count++
- if mp.count > 0 {
- pthread_cond_signal(&mp.cond)
- }
- pthread_mutex_unlock(&mp.mutex)
+ dispatch_semaphore_signal(mp.sema)
}
// BSD interface for threading.
//go:nosplit
//go:cgo_unsafe_args
-func pthread_mutex_init(m *pthreadmutex, attr *pthreadmutexattr) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_mutex_init_trampoline)), unsafe.Pointer(&m))
-}
-func pthread_mutex_init_trampoline()
-
-//go:nosplit
-//go:cgo_unsafe_args
-func pthread_mutex_lock(m *pthreadmutex) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m))
-}
-func pthread_mutex_lock_trampoline()
-
-//go:nosplit
-//go:cgo_unsafe_args
-func pthread_mutex_unlock(m *pthreadmutex) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m))
-}
-func pthread_mutex_unlock_trampoline()
-
-//go:nosplit
-//go:cgo_unsafe_args
-func pthread_cond_init(c *pthreadcond, attr *pthreadcondattr) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_cond_init_trampoline)), unsafe.Pointer(&c))
+func dispatch_semaphore_create(val int) (sema uintptr) {
+ libcCall(unsafe.Pointer(funcPC(dispatch_semaphore_create_trampoline)), unsafe.Pointer(&val))
+ return
}
-func pthread_cond_init_trampoline()
+func dispatch_semaphore_create_trampoline()
//go:nosplit
//go:cgo_unsafe_args
-func pthread_cond_wait(c *pthreadcond, m *pthreadmutex) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_cond_wait_trampoline)), unsafe.Pointer(&c))
+func dispatch_semaphore_wait(sema uintptr, t uint64) int32 {
+ return libcCall(unsafe.Pointer(funcPC(dispatch_semaphore_wait_trampoline)), unsafe.Pointer(&sema))
}
-func pthread_cond_wait_trampoline()
+func dispatch_semaphore_wait_trampoline()
//go:nosplit
//go:cgo_unsafe_args
-func pthread_cond_timedwait_relative_np(c *pthreadcond, m *pthreadmutex, t *timespec) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c))
+func dispatch_semaphore_signal(sema uintptr) {
+ libcCall(unsafe.Pointer(funcPC(dispatch_semaphore_signal_trampoline)), unsafe.Pointer(&sema))
}
-func pthread_cond_timedwait_relative_np_trampoline()
+func dispatch_semaphore_signal_trampoline()
//go:nosplit
//go:cgo_unsafe_args
-func pthread_cond_signal(c *pthreadcond) int32 {
- return libcCall(unsafe.Pointer(funcPC(pthread_cond_signal_trampoline)), unsafe.Pointer(&c))
+func dispatch_time(base uint64, delta int64) (result uint64) {
+ libcCall(unsafe.Pointer(funcPC(dispatch_time_trampoline)), unsafe.Pointer(&base))
+ return
}
-func pthread_cond_signal_trampoline()
+func dispatch_time_trampoline()
// Not used on Darwin, but must be defined.
func exitThread(wait *uint32) {
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_mutex_init pthread_mutex_init "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_cond_init pthread_cond_init "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_cond_wait pthread_cond_wait "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_dispatch_semaphore_create dispatch_semaphore_create "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_dispatch_semaphore_wait dispatch_semaphore_wait "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_dispatch_semaphore_signal dispatch_semaphore_signal "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_dispatch_time dispatch_time "/usr/lib/libSystem.B.dylib"
// Magic incantation to get libSystem actually dynamically linked.
// TODO: Why does the code require this? See cmd/link/internal/ld/go.go
POPL BP
RET
-TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_create_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
- MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 mutex
- MOVL AX, 0(SP)
- MOVL 4(CX), AX // arg 2 attr
- MOVL AX, 4(SP)
- CALL libc_pthread_mutex_init(SB)
- MOVL BP, SP
- POPL BP
- RET
-
-TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
- PUSHL BP
- MOVL SP, BP
- SUBL $8, SP
- MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 mutex
- MOVL AX, 0(SP)
- CALL libc_pthread_mutex_lock(SB)
- MOVL BP, SP
- POPL BP
- RET
-
-TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
- PUSHL BP
- MOVL SP, BP
- SUBL $8, SP
- MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 mutex
+ MOVL 16(SP), BX
+ MOVL 0(BX), AX // arg 1 value
MOVL AX, 0(SP)
- CALL libc_pthread_mutex_unlock(SB)
+ CALL libc_dispatch_semaphore_create(SB)
+ MOVL AX, 4(BX) // result sema
MOVL BP, SP
POPL BP
RET
-TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_wait_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
- SUBL $8, SP
- MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 cond
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 sema
MOVL AX, 0(SP)
- MOVL 4(CX), AX // arg 2 attr
+ MOVL 4(CX), AX // arg 2 timeout/0
MOVL AX, 4(SP)
- CALL libc_pthread_cond_init(SB)
+ MOVL 8(CX), AX // arg 2 timeout/1
+ MOVL AX, 8(SP)
+ CALL libc_dispatch_semaphore_wait(SB)
MOVL BP, SP
POPL BP
RET
-TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_signal_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 cond
+ MOVL 0(CX), AX // arg 1 sema
MOVL AX, 0(SP)
- MOVL 4(CX), AX // arg 2 mutex
- MOVL AX, 4(SP)
- CALL libc_pthread_cond_wait(SB)
+ CALL libc_dispatch_semaphore_signal(SB)
MOVL BP, SP
POPL BP
RET
-TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_time_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $24, SP
- MOVL 32(SP), CX
- MOVL 0(CX), AX // arg 1 cond
+ MOVL 32(SP), BX
+ MOVL 0(BX), AX // arg 1 base/0
MOVL AX, 0(SP)
- MOVL 4(CX), AX // arg 2 mutex
+ MOVL 4(BX), AX // arg 1 base/1
MOVL AX, 4(SP)
- MOVL 8(CX), AX // arg 3 timeout
+ MOVL 8(BX), AX // arg 2 delta/0
MOVL AX, 8(SP)
- CALL libc_pthread_cond_timedwait_relative_np(SB)
- MOVL BP, SP
- POPL BP
- RET
-
-TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
- PUSHL BP
- MOVL SP, BP
- SUBL $8, SP
- MOVL 16(SP), CX
- MOVL 0(CX), AX // arg 1 cond
- MOVL AX, 0(SP)
- CALL libc_pthread_cond_signal(SB)
+ MOVL 12(BX), AX // arg 2 delta/1
+ MOVL AX, 12(SP)
+ CALL libc_dispatch_time(SB)
+ MOVL AX, 16(BX) // result/0
+ MOVL DX, 20(BX) // result/1
MOVL BP, SP
POPL BP
RET
POPQ BP
RET
-TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_create_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
- MOVQ 8(DI), SI // arg 2 attr
- MOVQ 0(DI), DI // arg 1 mutex
- CALL libc_pthread_mutex_init(SB)
- POPQ BP
- RET
-
-TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
- PUSHQ BP
- MOVQ SP, BP
- MOVQ 0(DI), DI // arg 1 mutex
- CALL libc_pthread_mutex_lock(SB)
- POPQ BP
- RET
-
-TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
- PUSHQ BP
- MOVQ SP, BP
- MOVQ 0(DI), DI // arg 1 mutex
- CALL libc_pthread_mutex_unlock(SB)
- POPQ BP
- RET
-
-TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
- PUSHQ BP
- MOVQ SP, BP
- MOVQ 8(DI), SI // arg 2 attr
- MOVQ 0(DI), DI // arg 1 cond
- CALL libc_pthread_cond_init(SB)
+ MOVQ DI, BX
+ MOVQ 0(BX), DI // arg 1 value
+ CALL libc_dispatch_semaphore_create(SB)
+ MOVQ AX, 8(BX) // result sema
POPQ BP
RET
-TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_wait_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
- MOVQ 8(DI), SI // arg 2 mutex
- MOVQ 0(DI), DI // arg 1 cond
- CALL libc_pthread_cond_wait(SB)
+ MOVQ 8(DI), SI // arg 2 timeout
+ MOVQ 0(DI), DI // arg 1 sema
+ CALL libc_dispatch_semaphore_wait(SB)
+ TESTQ AX, AX // For safety convert 64-bit result to int32 0 or 1.
+ JEQ 2(PC)
+ MOVL $1, AX
POPQ BP
RET
-TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_semaphore_signal_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
- MOVQ 8(DI), SI // arg 2 mutex
- MOVQ 16(DI), DX // arg 3 timeout
- MOVQ 0(DI), DI // arg 1 cond
- CALL libc_pthread_cond_timedwait_relative_np(SB)
+ MOVQ 0(DI), DI // arg 1 sema
+ CALL libc_dispatch_semaphore_signal(SB)
POPQ BP
RET
-TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
+TEXT runtime·dispatch_time_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
- MOVQ 0(DI), DI // arg 1 cond
- CALL libc_pthread_cond_signal(SB)
+ MOVQ DI, BX
+ MOVQ 0(BX), DI // arg 1 base
+ MOVQ 8(BX), SI // arg 2 delta
+ CALL libc_dispatch_time(SB)
+ MOVQ AX, 16(BX)
POPQ BP
RET
BL libc_raise(SB)
RET
-TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
- MOVW 4(R0), R1 // arg 2 attr
- MOVW 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_init(SB)
- RET
-
-TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
- MOVW 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_lock(SB)
- RET
-
-TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
- MOVW 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_unlock(SB)
- RET
-
-TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
- MOVW 4(R0), R1 // arg 2 attr
- MOVW 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_init(SB)
+TEXT runtime·dispatch_semaphore_create_trampoline(SB),NOSPLIT,$0
+ MOVW R0, R8
+ MOVW 0(R8), R0 // arg 1 value
+ BL libc_dispatch_semaphore_create(SB)
+ MOVW R0, 4(R8) // result sema
RET
-TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
- MOVW 4(R0), R1 // arg 2 mutex
- MOVW 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_wait(SB)
+TEXT runtime·dispatch_semaphore_wait_trampoline(SB),NOSPLIT,$0
+ MOVW 4(R0), R1 // arg 2 timeout/0
+ MOVW 8(R0), R2 // arg 2 timeout/1
+ MOVW 0(R0), R0 // arg 1 sema
+ BL libc_dispatch_semaphore_wait(SB)
RET
-TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
- MOVW 4(R0), R1 // arg 2 mutex
- MOVW 8(R0), R2 // arg 3 timeout
- MOVW 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_timedwait_relative_np(SB)
+TEXT runtime·dispatch_semaphore_signal_trampoline(SB),NOSPLIT,$0
+ MOVW 0(R0), R0 // arg 1 sema
+ BL libc_dispatch_semaphore_signal(SB)
RET
-TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
- MOVW 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_signal(SB)
+TEXT runtime·dispatch_time_trampoline(SB),NOSPLIT,$0
+ MOVW R0, R8
+ MOVW 0(R8), R0 // arg 1 base/0
+ MOVW 4(R8), R1 // arg 1 base/1
+ MOVW 8(R8), R2 // arg 2 delta/0
+ MOVW 12(R8), R3 // arg 2 delta/1
+ BL libc_dispatch_time(SB)
+ MOVW R0, 16(R8) // result/0
+ MOVW R1, 20(R8) // result/1
RET
// syscall calls a function in libc on behalf of the syscall package.
BL libc_raise(SB)
RET
-TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
- MOVD 8(R0), R1 // arg 2 attr
- MOVD 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_init(SB)
- RET
-
-TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
- MOVD 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_lock(SB)
- RET
-
-TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
- MOVD 0(R0), R0 // arg 1 mutex
- BL libc_pthread_mutex_unlock(SB)
- RET
-
-TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
- MOVD 8(R0), R1 // arg 2 attr
- MOVD 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_init(SB)
+TEXT runtime·dispatch_semaphore_create_trampoline(SB),NOSPLIT,$0
+ MOVD R0, R19
+ MOVD 0(R19), R0 // arg 1 value
+ BL libc_dispatch_semaphore_create(SB)
+ MOVD R0, 8(R19) // result sema
RET
-TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
- MOVD 8(R0), R1 // arg 2 mutex
- MOVD 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_wait(SB)
+TEXT runtime·dispatch_semaphore_wait_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 timeout
+ MOVD 0(R0), R0 // arg 1 sema
+ BL libc_dispatch_semaphore_wait(SB)
+ CMP $0, R0 // For safety convert 64-bit result to int32 0 or 1.
+ BEQ 2(PC)
+ MOVW $1, R0
RET
-TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
- MOVD 8(R0), R1 // arg 2 mutex
- MOVD 16(R0), R2 // arg 3 timeout
- MOVD 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_timedwait_relative_np(SB)
+TEXT runtime·dispatch_semaphore_signal_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R0 // arg 1 sema
+ BL libc_dispatch_semaphore_signal(SB)
RET
-TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
- MOVD 0(R0), R0 // arg 1 cond
- BL libc_pthread_cond_signal(SB)
+TEXT runtime·dispatch_time_trampoline(SB),NOSPLIT,$0
+ MOVD R0, R19
+ MOVD 0(R19), R0 // arg 1 base
+ MOVD 8(R19), R1 // arg 2 delta
+ BL libc_dispatch_time(SB)
+ MOVD R0, 16(R19) // result
RET
// syscall calls a function in libc on behalf of the syscall package.