1// Copyright 2019 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 5// This file is derived from os_aix.go. 6 7package runtime 8 9import "unsafe" 10 11//extern sysconf 12func sysconf(int32) _C_long 13 14//extern getpagesize 15func getPageSize() int32 16 17type mOS struct { 18 waitsema uintptr // semaphore for parking on locks 19} 20 21//extern malloc 22func libc_malloc(uintptr) unsafe.Pointer 23 24//go:noescape 25//extern sem_init 26func sem_init(sem *_sem_t, pshared int32, value uint32) int32 27 28//go:noescape 29//extern sem_wait 30func sem_wait(sem *_sem_t) int32 31 32//go:noescape 33//extern sem_post 34func sem_post(sem *_sem_t) int32 35 36//go:noescape 37//extern sem_timedwait 38func sem_timedwait(sem *_sem_t, timeout *timespec) int32 39 40//go:noescape 41//extern clock_gettime 42func clock_gettime(clock_id int32, timeout *timespec) int32 43 44//go:nosplit 45func semacreate(mp *m) { 46 if mp.waitsema != 0 { 47 return 48 } 49 50 var sem *_sem_t 51 52 // Call libc's malloc rather than malloc. This will 53 // allocate space on the C heap. We can't call malloc 54 // here because it could cause a deadlock. 55 sem = (*_sem_t)(libc_malloc(unsafe.Sizeof(*sem))) 56 if sem_init(sem, 0, 0) != 0 { 57 throw("sem_init") 58 } 59 mp.waitsema = uintptr(unsafe.Pointer(sem)) 60} 61 62//go:nosplit 63func semasleep(ns int64) int32 { 64 _m_ := getg().m 65 if ns >= 0 { 66 var ts timespec 67 68 if clock_gettime(_CLOCK_REALTIME, &ts) != 0 { 69 throw("clock_gettime") 70 } 71 72 sec := int64(ts.tv_sec) + ns/1e9 73 nsec := int64(ts.tv_nsec) + ns%1e9 74 if nsec >= 1e9 { 75 sec++ 76 nsec -= 1e9 77 } 78 if sec != int64(timespec_sec_t(sec)) { 79 // Handle overflows (timespec_sec_t is 32-bit in 32-bit applications) 80 sec = 1<<31 - 1 81 } 82 ts.tv_sec = timespec_sec_t(sec) 83 ts.tv_nsec = timespec_nsec_t(nsec) 84 85 if sem_timedwait((*_sem_t)(unsafe.Pointer(_m_.waitsema)), &ts) != 0 { 86 err := errno() 87 if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { 88 return -1 89 } 90 throw("sem_timedwait") 91 } 92 return 0 93 } 94 for { 95 r1 := sem_wait((*_sem_t)(unsafe.Pointer(_m_.waitsema))) 96 if r1 == 0 { 97 break 98 } 99 if errno() == _EINTR { 100 continue 101 } 102 throw("sem_wait") 103 } 104 return 0 105} 106 107//go:nosplit 108func semawakeup(mp *m) { 109 if sem_post((*_sem_t)(unsafe.Pointer(mp.waitsema))) != 0 { 110 throw("sem_post") 111 } 112} 113 114func getncpu() int32 { 115 n := int32(sysconf(__SC_NPROCESSORS_ONLN)) 116 if n < 1 { 117 return 1 118 } 119 return n 120} 121 122func osinit() { 123 ncpu = getncpu() 124 if physPageSize == 0 { 125 physPageSize = uintptr(getPageSize()) 126 } 127} 128