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 ( 8 "runtime/internal/sys" 9 "unsafe" 10) 11 12type mOS struct{} 13 14//go:noescape 15//extern umtx_sleep 16func sys_umtx_sleep(addr *uint32, val, timeout int32) int32 17 18//go:noescape 19//extern umtx_wakeup 20func sys_umtx_wakeup(addr *uint32, val int32) int32 21 22//go:noescape 23//extern sysctl 24func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32 25 26func getncpu() int32 { 27 mib := [2]uint32{_CTL_HW, _HW_NCPU} 28 out := uint32(0) 29 nout := uintptr(unsafe.Sizeof(out)) 30 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 31 if ret >= 0 { 32 return int32(out) 33 } 34 return 1 35} 36 37func getPageSize() uintptr { 38 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE} 39 out := uint32(0) 40 nout := uintptr(unsafe.Sizeof(out)) 41 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 42 if ret >= 0 { 43 return uintptr(out) 44 } 45 return 0 46} 47 48//go:nosplit 49func futexsleep(addr *uint32, val uint32, ns int64) { 50 systemstack(func() { 51 futexsleep1(addr, val, ns) 52 }) 53} 54 55func futexsleep1(addr *uint32, val uint32, ns int64) { 56 var timeout int32 57 if ns >= 0 { 58 // The timeout is specified in microseconds - ensure that we 59 // do not end up dividing to zero, which would put us to sleep 60 // indefinitely... 61 timeout = timediv(ns, 1000, nil) 62 if timeout == 0 { 63 timeout = 1 64 } 65 } 66 67 // sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout 68 // expires or EBUSY if the mutex value does not match. 69 ret := sys_umtx_sleep(addr, int32(val), timeout) 70 if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY { 71 return 72 } 73 74 print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n") 75 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005 76} 77 78//go:nosplit 79func futexwakeup(addr *uint32, cnt uint32) { 80 ret := sys_umtx_wakeup(addr, int32(cnt)) 81 if ret >= 0 { 82 return 83 } 84 85 systemstack(func() { 86 print("umtx_wake_addr=", addr, " ret=", ret, "\n") 87 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006 88 }) 89} 90 91func osinit() { 92 ncpu = getncpu() 93 if physPageSize == 0 { 94 physPageSize = getPageSize() 95 } 96} 97