1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package runtime
6
7import "unsafe"
8
9type mOS struct {
10	unused byte
11}
12
13//go:noescape
14//extern umtx_sleep
15func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
16
17//go:noescape
18//extern umtx_wakeup
19func sys_umtx_wakeup(addr *uint32, val int32) int32
20
21//go:nosplit
22func futexsleep(addr *uint32, val uint32, ns int64) {
23	systemstack(func() {
24		futexsleep1(addr, val, ns)
25	})
26}
27
28func futexsleep1(addr *uint32, val uint32, ns int64) {
29	var timeout int32
30	if ns >= 0 {
31		// The timeout is specified in microseconds - ensure that we
32		// do not end up dividing to zero, which would put us to sleep
33		// indefinitely...
34		timeout = timediv(ns, 1000, nil)
35		if timeout == 0 {
36			timeout = 1
37		}
38	}
39
40	// sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
41	// expires or EBUSY if the mutex value does not match.
42	ret := sys_umtx_sleep(addr, int32(val), timeout)
43	if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
44		return
45	}
46
47	print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
48	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
49}
50
51//go:nosplit
52func futexwakeup(addr *uint32, cnt uint32) {
53	ret := sys_umtx_wakeup(addr, int32(cnt))
54	if ret >= 0 {
55		return
56	}
57
58	systemstack(func() {
59		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
60		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
61	})
62}
63