package runtime
import "unsafe"
type mOS struct {
initialized bool
mutex pthreadmutex
cond pthreadcond
count int
}
func unimplemented (name string ) {
println (name , "not implemented" )
*(*int )(unsafe .Pointer (uintptr (1231 ))) = 1231
}
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" )
}
}
func semasleep (ns int64 ) int32 {
var start int64
if ns >= 0 {
start = nanotime ()
}
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 )
}
}
}
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 )
}
var sigNoteRead , sigNoteWrite int32
func sigNoteSetup (*note ) {
if sigNoteRead != 0 || sigNoteWrite != 0 {
throw ("duplicate sigNoteSetup" )
}
var errno int32
sigNoteRead , sigNoteWrite , errno = pipe ()
if errno != 0 {
throw ("pipe failed" )
}
closeonexec (sigNoteRead )
closeonexec (sigNoteWrite )
setNonblock (sigNoteWrite )
}
func sigNoteWakeup (*note ) {
var b byte
write (uintptr (sigNoteWrite ), unsafe .Pointer (&b ), 1 )
}
func sigNoteSleep (*note ) {
entersyscallblock ()
var b byte
read (sigNoteRead , unsafe .Pointer (&b ), 1 )
exitsyscall ()
}
func osinit () {
ncpu = getncpu ()
physPageSize = getPageSize ()
}
func sysctlbynameInt32 (name []byte ) (int32 , int32 ) {
out := int32 (0 )
nout := unsafe .Sizeof (out )
ret := sysctlbyname (&name [0 ], (*byte )(unsafe .Pointer (&out )), &nout , nil , 0 )
return ret , out
}
func internal_cpu_getsysctlbyname (name []byte ) (int32 , int32 ) {
return sysctlbynameInt32 (name )
}
const (
_CTL_HW = 6
_HW_NCPU = 3
_HW_PAGESIZE = 7
)
func getncpu () int32 {
mib := [2 ]uint32 {_CTL_HW , _HW_NCPU }
out := uint32 (0 )
nout := unsafe .Sizeof (out )
ret := sysctl (&mib [0 ], 2 , (*byte )(unsafe .Pointer (&out )), &nout , nil , 0 )
if ret >= 0 && int32 (out ) > 0 {
return int32 (out )
}
return 1
}
func getPageSize () uintptr {
mib := [2 ]uint32 {_CTL_HW , _HW_PAGESIZE }
out := uint32 (0 )
nout := unsafe .Sizeof (out )
ret := sysctl (&mib [0 ], 2 , (*byte )(unsafe .Pointer (&out )), &nout , nil , 0 )
if ret >= 0 && int32 (out ) > 0 {
return uintptr (out )
}
return 0
}
var urandom_dev = []byte ("/dev/urandom\x00" )
func getRandomData (r []byte ) {
fd := open (&urandom_dev [0 ], 0 , 0 )
n := read (fd , unsafe .Pointer (&r [0 ]), int32 (len (r )))
closefd (fd )
extendRandom (r , int (n ))
}
func goenvs () {
goenvs_unix ()
}
func newosproc (mp *m ) {
stk := unsafe .Pointer (mp .g0 .stack .hi )
if false {
print ("newosproc stk=" , stk , " m=" , mp , " g=" , mp .g0 , " id=" , mp .id , " ostk=" , &mp , "\n" )
}
var attr pthreadattr
var err int32
err = pthread_attr_init (&attr )
if err != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
var stacksize uintptr
if pthread_attr_getstacksize (&attr , &stacksize ) != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
mp .g0 .stack .hi = stacksize
if pthread_attr_setdetachstate (&attr , _PTHREAD_CREATE_DETACHED ) != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
var oset sigset
sigprocmask (_SIG_SETMASK , &sigset_all , &oset )
err = pthread_create (&attr , funcPC (mstart_stub ), unsafe .Pointer (mp ))
sigprocmask (_SIG_SETMASK , &oset , nil )
if err != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
}
func mstart_stub ()
func newosproc0 (stacksize uintptr , fn uintptr ) {
var attr pthreadattr
var err int32
err = pthread_attr_init (&attr )
if err != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
if pthread_attr_getstacksize (&attr , &stacksize ) != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
g0 .stack .hi = stacksize
memstats .stacks_sys .add (int64 (stacksize ))
if pthread_attr_setdetachstate (&attr , _PTHREAD_CREATE_DETACHED ) != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
var oset sigset
sigprocmask (_SIG_SETMASK , &sigset_all , &oset )
err = pthread_create (&attr , fn , nil )
sigprocmask (_SIG_SETMASK , &oset , nil )
if err != 0 {
write (2 , unsafe .Pointer (&failthreadcreate [0 ]), int32 (len (failthreadcreate )))
exit (1 )
}
}
var failallocatestack = []byte ("runtime: failed to allocate stack for the new OS thread\n" )
var failthreadcreate = []byte ("runtime: failed to create new OS thread\n" )
func libpreinit () {
initsig (true )
}
func mpreinit (mp *m ) {
mp .gsignal = malg (32 * 1024 )
mp .gsignal .m = mp
if GOOS == "darwin" && GOARCH == "arm64" {
mlock (unsafe .Pointer (mp .gsignal .stack .hi -physPageSize ), physPageSize )
}
}
func minit () {
if !(GOOS == "ios" && GOARCH == "arm64" ) {
minitSignalStack ()
}
minitSignalMask ()
getg ().m .procid = uint64 (pthread_self ())
}
func unminit () {
if !(GOOS == "ios" && GOARCH == "arm64" ) {
unminitSignals ()
}
}
func mdestroy (mp *m ) {
}
func osyield () {
usleep (1 )
}
const (
_NSIG = 32
_SI_USER = 0
_SIG_BLOCK = 1
_SIG_UNBLOCK = 2
_SIG_SETMASK = 3
_SS_DISABLE = 4
)
type sigset uint32
var sigset_all = ^sigset (0 )
func setsig (i uint32 , fn uintptr ) {
var sa usigactiont
sa .sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
sa .sa_mask = ^uint32 (0 )
if fn == funcPC (sighandler ) {
if iscgo {
fn = funcPC (cgoSigtramp )
} else {
fn = funcPC (sigtramp )
}
}
*(*uintptr )(unsafe .Pointer (&sa .__sigaction_u )) = fn
sigaction (i , &sa , nil )
}
func sigtramp ()
func cgoSigtramp ()
func setsigstack (i uint32 ) {
var osa usigactiont
sigaction (i , nil , &osa )
handler := *(*uintptr )(unsafe .Pointer (&osa .__sigaction_u ))
if osa .sa_flags &_SA_ONSTACK != 0 {
return
}
var sa usigactiont
*(*uintptr )(unsafe .Pointer (&sa .__sigaction_u )) = handler
sa .sa_mask = osa .sa_mask
sa .sa_flags = osa .sa_flags | _SA_ONSTACK
sigaction (i , &sa , nil )
}
func getsig (i uint32 ) uintptr {
var sa usigactiont
sigaction (i , nil , &sa )
return *(*uintptr )(unsafe .Pointer (&sa .__sigaction_u ))
}
func setSignalstackSP (s *stackt , sp uintptr ) {
*(*uintptr )(unsafe .Pointer (&s .ss_sp )) = sp
}
func sigaddset (mask *sigset , i int ) {
*mask |= 1 << (uint32 (i ) - 1 )
}
func sigdelset (mask *sigset , i int ) {
*mask &^= 1 << (uint32 (i ) - 1 )
}
var executablePath string
func sysargs (argc int32 , argv **byte ) {
n := argc + 1
for argv_index (argv , n ) != nil {
n ++
}
executablePath = gostringnocopy (argv_index (argv , n +1 ))
const prefix = "executable_path="
if len (executablePath ) > len (prefix ) && executablePath [:len (prefix )] == prefix {
executablePath = executablePath [len (prefix ):]
}
}
func signalM (mp *m , sig int ) {
pthread_kill (pthread (mp .procid ), uint32 (sig ))
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .