// 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 "arch_GOARCH.h" #include "../../cmd/ld/textflag.h" enum { maxround = sizeof(uintptr), }; /* * We assume that all architectures turn faults and the like * into apparent calls to runtime.sigpanic. If we see a "call" * to runtime.sigpanic, we do not back up the PC to find the * line number of the CALL instruction, because there is no CALL. */ void runtime·sigpanic(void); // 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; if(crash != nil) *crash = false; p = runtime·getenv("GOTRACEBACK"); if(p == nil || p[0] == '\0') return 1; // default is on if(runtime·strcmp(p, (byte*)"crash") == 0) { if(crash != nil) *crash = true; return 2; // extra information } return runtime·atoi(p); } 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·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; i f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic)) pc--; retline = runtime·funcline(f, pc, &retfile); retbool = true; } FLUSH(&retpc); FLUSH(&retfile); FLUSH(&retline); FLUSH(&retbool); } void runtime·Callers(intgo skip, Slice pc, intgo retn) { // runtime.callers uses pc.array==nil as a signal // to print a stack trace. Pick off 0-length pc here // so that we don't let a nil pc slice get to it. if(pc.len == 0) retn = 0; else retn = runtime·callers(skip, (uintptr*)pc.array, pc.len); FLUSH(&retn); } void runtime·FuncForPC(uintptr pc, void *retf) { retf = runtime·findfunc(pc); FLUSH(&retf); } uint32 runtime·fastrand1(void) { uint32 x; x = m->fastrand; 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; } void runtime∕pprof·runtime_cyclesPerSecond(int64 res) { res = runtime·tickspersecond(); FLUSH(&res); } DebugVars runtime·debug; static struct { int8* name; int32* value; } dbgvar[] = { {"gctrace", &runtime·debug.gctrace}, }; void runtime·parsedebugvars(void) { byte *p; intgo i, n; p = runtime·getenv("GODEBUG"); if(p == nil) return; for(;;) { for(i=0; i