github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/runtime.c (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 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "../../cmd/ld/textflag.h" 8 9 enum { 10 maxround = sizeof(uintptr), 11 }; 12 13 /* 14 * We assume that all architectures turn faults and the like 15 * into apparent calls to runtime.sigpanic. If we see a "call" 16 * to runtime.sigpanic, we do not back up the PC to find the 17 * line number of the CALL instruction, because there is no CALL. 18 */ 19 void runtime·sigpanic(void); 20 21 // The GOTRACEBACK environment variable controls the 22 // behavior of a Go program that is crashing and exiting. 23 // GOTRACEBACK=0 suppress all tracebacks 24 // GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames 25 // GOTRACEBACK=2 show tracebacks including runtime frames 26 // GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc) 27 int32 28 runtime·gotraceback(bool *crash) 29 { 30 byte *p; 31 32 if(crash != nil) 33 *crash = false; 34 p = runtime·getenv("GOTRACEBACK"); 35 if(p == nil || p[0] == '\0') 36 return 1; // default is on 37 if(runtime·strcmp(p, (byte*)"crash") == 0) { 38 if(crash != nil) 39 *crash = true; 40 return 2; // extra information 41 } 42 return runtime·atoi(p); 43 } 44 45 int32 46 runtime·mcmp(byte *s1, byte *s2, uintptr n) 47 { 48 uintptr i; 49 byte c1, c2; 50 51 for(i=0; i<n; i++) { 52 c1 = s1[i]; 53 c2 = s2[i]; 54 if(c1 < c2) 55 return -1; 56 if(c1 > c2) 57 return +1; 58 } 59 return 0; 60 } 61 62 63 byte* 64 runtime·mchr(byte *p, byte c, byte *ep) 65 { 66 for(; p < ep; p++) 67 if(*p == c) 68 return p; 69 return nil; 70 } 71 72 static int32 argc; 73 static uint8** argv; 74 75 Slice os·Args; 76 Slice syscall·envs; 77 78 void (*runtime·sysargs)(int32, uint8**); 79 80 void 81 runtime·args(int32 c, uint8 **v) 82 { 83 argc = c; 84 argv = v; 85 if(runtime·sysargs != nil) 86 runtime·sysargs(c, v); 87 } 88 89 int32 runtime·isplan9; 90 int32 runtime·iswindows; 91 92 // Information about what cpu features are available. 93 // Set on startup in asm_{x86/amd64}.s. 94 uint32 runtime·cpuid_ecx; 95 uint32 runtime·cpuid_edx; 96 97 void 98 runtime·goargs(void) 99 { 100 String *s; 101 int32 i; 102 103 // for windows implementation see "os" package 104 if(Windows) 105 return; 106 107 s = runtime·malloc(argc*sizeof s[0]); 108 for(i=0; i<argc; i++) 109 s[i] = runtime·gostringnocopy(argv[i]); 110 os·Args.array = (byte*)s; 111 os·Args.len = argc; 112 os·Args.cap = argc; 113 } 114 115 void 116 runtime·goenvs_unix(void) 117 { 118 String *s; 119 int32 i, n; 120 121 for(n=0; argv[argc+1+n] != 0; n++) 122 ; 123 124 s = runtime·malloc(n*sizeof s[0]); 125 for(i=0; i<n; i++) 126 s[i] = runtime·gostringnocopy(argv[argc+1+i]); 127 syscall·envs.array = (byte*)s; 128 syscall·envs.len = n; 129 syscall·envs.cap = n; 130 } 131 132 void 133 runtime·getgoroot(String out) 134 { 135 byte *p; 136 137 p = runtime·getenv("GOROOT"); 138 out = runtime·gostringnocopy(p); 139 FLUSH(&out); 140 } 141 142 int32 143 runtime·atoi(byte *p) 144 { 145 int32 n; 146 147 n = 0; 148 while('0' <= *p && *p <= '9') 149 n = n*10 + *p++ - '0'; 150 return n; 151 } 152 153 static void 154 TestAtomic64(void) 155 { 156 uint64 z64, x64; 157 158 z64 = 42; 159 x64 = 0; 160 PREFETCH(&z64); 161 if(runtime·cas64(&z64, x64, 1)) 162 runtime·throw("cas64 failed"); 163 if(x64 != 0) 164 runtime·throw("cas64 failed"); 165 x64 = 42; 166 if(!runtime·cas64(&z64, x64, 1)) 167 runtime·throw("cas64 failed"); 168 if(x64 != 42 || z64 != 1) 169 runtime·throw("cas64 failed"); 170 if(runtime·atomicload64(&z64) != 1) 171 runtime·throw("load64 failed"); 172 runtime·atomicstore64(&z64, (1ull<<40)+1); 173 if(runtime·atomicload64(&z64) != (1ull<<40)+1) 174 runtime·throw("store64 failed"); 175 if(runtime·xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2) 176 runtime·throw("xadd64 failed"); 177 if(runtime·atomicload64(&z64) != (2ull<<40)+2) 178 runtime·throw("xadd64 failed"); 179 if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2) 180 runtime·throw("xchg64 failed"); 181 if(runtime·atomicload64(&z64) != (3ull<<40)+3) 182 runtime·throw("xchg64 failed"); 183 } 184 185 void 186 runtime·check(void) 187 { 188 int8 a; 189 uint8 b; 190 int16 c; 191 uint16 d; 192 int32 e; 193 uint32 f; 194 int64 g; 195 uint64 h; 196 float32 i, i1; 197 float64 j, j1; 198 byte *k, *k1; 199 uint16* l; 200 struct x1 { 201 byte x; 202 }; 203 struct y1 { 204 struct x1 x1; 205 byte y; 206 }; 207 208 if(sizeof(a) != 1) runtime·throw("bad a"); 209 if(sizeof(b) != 1) runtime·throw("bad b"); 210 if(sizeof(c) != 2) runtime·throw("bad c"); 211 if(sizeof(d) != 2) runtime·throw("bad d"); 212 if(sizeof(e) != 4) runtime·throw("bad e"); 213 if(sizeof(f) != 4) runtime·throw("bad f"); 214 if(sizeof(g) != 8) runtime·throw("bad g"); 215 if(sizeof(h) != 8) runtime·throw("bad h"); 216 if(sizeof(i) != 4) runtime·throw("bad i"); 217 if(sizeof(j) != 8) runtime·throw("bad j"); 218 if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k"); 219 if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l"); 220 if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1"); 221 if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y"); 222 if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1"); 223 224 if(runtime·timediv(12345LL*1000000000+54321, 1000000000, &e) != 12345 || e != 54321) 225 runtime·throw("bad timediv"); 226 227 uint32 z; 228 z = 1; 229 if(!runtime·cas(&z, 1, 2)) 230 runtime·throw("cas1"); 231 if(z != 2) 232 runtime·throw("cas2"); 233 234 z = 4; 235 if(runtime·cas(&z, 5, 6)) 236 runtime·throw("cas3"); 237 if(z != 4) 238 runtime·throw("cas4"); 239 240 k = (byte*)0xfedcb123; 241 if(sizeof(void*) == 8) 242 k = (byte*)((uintptr)k<<10); 243 if(runtime·casp((void**)&k, nil, nil)) 244 runtime·throw("casp1"); 245 k1 = k+1; 246 if(!runtime·casp((void**)&k, k, k1)) 247 runtime·throw("casp2"); 248 if(k != k1) 249 runtime·throw("casp3"); 250 251 *(uint64*)&j = ~0ULL; 252 if(j == j) 253 runtime·throw("float64nan"); 254 if(!(j != j)) 255 runtime·throw("float64nan1"); 256 257 *(uint64*)&j1 = ~1ULL; 258 if(j == j1) 259 runtime·throw("float64nan2"); 260 if(!(j != j1)) 261 runtime·throw("float64nan3"); 262 263 *(uint32*)&i = ~0UL; 264 if(i == i) 265 runtime·throw("float32nan"); 266 if(!(i != i)) 267 runtime·throw("float32nan1"); 268 269 *(uint32*)&i1 = ~1UL; 270 if(i == i1) 271 runtime·throw("float32nan2"); 272 if(!(i != i1)) 273 runtime·throw("float32nan3"); 274 275 TestAtomic64(); 276 } 277 278 void 279 runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool retbool) 280 { 281 Func *f, *g; 282 uintptr pc; 283 uintptr rpc[2]; 284 285 /* 286 * Ask for two PCs: the one we were asked for 287 * and what it called, so that we can see if it 288 * "called" sigpanic. 289 */ 290 retpc = 0; 291 if(runtime·callers(1+skip-1, rpc, 2) < 2) { 292 retfile = runtime·emptystring; 293 retline = 0; 294 retbool = false; 295 } else if((f = runtime·findfunc(rpc[1])) == nil) { 296 retfile = runtime·emptystring; 297 retline = 0; 298 retbool = true; // have retpc at least 299 } else { 300 retpc = rpc[1]; 301 pc = retpc; 302 g = runtime·findfunc(rpc[0]); 303 if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic)) 304 pc--; 305 retline = runtime·funcline(f, pc, &retfile); 306 retbool = true; 307 } 308 FLUSH(&retpc); 309 FLUSH(&retfile); 310 FLUSH(&retline); 311 FLUSH(&retbool); 312 } 313 314 void 315 runtime·Callers(intgo skip, Slice pc, intgo retn) 316 { 317 // runtime.callers uses pc.array==nil as a signal 318 // to print a stack trace. Pick off 0-length pc here 319 // so that we don't let a nil pc slice get to it. 320 if(pc.len == 0) 321 retn = 0; 322 else 323 retn = runtime·callers(skip, (uintptr*)pc.array, pc.len); 324 FLUSH(&retn); 325 } 326 327 void 328 runtime·FuncForPC(uintptr pc, void *retf) 329 { 330 retf = runtime·findfunc(pc); 331 FLUSH(&retf); 332 } 333 334 uint32 335 runtime·fastrand1(void) 336 { 337 uint32 x; 338 339 x = m->fastrand; 340 x += x; 341 if(x & 0x80000000L) 342 x ^= 0x88888eefUL; 343 m->fastrand = x; 344 return x; 345 } 346 347 static Lock ticksLock; 348 static int64 ticks; 349 350 int64 351 runtime·tickspersecond(void) 352 { 353 int64 res, t0, t1, c0, c1; 354 355 res = (int64)runtime·atomicload64((uint64*)&ticks); 356 if(res != 0) 357 return ticks; 358 runtime·lock(&ticksLock); 359 res = ticks; 360 if(res == 0) { 361 t0 = runtime·nanotime(); 362 c0 = runtime·cputicks(); 363 runtime·usleep(100*1000); 364 t1 = runtime·nanotime(); 365 c1 = runtime·cputicks(); 366 if(t1 == t0) 367 t1++; 368 res = (c1-c0)*1000*1000*1000/(t1-t0); 369 if(res == 0) 370 res++; 371 runtime·atomicstore64((uint64*)&ticks, res); 372 } 373 runtime·unlock(&ticksLock); 374 return res; 375 } 376 377 void 378 runtime∕pprof·runtime_cyclesPerSecond(int64 res) 379 { 380 res = runtime·tickspersecond(); 381 FLUSH(&res); 382 } 383 384 DebugVars runtime·debug; 385 386 static struct { 387 int8* name; 388 int32* value; 389 } dbgvar[] = { 390 {"gctrace", &runtime·debug.gctrace}, 391 {"schedtrace", &runtime·debug.schedtrace}, 392 {"scheddetail", &runtime·debug.scheddetail}, 393 }; 394 395 void 396 runtime·parsedebugvars(void) 397 { 398 byte *p; 399 intgo i, n; 400 401 p = runtime·getenv("GODEBUG"); 402 if(p == nil) 403 return; 404 for(;;) { 405 for(i=0; i<nelem(dbgvar); i++) { 406 n = runtime·findnull((byte*)dbgvar[i].name); 407 if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=') 408 *dbgvar[i].value = runtime·atoi(p+n+1); 409 } 410 p = runtime·strstr(p, (byte*)","); 411 if(p == nil) 412 break; 413 p++; 414 } 415 } 416 417 // Poor mans 64-bit division. 418 // This is a very special function, do not use it if you are not sure what you are doing. 419 // int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions. 420 // Handles overflow in a time-specific manner. 421 #pragma textflag NOSPLIT 422 int32 423 runtime·timediv(int64 v, int32 div, int32 *rem) 424 { 425 int32 res, bit; 426 427 if(v >= (int64)div*0x7fffffffLL) { 428 if(rem != nil) 429 *rem = 0; 430 return 0x7fffffff; 431 } 432 res = 0; 433 for(bit = 30; bit >= 0; bit--) { 434 if(v >= ((int64)div<<bit)) { 435 v = v - ((int64)div<<bit); 436 res += 1<<bit; 437 } 438 } 439 if(rem != nil) 440 *rem = v; 441 return res; 442 }