From 5ff4c17907d5b19510a62e08fd8d3b11e62b431d Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 13 Sep 2011 13:13:40 +0200 Subject: Imported Upstream version 60 --- src/pkg/runtime/runtime.c | 728 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 728 insertions(+) create mode 100644 src/pkg/runtime/runtime.c (limited to 'src/pkg/runtime/runtime.c') diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c new file mode 100644 index 000000000..49aba7da0 --- /dev/null +++ b/src/pkg/runtime/runtime.c @@ -0,0 +1,728 @@ +// 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 +memequal8(uint32 s, uint8 *a, uint8 *b) +{ + USED(s); + return *a == *b; +} + +static void +memcopy8(uint32 s, uint8 *a, uint8 *b) +{ + USED(s); + if(b == nil) { + *a = 0; + return; + } + *a = *b; +} + +static uint32 +memequal16(uint32 s, uint16 *a, uint16 *b) +{ + USED(s); + return *a == *b; +} + +static void +memcopy16(uint32 s, uint16 *a, uint16 *b) +{ + USED(s); + if(b == nil) { + *a = 0; + return; + } + *a = *b; +} + +static uint32 +memequal32(uint32 s, uint32 *a, uint32 *b) +{ + USED(s); + return *a == *b; +} + +static void +memcopy32(uint32 s, uint32 *a, uint32 *b) +{ + USED(s); + if(b == nil) { + *a = 0; + return; + } + *a = *b; +} + +static uint32 +memequal64(uint32 s, uint64 *a, uint64 *b) +{ + USED(s); + return *a == *b; +} + +static void +memcopy64(uint32 s, uint64 *a, uint64 *b) +{ + USED(s); + if(b == nil) { + *a = 0; + return; + } + *a = *b; +} + +static uint32 +memequal128(uint32 s, uint64 *a, uint64 *b) +{ + USED(s); + return a[0] == b[0] && a[1] == b[1]; +} + +static void +memcopy128(uint32 s, uint64 *a, uint64 *b) +{ + USED(s); + if(b == nil) { + a[0] = 0; + a[1] = 0; + return; + } + a[0] = b[0]; + a[1] = b[1]; +} + +static void +slicecopy(uint32 s, Slice *a, Slice *b) +{ + USED(s); + if(b == nil) { + a->array = 0; + a->len = 0; + a->cap = 0; + return; + } + a->array = b->array; + a->len = b->len; + a->cap = b->cap; +} + +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 void +strcopy(uint32 s, String *a, String *b) +{ + USED(s); + if(b == nil) { + a->str = 0; + a->len = 0; + return; + } + a->str = b->str; + a->len = b->len; +} + +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 void +intercopy(uint32 s, Iface *a, Iface *b) +{ + USED(s); + if(b == nil) { + a->tab = 0; + a->data = 0; + return; + } + a->tab = b->tab; + a->data = b->data; +} + +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); +} + +static void +nilintercopy(uint32 s, Eface *a, Eface *b) +{ + USED(s); + if(b == nil) { + a->type = 0; + a->data = 0; + return; + } + a->type = b->type; + a->data = b->data; +} + +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, strcopy }, +[AINTER] { interhash, interequal, interprint, intercopy }, +[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, nilintercopy }, +[ASLICE] { runtime·nohash, runtime·noequal, memprint, slicecopy }, +[AMEM8] { memhash, memequal8, memprint, memcopy8 }, +[AMEM16] { memhash, memequal16, memprint, memcopy16 }, +[AMEM32] { memhash, memequal32, memprint, memcopy32 }, +[AMEM64] { memhash, memequal64, memprint, memcopy64 }, +[AMEM128] { memhash, memequal128, memprint, memcopy128 }, +[ANOEQ8] { runtime·nohash, runtime·noequal, memprint, memcopy8 }, +[ANOEQ16] { runtime·nohash, runtime·noequal, memprint, memcopy16 }, +[ANOEQ32] { runtime·nohash, runtime·noequal, memprint, memcopy32 }, +[ANOEQ64] { runtime·nohash, runtime·noequal, memprint, memcopy64 }, +[ANOEQ128] { runtime·nohash, runtime·noequal, memprint, memcopy128 }, +}; + +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; +} -- cgit v1.2.3