github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/os_openbsd.c (about) 1 // Copyright 2011 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 #include "runtime.h" 6 #include "defs_GOOS_GOARCH.h" 7 #include "os_GOOS.h" 8 #include "signal_unix.h" 9 #include "stack.h" 10 11 enum 12 { 13 ESRCH = 3, 14 ENOTSUP = 91, 15 16 // From OpenBSD's sys/time.h 17 CLOCK_REALTIME = 0, 18 CLOCK_VIRTUAL = 1, 19 CLOCK_PROF = 2, 20 CLOCK_MONOTONIC = 3 21 }; 22 23 extern SigTab runtime·sigtab[]; 24 25 static Sigset sigset_none; 26 static Sigset sigset_all = ~(Sigset)0; 27 28 extern int64 runtime·tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void)); 29 extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock, const int32 *abort); 30 extern int32 runtime·thrwakeup(void *ident, int32 n); 31 32 // From OpenBSD's <sys/sysctl.h> 33 #define CTL_HW 6 34 #define HW_NCPU 3 35 36 static int32 37 getncpu(void) 38 { 39 uint32 mib[2]; 40 uint32 out; 41 int32 ret; 42 uintptr nout; 43 44 // Fetch hw.ncpu via sysctl. 45 mib[0] = CTL_HW; 46 mib[1] = HW_NCPU; 47 nout = sizeof out; 48 out = 0; 49 ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0); 50 if(ret >= 0) 51 return out; 52 else 53 return 1; 54 } 55 56 uintptr 57 runtime·semacreate(void) 58 { 59 return 1; 60 } 61 62 int32 63 runtime·semasleep(int64 ns) 64 { 65 Timespec ts; 66 int64 secs; 67 68 // spin-mutex lock 69 while(runtime·xchg(&m->waitsemalock, 1)) 70 runtime·osyield(); 71 72 for(;;) { 73 // lock held 74 if(m->waitsemacount == 0) { 75 // sleep until semaphore != 0 or timeout. 76 // thrsleep unlocks m->waitsemalock. 77 if(ns < 0) 78 runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil); 79 else { 80 ns += runtime·nanotime(); 81 secs = ns/1000000000LL; 82 // Avoid overflow 83 if(secs >= 1LL<<31) 84 secs = (1LL<<31) - 1; 85 ts.tv_sec = secs; 86 ts.tv_nsec = ns%1000000000LL; 87 runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock, nil); 88 } 89 // reacquire lock 90 while(runtime·xchg(&m->waitsemalock, 1)) 91 runtime·osyield(); 92 } 93 94 // lock held (again) 95 if(m->waitsemacount != 0) { 96 // semaphore is available. 97 m->waitsemacount--; 98 // spin-mutex unlock 99 runtime·atomicstore(&m->waitsemalock, 0); 100 return 0; // semaphore acquired 101 } 102 103 // semaphore not available. 104 // if there is a timeout, stop now. 105 // otherwise keep trying. 106 if(ns >= 0) 107 break; 108 } 109 110 // lock held but giving up 111 // spin-mutex unlock 112 runtime·atomicstore(&m->waitsemalock, 0); 113 return -1; 114 } 115 116 void 117 runtime·semawakeup(M *mp) 118 { 119 uint32 ret; 120 121 // spin-mutex lock 122 while(runtime·xchg(&mp->waitsemalock, 1)) 123 runtime·osyield(); 124 mp->waitsemacount++; 125 ret = runtime·thrwakeup(&mp->waitsemacount, 1); 126 if(ret != 0 && ret != ESRCH) 127 runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret); 128 // spin-mutex unlock 129 runtime·atomicstore(&mp->waitsemalock, 0); 130 } 131 132 void 133 runtime·newosproc(M *mp, void *stk) 134 { 135 Tfork param; 136 Sigset oset; 137 int32 ret; 138 139 if(0) { 140 runtime·printf( 141 "newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n", 142 stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp); 143 } 144 145 mp->tls[0] = mp->id; // so 386 asm can find it 146 147 param.tf_tcb = (byte*)&mp->tls[0]; 148 param.tf_tid = (int32*)&mp->procid; 149 param.tf_stack = stk; 150 151 oset = runtime·sigprocmask(SIG_SETMASK, sigset_all); 152 ret = runtime·tfork((byte*)¶m, sizeof(param), mp, mp->g0, runtime·mstart); 153 runtime·sigprocmask(SIG_SETMASK, oset); 154 155 if(ret < 0) { 156 runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret); 157 if (ret == -ENOTSUP) 158 runtime·printf("runtime: is kern.rthreads disabled?\n"); 159 runtime·throw("runtime.newosproc"); 160 } 161 } 162 163 void 164 runtime·osinit(void) 165 { 166 runtime·ncpu = getncpu(); 167 } 168 169 void 170 runtime·get_random_data(byte **rnd, int32 *rnd_len) 171 { 172 static byte urandom_data[HashRandomBytes]; 173 int32 fd; 174 fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0); 175 if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) { 176 *rnd = urandom_data; 177 *rnd_len = HashRandomBytes; 178 } else { 179 *rnd = nil; 180 *rnd_len = 0; 181 } 182 runtime·close(fd); 183 } 184 185 void 186 runtime·goenvs(void) 187 { 188 runtime·goenvs_unix(); 189 } 190 191 // Called to initialize a new m (including the bootstrap m). 192 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 193 void 194 runtime·mpreinit(M *mp) 195 { 196 mp->gsignal = runtime·malg(32*1024); 197 } 198 199 // Called to initialize a new m (including the bootstrap m). 200 // Called on the new thread, can not allocate memory. 201 void 202 runtime·minit(void) 203 { 204 // Initialize signal handling 205 runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024); 206 runtime·sigprocmask(SIG_SETMASK, sigset_none); 207 } 208 209 // Called from dropm to undo the effect of an minit. 210 void 211 runtime·unminit(void) 212 { 213 runtime·signalstack(nil, 0); 214 } 215 216 void 217 runtime·sigpanic(void) 218 { 219 switch(g->sig) { 220 case SIGBUS: 221 if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) { 222 if(g->sigpc == 0) 223 runtime·panicstring("call of nil func value"); 224 runtime·panicstring("invalid memory address or nil pointer dereference"); 225 } 226 runtime·printf("unexpected fault address %p\n", g->sigcode1); 227 runtime·throw("fault"); 228 case SIGSEGV: 229 if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) { 230 if(g->sigpc == 0) 231 runtime·panicstring("call of nil func value"); 232 runtime·panicstring("invalid memory address or nil pointer dereference"); 233 } 234 runtime·printf("unexpected fault address %p\n", g->sigcode1); 235 runtime·throw("fault"); 236 case SIGFPE: 237 switch(g->sigcode0) { 238 case FPE_INTDIV: 239 runtime·panicstring("integer divide by zero"); 240 case FPE_INTOVF: 241 runtime·panicstring("integer overflow"); 242 } 243 runtime·panicstring("floating point error"); 244 } 245 runtime·panicstring(runtime·sigtab[g->sig].name); 246 } 247 248 uintptr 249 runtime·memlimit(void) 250 { 251 return 0; 252 } 253 254 void 255 runtime·setprof(bool on) 256 { 257 USED(on); 258 } 259 260 static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n"; 261 262 // This runs on a foreign stack, without an m or a g. No stack split. 263 #pragma textflag 7 264 void 265 runtime·badcallback(void) 266 { 267 runtime·write(2, badcallback, sizeof badcallback - 1); 268 } 269 270 static int8 badsignal[] = "runtime: signal received on thread not created by Go: "; 271 272 // This runs on a foreign stack, without an m or a g. No stack split. 273 #pragma textflag 7 274 void 275 runtime·badsignal(int32 sig) 276 { 277 int32 len; 278 279 if (sig == SIGPROF) { 280 return; // Ignore SIGPROFs intended for a non-Go thread. 281 } 282 runtime·write(2, badsignal, sizeof badsignal - 1); 283 if (0 <= sig && sig < NSIG) { 284 // Can't call findnull() because it will split stack. 285 for(len = 0; runtime·sigtab[sig].name[len]; len++) 286 ; 287 runtime·write(2, runtime·sigtab[sig].name, len); 288 } 289 runtime·write(2, "\n", 1); 290 runtime·exit(1); 291 } 292 293 extern void runtime·sigtramp(void); 294 295 typedef struct sigaction { 296 union { 297 void (*__sa_handler)(int32); 298 void (*__sa_sigaction)(int32, Siginfo*, void *); 299 } __sigaction_u; /* signal handler */ 300 uint32 sa_mask; /* signal mask to apply */ 301 int32 sa_flags; /* see signal options below */ 302 } Sigaction; 303 304 void 305 runtime·setsig(int32 i, GoSighandler *fn, bool restart) 306 { 307 Sigaction sa; 308 309 runtime·memclr((byte*)&sa, sizeof sa); 310 sa.sa_flags = SA_SIGINFO|SA_ONSTACK; 311 if(restart) 312 sa.sa_flags |= SA_RESTART; 313 sa.sa_mask = ~0U; 314 if(fn == runtime·sighandler) 315 fn = (void*)runtime·sigtramp; 316 sa.__sigaction_u.__sa_sigaction = (void*)fn; 317 runtime·sigaction(i, &sa, nil); 318 } 319 320 GoSighandler* 321 runtime·getsig(int32 i) 322 { 323 Sigaction sa; 324 325 runtime·memclr((byte*)&sa, sizeof sa); 326 runtime·sigaction(i, nil, &sa); 327 if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp) 328 return runtime·sighandler; 329 return (void*)sa.__sigaction_u.__sa_sigaction; 330 } 331 332 void 333 runtime·signalstack(byte *p, int32 n) 334 { 335 StackT st; 336 337 st.ss_sp = (void*)p; 338 st.ss_size = n; 339 st.ss_flags = 0; 340 if(p == nil) 341 st.ss_flags = SS_DISABLE; 342 runtime·sigaltstack(&st, nil); 343 }