github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/os_aix.go (about) 1 // Copyright 2018 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 // +build aix 6 7 package runtime 8 9 import ( 10 "internal/cpu" 11 "unsafe" 12 ) 13 14 const ( 15 threadStackSize = 0x100000 // size of a thread stack allocated by OS 16 ) 17 18 // funcDescriptor is a structure representing a function descriptor 19 // A variable with this type is always created in assembler 20 type funcDescriptor struct { 21 fn uintptr 22 toc uintptr 23 envPointer uintptr // unused in Golang 24 } 25 26 type mOS struct { 27 waitsema uintptr // semaphore for parking on locks 28 perrno uintptr // pointer to tls errno 29 } 30 31 //go:nosplit 32 func semacreate(mp *m) { 33 if mp.waitsema != 0 { 34 return 35 } 36 37 var sem *semt 38 39 // Call libc's malloc rather than malloc. This will 40 // allocate space on the C heap. We can't call mallocgc 41 // here because it could cause a deadlock. 42 sem = (*semt)(malloc(unsafe.Sizeof(*sem))) 43 if sem_init(sem, 0, 0) != 0 { 44 throw("sem_init") 45 } 46 mp.waitsema = uintptr(unsafe.Pointer(sem)) 47 } 48 49 //go:nosplit 50 func semasleep(ns int64) int32 { 51 _m_ := getg().m 52 if ns >= 0 { 53 var ts timespec 54 55 if clock_gettime(_CLOCK_REALTIME, &ts) != 0 { 56 throw("clock_gettime") 57 } 58 ts.tv_sec += ns / 1e9 59 ts.tv_nsec += ns % 1e9 60 if ts.tv_nsec >= 1e9 { 61 ts.tv_sec++ 62 ts.tv_nsec -= 1e9 63 } 64 65 if r, err := sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts); r != 0 { 66 if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { 67 return -1 68 } 69 println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", _m_.id) 70 throw("sem_timedwait") 71 } 72 return 0 73 } 74 for { 75 r1, err := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema))) 76 if r1 == 0 { 77 break 78 } 79 if err == _EINTR { 80 continue 81 } 82 throw("sem_wait") 83 } 84 return 0 85 } 86 87 //go:nosplit 88 func semawakeup(mp *m) { 89 if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { 90 throw("sem_post") 91 } 92 } 93 94 func osinit() { 95 ncpu = int32(sysconf(__SC_NPROCESSORS_ONLN)) 96 physPageSize = sysconf(__SC_PAGE_SIZE) 97 setupSystemConf() 98 } 99 100 // Ms related functions 101 func mpreinit(mp *m) { 102 mp.gsignal = malg(32 * 1024) // AIX wants >= 8K 103 mp.gsignal.m = mp 104 } 105 106 // errno address must be retrieved by calling _Errno libc function. 107 // This will return a pointer to errno 108 func miniterrno() { 109 mp := getg().m 110 r, _ := syscall0(&libc__Errno) 111 mp.perrno = r 112 113 } 114 115 func minit() { 116 miniterrno() 117 minitSignals() 118 } 119 120 func unminit() { 121 unminitSignals() 122 } 123 124 // tstart is a function descriptor to _tstart defined in assembly. 125 var tstart funcDescriptor 126 127 func newosproc(mp *m) { 128 var ( 129 attr pthread_attr 130 oset sigset 131 tid pthread 132 ) 133 134 if pthread_attr_init(&attr) != 0 { 135 throw("pthread_attr_init") 136 } 137 138 if pthread_attr_setstacksize(&attr, threadStackSize) != 0 { 139 throw("pthread_attr_getstacksize") 140 } 141 142 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 143 throw("pthread_attr_setdetachstate") 144 } 145 146 // Disable signals during create, so that the new thread starts 147 // with signals disabled. It will enable them in minit. 148 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 149 var ret int32 150 for tries := 0; tries < 20; tries++ { 151 // pthread_create can fail with EAGAIN for no reasons 152 // but it will be ok if it retries. 153 ret = pthread_create(&tid, &attr, &tstart, unsafe.Pointer(mp)) 154 if ret != _EAGAIN { 155 break 156 } 157 usleep(uint32(tries+1) * 1000) // Milliseconds. 158 } 159 sigprocmask(_SIG_SETMASK, &oset, nil) 160 if ret != 0 { 161 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n") 162 if ret == _EAGAIN { 163 println("runtime: may need to increase max user processes (ulimit -u)") 164 } 165 throw("newosproc") 166 } 167 168 } 169 170 func exitThread(wait *uint32) { 171 // We should never reach exitThread on AIX because we let 172 // libc clean up threads. 173 throw("exitThread") 174 } 175 176 var urandom_dev = []byte("/dev/urandom\x00") 177 178 //go:nosplit 179 func getRandomData(r []byte) { 180 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 181 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 182 closefd(fd) 183 extendRandom(r, int(n)) 184 } 185 186 func goenvs() { 187 goenvs_unix() 188 } 189 190 /* SIGNAL */ 191 192 const ( 193 _NSIG = 256 194 ) 195 196 // sigtramp is a function descriptor to _sigtramp defined in assembly 197 var sigtramp funcDescriptor 198 199 //go:nosplit 200 //go:nowritebarrierrec 201 func setsig(i uint32, fn uintptr) { 202 var sa sigactiont 203 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 204 sa.sa_mask = sigset_all 205 if fn == funcPC(sighandler) { 206 fn = uintptr(unsafe.Pointer(&sigtramp)) 207 } 208 sa.sa_handler = fn 209 sigaction(uintptr(i), &sa, nil) 210 211 } 212 213 //go:nosplit 214 //go:nowritebarrierrec 215 func setsigstack(i uint32) { 216 throw("Not yet implemented\n") 217 } 218 219 //go:nosplit 220 //go:nowritebarrierrec 221 func getsig(i uint32) uintptr { 222 var sa sigactiont 223 sigaction(uintptr(i), nil, &sa) 224 return sa.sa_handler 225 } 226 227 // setSignaltstackSP sets the ss_sp field of a stackt. 228 //go:nosplit 229 func setSignalstackSP(s *stackt, sp uintptr) { 230 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp 231 } 232 233 func (c *sigctxt) fixsigcode(sig uint32) { 234 } 235 236 func sigaddset(mask *sigset, i int) { 237 (*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63) 238 } 239 240 func sigdelset(mask *sigset, i int) { 241 (*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63) 242 } 243 244 const ( 245 _CLOCK_REALTIME = 9 246 _CLOCK_MONOTONIC = 10 247 ) 248 249 //go:nosplit 250 func nanotime() int64 { 251 tp := ×pec{} 252 if clock_gettime(_CLOCK_REALTIME, tp) != 0 { 253 throw("syscall clock_gettime failed") 254 } 255 return tp.tv_sec*1000000000 + tp.tv_nsec 256 } 257 258 func walltime() (sec int64, nsec int32) { 259 ts := ×pec{} 260 if clock_gettime(_CLOCK_REALTIME, ts) != 0 { 261 throw("syscall clock_gettime failed") 262 } 263 return ts.tv_sec, int32(ts.tv_nsec) 264 } 265 266 const ( 267 // getsystemcfg constants 268 _SC_IMPL = 2 269 _IMPL_POWER8 = 0x10000 270 _IMPL_POWER9 = 0x20000 271 ) 272 273 // setupSystemConf retrieves information about the CPU and updates 274 // cpu.HWCap variables. 275 func setupSystemConf() { 276 impl := getsystemcfg(_SC_IMPL) 277 if impl&_IMPL_POWER8 != 0 { 278 cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_2_07 279 } 280 if impl&_IMPL_POWER9 != 0 { 281 cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_3_00 282 } 283 }