// 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" enum { maxround = sizeof(uintptr), }; uint32 runtime·panicking; void (*runtime·destroylock)(Lock*); /* * 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); int32 runtime·gotraceback(void) { byte *p; p = runtime·getenv("GOTRACEBACK"); if(p == nil || p[0] == '\0') return 1; // default is on return runtime·atoi(p); } static Lock paniclk; void runtime·startpanic(void) { if(m->dying) { runtime·printf("panic during panic\n"); runtime·exit(3); } m->dying = 1; runtime·xadd(&runtime·panicking, 1); runtime·lock(&paniclk); } void runtime·dopanic(int32 unused) { static bool didothers; if(g->sig != 0) runtime·printf("\n[signal %x code=%p addr=%p pc=%p]\n", g->sig, g->sigcode0, g->sigcode1, g->sigpc); runtime·printf("\n"); if(runtime·gotraceback()){ runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g); if(!didothers) { didothers = true; runtime·tracebackothers(g); } } runtime·unlock(&paniclk); if(runtime·xadd(&runtime·panicking, -1) != 0) { // Some other m is panicking too. // Let it print what it needs to print. // Wait forever without chewing up cpu. // It will exit when it's done. static Lock deadlock; runtime·lock(&deadlock); runtime·lock(&deadlock); } runtime·exit(2); } void runtime·panicindex(void) { runtime·panicstring("index out of range"); } void runtime·panicslice(void) { runtime·panicstring("slice bounds out of range"); } void runtime·throwreturn(void) { // can only happen if compiler is broken runtime·throw("no return at end of a typed function - compiler is broken"); } void runtime·throwinit(void) { // can only happen with linker skew runtime·throw("recursive call during initialization - linker skew"); } void runtime·throw(int8 *s) { runtime·startpanic(); runtime·printf("throw: %s\n", s); runtime·dopanic(0); *(int32*)0 = 0; // not reached runtime·exit(1); // even more not reached } void runtime·panicstring(int8 *s) { Eface err; if(m->gcing) { runtime·printf("panic: %s\n", s); runtime·throw("panic during gc"); } runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err); runtime·panic(err); } int32 runtime·mcmp(byte *s1, byte *s2, uint32 n) { uint32 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; } uint32 runtime·rnd(uint32 n, uint32 m) { uint32 r; if(m > maxround) m = maxround; r = n % m; if(r) n += m-r; return n; } static int32 argc; static uint8** argv; Slice os·Args; Slice os·Envs; void runtime·args(int32 c, uint8 **v) { argc = c; argv = v; } int32 runtime·isplan9; int32 runtime·iswindows; 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 0) { if(sizeof(hash) == 4) hash = (hash ^ *b) * 3267000013UL; else hash = (hash ^ *b) * 23344194077549503ULL; b++; s--; } return hash; } static uint32 memequal(uint32 s, void *a, void *b) { byte *ba, *bb, *aend; if(a == b) return 1; ba = a; bb = b; aend = ba+s; while(ba != aend) { if(*ba != *bb) return 0; ba++; bb++; } return 1; } static void memprint(uint32 s, void *a) { uint64 v; v = 0xbadb00b; switch(s) { case 1: v = *(uint8*)a; break; case 2: v = *(uint16*)a; break; case 4: v = *(uint32*)a; break; case 8: v = *(uint64*)a; break; } runtime·printint(v); } static void memcopy(uint32 s, void *a, void *b) { if(b == nil) { runtime·memclr(a,s); return; } runtime·memmove(a,b,s); } static uint32 memwordequal(uint32 s, void *a, void *b) { USED(s); return *(uintptr*)(a) == *(uintptr*)(b); } static void memwordcopy(uint32 s, void *a, void *b) { USED(s); if (b == nil) { *(uintptr*)(a) = 0; return; } *(uintptr*)(a) = *(uintptr*)(b); } static uintptr strhash(uint32 s, String *a) { USED(s); return memhash((*a).len, (*a).str); } static uint32 strequal(uint32 s, String *a, String *b) { int32 alen; USED(s); alen = a->len; if(alen != b->len) return false; return memequal(alen, a->str, b->str); } static void strprint(uint32 s, String *a) { USED(s); runtime·printstring(*a); } static uintptr interhash(uint32 s, Iface *a) { USED(s); return runtime·ifacehash(*a); } static void interprint(uint32 s, Iface *a) { USED(s); runtime·printiface(*a); } static uint32 interequal(uint32 s, Iface *a, Iface *b) { USED(s); return runtime·ifaceeq_c(*a, *b); } static uintptr nilinterhash(uint32 s, Eface *a) { USED(s); return runtime·efacehash(*a); } static void nilinterprint(uint32 s, Eface *a) { USED(s); runtime·printeface(*a); } static uint32 nilinterequal(uint32 s, Eface *a, Eface *b) { USED(s); return runtime·efaceeq_c(*a, *b); } uintptr runtime·nohash(uint32 s, void *a) { USED(s); USED(a); runtime·panicstring("hash of unhashable type"); return 0; } uint32 runtime·noequal(uint32 s, void *a, void *b) { USED(s); USED(a); USED(b); runtime·panicstring("comparing uncomparable types"); return 0; } Alg runtime·algarray[] = { [AMEM] { memhash, memequal, memprint, memcopy }, [ANOEQ] { runtime·nohash, runtime·noequal, memprint, memcopy }, [ASTRING] { strhash, strequal, strprint, memcopy }, [AINTER] { interhash, interequal, interprint, memcopy }, [ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy }, [AMEMWORD] { memhash, memwordequal, memprint, memwordcopy }, }; int64 runtime·nanotime(void) { int64 sec; int32 usec; sec = 0; usec = 0; runtime·gettime(&sec, &usec); return sec*1000000000 + (int64)usec*1000; } void runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool) { Func *f, *g; uintptr pc; uintptr rpc[2]; /* * Ask for two PCs: the one we were asked for * and what it called, so that we can see if it * "called" sigpanic. */ retpc = 0; if(runtime·callers(1+skip-1, rpc, 2) < 2) { retfile = runtime·emptystring; retline = 0; retbool = false; } else if((f = runtime·findfunc(rpc[1])) == nil) { retfile = runtime·emptystring; retline = 0; retbool = true; // have retpc at least } else { retpc = rpc[1]; retfile = f->src; pc = retpc; g = runtime·findfunc(rpc[0]); if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic)) pc--; retline = runtime·funcline(f, pc); retbool = true; } FLUSH(&retpc); FLUSH(&retfile); FLUSH(&retline); FLUSH(&retbool); } void runtime·Callers(int32 skip, Slice pc, int32 retn) { 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; }