// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "runtime.h" #include "stack.h" #include "arch_GOARCH.h" #include "../../cmd/ld/textflag.h" enum { maxround = sizeof(uintptr), }; // Keep a cached value to make gotraceback fast, // since we call it on every call to gentraceback. // The cached value is a uint32 in which the low bit // is the "crash" setting and the top 31 bits are the // gotraceback value. static uint32 traceback_cache = ~(uint32)0; // The GOTRACEBACK environment variable controls the // behavior of a Go program that is crashing and exiting. // GOTRACEBACK=0 suppress all tracebacks // GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames // GOTRACEBACK=2 show tracebacks including runtime frames // GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc) int32 runtime·gotraceback(bool *crash) { byte *p; uint32 x; if(crash != nil) *crash = false; if(m->traceback != 0) return m->traceback; x = runtime·atomicload(&traceback_cache); if(x == ~(uint32)0) { p = runtime·getenv("GOTRACEBACK"); if(p == nil) p = (byte*)""; if(p[0] == '\0') x = 1<<1; else if(runtime·strcmp(p, (byte*)"crash") == 0) x = (2<<1) | 1; else x = runtime·atoi(p)<<1; runtime·atomicstore(&traceback_cache, x); } if(crash != nil) *crash = x&1; return x>>1; } int32 runtime·mcmp(byte *s1, byte *s2, uintptr n) { uintptr i; byte c1, c2; for(i=0; i c2) return +1; } return 0; } byte* runtime·mchr(byte *p, byte c, byte *ep) { for(; p < ep; p++) if(*p == c) return p; return nil; } static int32 argc; static uint8** argv; Slice os·Args; Slice syscall·envs; void (*runtime·sysargs)(int32, uint8**); void runtime·args(int32 c, uint8 **v) { argc = c; argv = v; if(runtime·sysargs != nil) runtime·sysargs(c, v); } int32 runtime·isplan9; int32 runtime·issolaris; int32 runtime·iswindows; // Information about what cpu features are available. // Set on startup in asm_{x86/amd64}.s. uint32 runtime·cpuid_ecx; uint32 runtime·cpuid_edx; void runtime·goargs(void) { String *s; int32 i; // for windows implementation see "os" package if(Windows) return; s = runtime·malloc(argc*sizeof s[0]); for(i=0; ifastrand; x += x; if(x & 0x80000000L) x ^= 0x88888eefUL; m->fastrand = x; return x; } static Lock ticksLock; static int64 ticks; int64 runtime·tickspersecond(void) { int64 res, t0, t1, c0, c1; res = (int64)runtime·atomicload64((uint64*)&ticks); if(res != 0) return ticks; runtime·lock(&ticksLock); res = ticks; if(res == 0) { t0 = runtime·nanotime(); c0 = runtime·cputicks(); runtime·usleep(100*1000); t1 = runtime·nanotime(); c1 = runtime·cputicks(); if(t1 == t0) t1++; res = (c1-c0)*1000*1000*1000/(t1-t0); if(res == 0) res++; runtime·atomicstore64((uint64*)&ticks, res); } runtime·unlock(&ticksLock); return res; } DebugVars runtime·debug; static struct { int8* name; int32* value; } dbgvar[] = { {"allocfreetrace", &runtime·debug.allocfreetrace}, {"efence", &runtime·debug.efence}, {"gctrace", &runtime·debug.gctrace}, {"gcdead", &runtime·debug.gcdead}, {"scheddetail", &runtime·debug.scheddetail}, {"schedtrace", &runtime·debug.schedtrace}, }; void runtime·parsedebugvars(void) { byte *p; intgo i, n; p = runtime·getenv("GODEBUG"); if(p == nil) return; for(;;) { for(i=0; i