github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/runtime/os_darwin.go (about) 1 // Copyright 2009 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 package runtime 6 7 import "unsafe" 8 9 type mOS struct { 10 initialized bool 11 mutex pthreadmutex 12 cond pthreadcond 13 count int 14 } 15 16 func unimplemented(name string) { 17 println(name, "not implemented") 18 *(*int)(unsafe.Pointer(uintptr(1231))) = 1231 19 } 20 21 //go:nosplit 22 func semacreate(mp *m) { 23 if mp.initialized { 24 return 25 } 26 mp.initialized = true 27 if err := pthread_mutex_init(&mp.mutex, nil); err != 0 { 28 throw("pthread_mutex_init") 29 } 30 if err := pthread_cond_init(&mp.cond, nil); err != 0 { 31 throw("pthread_cond_init") 32 } 33 } 34 35 //go:nosplit 36 func semasleep(ns int64) int32 { 37 var start int64 38 if ns >= 0 { 39 start = nanotime() 40 } 41 mp := getg().m 42 pthread_mutex_lock(&mp.mutex) 43 for { 44 if mp.count > 0 { 45 mp.count-- 46 pthread_mutex_unlock(&mp.mutex) 47 return 0 48 } 49 if ns >= 0 { 50 spent := nanotime() - start 51 if spent >= ns { 52 pthread_mutex_unlock(&mp.mutex) 53 return -1 54 } 55 var t timespec 56 t.set_nsec(ns - spent) 57 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t) 58 if err == _ETIMEDOUT { 59 pthread_mutex_unlock(&mp.mutex) 60 return -1 61 } 62 } else { 63 pthread_cond_wait(&mp.cond, &mp.mutex) 64 } 65 } 66 } 67 68 //go:nosplit 69 func semawakeup(mp *m) { 70 pthread_mutex_lock(&mp.mutex) 71 mp.count++ 72 if mp.count > 0 { 73 pthread_cond_signal(&mp.cond) 74 } 75 pthread_mutex_unlock(&mp.mutex) 76 } 77 78 // BSD interface for threading. 79 func osinit() { 80 // pthread_create delayed until end of goenvs so that we 81 // can look at the environment first. 82 83 ncpu = getncpu() 84 physPageSize = getPageSize() 85 } 86 87 const ( 88 _CTL_HW = 6 89 _HW_NCPU = 3 90 _HW_PAGESIZE = 7 91 ) 92 93 func getncpu() int32 { 94 // Use sysctl to fetch hw.ncpu. 95 mib := [2]uint32{_CTL_HW, _HW_NCPU} 96 out := uint32(0) 97 nout := unsafe.Sizeof(out) 98 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 99 if ret >= 0 && int32(out) > 0 { 100 return int32(out) 101 } 102 return 1 103 } 104 105 func getPageSize() uintptr { 106 // Use sysctl to fetch hw.pagesize. 107 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE} 108 out := uint32(0) 109 nout := unsafe.Sizeof(out) 110 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 111 if ret >= 0 && int32(out) > 0 { 112 return uintptr(out) 113 } 114 return 0 115 } 116 117 var urandom_dev = []byte("/dev/urandom\x00") 118 119 //go:nosplit 120 func getRandomData(r []byte) { 121 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 122 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 123 closefd(fd) 124 extendRandom(r, int(n)) 125 } 126 127 func goenvs() { 128 goenvs_unix() 129 } 130 131 // May run with m.p==nil, so write barriers are not allowed. 132 //go:nowritebarrierrec 133 func newosproc(mp *m) { 134 stk := unsafe.Pointer(mp.g0.stack.hi) 135 if false { 136 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") 137 } 138 139 // Initialize an attribute object. 140 var attr pthreadattr 141 var err int32 142 err = pthread_attr_init(&attr) 143 if err != 0 { 144 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 145 exit(1) 146 } 147 148 // Set the stack size we want to use. 64KB for now. 149 // TODO: just use OS default size? 150 const stackSize = 1 << 16 151 if pthread_attr_setstacksize(&attr, stackSize) != 0 { 152 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 153 exit(1) 154 } 155 //mSysStatInc(&memstats.stacks_sys, stackSize) //TODO: do this? 156 157 // Tell the pthread library we won't join with this thread. 158 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 159 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 160 exit(1) 161 } 162 163 // Finally, create the thread. It starts at mstart_stub, which does some low-level 164 // setup and then calls mstart. 165 var oset sigset 166 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 167 err = pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp)) 168 sigprocmask(_SIG_SETMASK, &oset, nil) 169 if err != 0 { 170 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 171 exit(1) 172 } 173 } 174 175 // glue code to call mstart from pthread_create. 176 func mstart_stub() 177 178 // newosproc0 is a version of newosproc that can be called before the runtime 179 // is initialized. 180 // 181 // This function is not safe to use after initialization as it does not pass an M as fnarg. 182 // 183 //go:nosplit 184 func newosproc0(stacksize uintptr, fn uintptr) { 185 // Initialize an attribute object. 186 var attr pthreadattr 187 var err int32 188 err = pthread_attr_init(&attr) 189 if err != 0 { 190 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 191 exit(1) 192 } 193 194 // Set the stack we want to use. 195 if pthread_attr_setstacksize(&attr, stacksize) != 0 { 196 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 197 exit(1) 198 } 199 mSysStatInc(&memstats.stacks_sys, stacksize) 200 201 // Tell the pthread library we won't join with this thread. 202 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 203 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 204 exit(1) 205 } 206 207 // Finally, create the thread. It starts at mstart_stub, which does some low-level 208 // setup and then calls mstart. 209 var oset sigset 210 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 211 err = pthread_create(&attr, fn, nil) 212 sigprocmask(_SIG_SETMASK, &oset, nil) 213 if err != 0 { 214 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 215 exit(1) 216 } 217 } 218 219 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n") 220 var failthreadcreate = []byte("runtime: failed to create new OS thread\n") 221 222 // Called to do synchronous initialization of Go code built with 223 // -buildmode=c-archive or -buildmode=c-shared. 224 // None of the Go runtime is initialized. 225 //go:nosplit 226 //go:nowritebarrierrec 227 func libpreinit() { 228 initsig(true) 229 } 230 231 // Called to initialize a new m (including the bootstrap m). 232 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 233 func mpreinit(mp *m) { 234 mp.gsignal = malg(32 * 1024) // OS X wants >= 8K 235 mp.gsignal.m = mp 236 } 237 238 // Called to initialize a new m (including the bootstrap m). 239 // Called on the new thread, cannot allocate memory. 240 func minit() { 241 // The alternate signal stack is buggy on arm and arm64. 242 // The signal handler handles it directly. 243 if GOARCH != "arm" && GOARCH != "arm64" { 244 minitSignalStack() 245 } 246 minitSignalMask() 247 } 248 249 // Called from dropm to undo the effect of an minit. 250 //go:nosplit 251 func unminit() { 252 // The alternate signal stack is buggy on arm and arm64. 253 // See minit. 254 if GOARCH != "arm" && GOARCH != "arm64" { 255 unminitSignals() 256 } 257 } 258 259 //go:nosplit 260 func osyield() { 261 usleep(1) 262 } 263 264 const ( 265 _NSIG = 32 266 _SI_USER = 0 /* empirically true, but not what headers say */ 267 _SIG_BLOCK = 1 268 _SIG_UNBLOCK = 2 269 _SIG_SETMASK = 3 270 _SS_DISABLE = 4 271 ) 272 273 //extern SigTabTT runtimeĀ·sigtab[]; 274 275 type sigset uint32 276 277 var sigset_all = ^sigset(0) 278 279 //go:nosplit 280 //go:nowritebarrierrec 281 func setsig(i uint32, fn uintptr) { 282 var sa usigactiont 283 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 284 sa.sa_mask = ^uint32(0) 285 if fn == funcPC(sighandler) { 286 if iscgo { 287 fn = funcPC(cgoSigtramp) 288 } else { 289 fn = funcPC(sigtramp) 290 } 291 } 292 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn 293 sigaction(i, &sa, nil) 294 } 295 296 // sigtramp is the callback from libc when a signal is received. 297 // It is called with the C calling convention. 298 func sigtramp() 299 func cgoSigtramp() 300 301 //go:nosplit 302 //go:nowritebarrierrec 303 func setsigstack(i uint32) { 304 var osa usigactiont 305 sigaction(i, nil, &osa) 306 handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u)) 307 if osa.sa_flags&_SA_ONSTACK != 0 { 308 return 309 } 310 var sa usigactiont 311 *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler 312 sa.sa_mask = osa.sa_mask 313 sa.sa_flags = osa.sa_flags | _SA_ONSTACK 314 sigaction(i, &sa, nil) 315 } 316 317 //go:nosplit 318 //go:nowritebarrierrec 319 func getsig(i uint32) uintptr { 320 var sa usigactiont 321 sigaction(i, nil, &sa) 322 return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) 323 } 324 325 // setSignaltstackSP sets the ss_sp field of a stackt. 326 //go:nosplit 327 func setSignalstackSP(s *stackt, sp uintptr) { 328 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp 329 } 330 331 //go:nosplit 332 //go:nowritebarrierrec 333 func sigaddset(mask *sigset, i int) { 334 *mask |= 1 << (uint32(i) - 1) 335 } 336 337 func sigdelset(mask *sigset, i int) { 338 *mask &^= 1 << (uint32(i) - 1) 339 } 340 341 //go:linkname executablePath os.executablePath 342 var executablePath string 343 344 func sysargs(argc int32, argv **byte) { 345 // skip over argv, envv and the first string will be the path 346 n := argc + 1 347 for argv_index(argv, n) != nil { 348 n++ 349 } 350 executablePath = gostringnocopy(argv_index(argv, n+1)) 351 352 // strip "executable_path=" prefix if available, it's added after OS X 10.11. 353 const prefix = "executable_path=" 354 if len(executablePath) > len(prefix) && executablePath[:len(prefix)] == prefix { 355 executablePath = executablePath[len(prefix):] 356 } 357 }