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