github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/os_dragonfly.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 extern SigTab runtime·sigtab[]; 13 extern int32 runtime·sys_umtx_sleep(uint32*, int32, int32); 14 extern int32 runtime·sys_umtx_wakeup(uint32*, int32); 15 16 // From DragonFly's <sys/sysctl.h> 17 #define CTL_HW 6 18 #define HW_NCPU 3 19 20 static Sigset sigset_none; 21 static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, }; 22 23 static int32 24 getncpu(void) 25 { 26 uint32 mib[2]; 27 uint32 out; 28 int32 ret; 29 uintptr nout; 30 31 // Fetch hw.ncpu via sysctl. 32 mib[0] = CTL_HW; 33 mib[1] = HW_NCPU; 34 nout = sizeof out; 35 out = 0; 36 ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0); 37 if(ret >= 0) 38 return out; 39 else 40 return 1; 41 } 42 43 #pragma textflag NOSPLIT 44 void 45 runtime·futexsleep(uint32 *addr, uint32 val, int64 ns) 46 { 47 int32 timeout = 0; 48 int32 ret; 49 50 if(ns >= 0) { 51 // The timeout is specified in microseconds - ensure that we 52 // do not end up dividing to zero, which would put us to sleep 53 // indefinitely... 54 timeout = runtime·timediv(ns, 1000, nil); 55 if(timeout == 0) 56 timeout = 1; 57 } 58 59 // sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout 60 // expires or EBUSY if the mutex value does not match. 61 ret = runtime·sys_umtx_sleep(addr, val, timeout); 62 if(ret >= 0 || ret == -EINTR || ret == -EAGAIN || ret == -EBUSY) 63 return; 64 65 runtime·prints("umtx_wait addr="); 66 runtime·printpointer(addr); 67 runtime·prints(" val="); 68 runtime·printint(val); 69 runtime·prints(" ret="); 70 runtime·printint(ret); 71 runtime·prints("\n"); 72 *(int32*)0x1005 = 0x1005; 73 } 74 75 void 76 runtime·futexwakeup(uint32 *addr, uint32 cnt) 77 { 78 int32 ret; 79 80 ret = runtime·sys_umtx_wakeup(addr, cnt); 81 if(ret >= 0) 82 return; 83 84 runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret); 85 *(int32*)0x1006 = 0x1006; 86 } 87 88 void runtime·lwp_start(void*); 89 90 void 91 runtime·newosproc(M *mp, void *stk) 92 { 93 Lwpparams params; 94 Sigset oset; 95 96 if(0){ 97 runtime·printf("newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n", 98 stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp); 99 } 100 101 runtime·sigprocmask(&sigset_all, &oset); 102 runtime·memclr((byte*)¶ms, sizeof params); 103 104 params.func = runtime·lwp_start; 105 params.arg = (byte*)mp; 106 params.stack = (byte*)stk; 107 params.tid1 = (int32*)&mp->procid; 108 params.tid2 = nil; 109 110 mp->tls[0] = mp->id; // so 386 asm can find it 111 112 runtime·lwp_create(¶ms); 113 runtime·sigprocmask(&oset, nil); 114 } 115 116 void 117 runtime·osinit(void) 118 { 119 runtime·ncpu = getncpu(); 120 } 121 122 void 123 runtime·get_random_data(byte **rnd, int32 *rnd_len) 124 { 125 static byte urandom_data[HashRandomBytes]; 126 int32 fd; 127 fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0); 128 if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) { 129 *rnd = urandom_data; 130 *rnd_len = HashRandomBytes; 131 } else { 132 *rnd = nil; 133 *rnd_len = 0; 134 } 135 runtime·close(fd); 136 } 137 138 void 139 runtime·goenvs(void) 140 { 141 runtime·goenvs_unix(); 142 } 143 144 // Called to initialize a new m (including the bootstrap m). 145 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 146 void 147 runtime·mpreinit(M *mp) 148 { 149 mp->gsignal = runtime·malg(32*1024); 150 } 151 152 // Called to initialize a new m (including the bootstrap m). 153 // Called on the new thread, can not allocate memory. 154 void 155 runtime·minit(void) 156 { 157 // Initialize signal handling 158 runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024); 159 runtime·sigprocmask(&sigset_none, nil); 160 } 161 162 // Called from dropm to undo the effect of an minit. 163 void 164 runtime·unminit(void) 165 { 166 runtime·signalstack(nil, 0); 167 } 168 169 void 170 runtime·sigpanic(void) 171 { 172 switch(g->sig) { 173 case SIGBUS: 174 if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) { 175 if(g->sigpc == 0) 176 runtime·panicstring("call of nil func value"); 177 runtime·panicstring("invalid memory address or nil pointer dereference"); 178 } 179 runtime·printf("unexpected fault address %p\n", g->sigcode1); 180 runtime·throw("fault"); 181 case SIGSEGV: 182 if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) { 183 if(g->sigpc == 0) 184 runtime·panicstring("call of nil func value"); 185 runtime·panicstring("invalid memory address or nil pointer dereference"); 186 } 187 runtime·printf("unexpected fault address %p\n", g->sigcode1); 188 runtime·throw("fault"); 189 case SIGFPE: 190 switch(g->sigcode0) { 191 case FPE_INTDIV: 192 runtime·panicstring("integer divide by zero"); 193 case FPE_INTOVF: 194 runtime·panicstring("integer overflow"); 195 } 196 runtime·panicstring("floating point error"); 197 } 198 runtime·panicstring(runtime·sigtab[g->sig].name); 199 } 200 201 uintptr 202 runtime·memlimit(void) 203 { 204 Rlimit rl; 205 extern byte text[], end[]; 206 uintptr used; 207 208 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 209 return 0; 210 if(rl.rlim_cur >= 0x7fffffff) 211 return 0; 212 213 // Estimate our VM footprint excluding the heap. 214 // Not an exact science: use size of binary plus 215 // some room for thread stacks. 216 used = end - text + (64<<20); 217 if(used >= rl.rlim_cur) 218 return 0; 219 220 // If there's not at least 16 MB left, we're probably 221 // not going to be able to do much. Treat as no limit. 222 rl.rlim_cur -= used; 223 if(rl.rlim_cur < (16<<20)) 224 return 0; 225 226 return rl.rlim_cur - used; 227 } 228 229 extern void runtime·sigtramp(void); 230 231 typedef struct sigaction { 232 union { 233 void (*__sa_handler)(int32); 234 void (*__sa_sigaction)(int32, Siginfo*, void *); 235 } __sigaction_u; /* signal handler */ 236 int32 sa_flags; /* see signal options below */ 237 Sigset sa_mask; /* signal mask to apply */ 238 } Sigaction; 239 240 void 241 runtime·setsig(int32 i, GoSighandler *fn, bool restart) 242 { 243 Sigaction sa; 244 245 runtime·memclr((byte*)&sa, sizeof sa); 246 sa.sa_flags = SA_SIGINFO|SA_ONSTACK; 247 if(restart) 248 sa.sa_flags |= SA_RESTART; 249 sa.sa_mask.__bits[0] = ~(uint32)0; 250 sa.sa_mask.__bits[1] = ~(uint32)0; 251 sa.sa_mask.__bits[2] = ~(uint32)0; 252 sa.sa_mask.__bits[3] = ~(uint32)0; 253 if(fn == runtime·sighandler) 254 fn = (void*)runtime·sigtramp; 255 sa.__sigaction_u.__sa_sigaction = (void*)fn; 256 runtime·sigaction(i, &sa, nil); 257 } 258 259 GoSighandler* 260 runtime·getsig(int32 i) 261 { 262 Sigaction sa; 263 264 runtime·memclr((byte*)&sa, sizeof sa); 265 runtime·sigaction(i, nil, &sa); 266 if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp) 267 return runtime·sighandler; 268 return (void*)sa.__sigaction_u.__sa_sigaction; 269 } 270 271 void 272 runtime·signalstack(byte *p, int32 n) 273 { 274 StackT st; 275 276 st.ss_sp = (void*)p; 277 st.ss_size = n; 278 st.ss_flags = 0; 279 if(p == nil) 280 st.ss_flags = SS_DISABLE; 281 runtime·sigaltstack(&st, nil); 282 }