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