summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/runtime.c')
-rw-r--r--src/pkg/runtime/runtime.c728
1 files changed, 728 insertions, 0 deletions
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<n; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if(c1 < c2)
+ return -1;
+ if(c1 > 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<argc; i++)
+ s[i] = runtime·gostringnocopy(argv[i]);
+ os·Args.array = (byte*)s;
+ os·Args.len = argc;
+ os·Args.cap = argc;
+}
+
+void
+runtime·goenvs_unix(void)
+{
+ String *s;
+ int32 i, n;
+
+ for(n=0; argv[argc+1+n] != 0; n++)
+ ;
+
+ s = runtime·malloc(n*sizeof s[0]);
+ for(i=0; i<n; i++)
+ s[i] = runtime·gostringnocopy(argv[argc+1+i]);
+ os·Envs.array = (byte*)s;
+ os·Envs.len = n;
+ os·Envs.cap = n;
+}
+
+byte*
+runtime·getenv(int8 *s)
+{
+ int32 i, j, len;
+ byte *v, *bs;
+ String* envv;
+ int32 envc;
+
+ bs = (byte*)s;
+ len = runtime·findnull(bs);
+ envv = (String*)os·Envs.array;
+ envc = os·Envs.len;
+ for(i=0; i<envc; i++){
+ if(envv[i].len <= len)
+ continue;
+ v = envv[i].str;
+ for(j=0; j<len; j++)
+ if(bs[j] != v[j])
+ goto nomatch;
+ if(v[len] != '=')
+ goto nomatch;
+ return v+len+1;
+ nomatch:;
+ }
+ return nil;
+}
+
+void
+runtime·getgoroot(String out)
+{
+ byte *p;
+
+ p = runtime·getenv("GOROOT");
+ out = runtime·gostringnocopy(p);
+ FLUSH(&out);
+}
+
+int32
+runtime·atoi(byte *p)
+{
+ int32 n;
+
+ n = 0;
+ while('0' <= *p && *p <= '9')
+ n = n*10 + *p++ - '0';
+ return n;
+}
+
+void
+runtime·check(void)
+{
+ int8 a;
+ uint8 b;
+ int16 c;
+ uint16 d;
+ int32 e;
+ uint32 f;
+ int64 g;
+ uint64 h;
+ float32 i;
+ float64 j;
+ void* k;
+ uint16* l;
+ struct x1 {
+ byte x;
+ };
+ struct y1 {
+ struct x1 x1;
+ byte y;
+ };
+
+ if(sizeof(a) != 1) runtime·throw("bad a");
+ if(sizeof(b) != 1) runtime·throw("bad b");
+ if(sizeof(c) != 2) runtime·throw("bad c");
+ if(sizeof(d) != 2) runtime·throw("bad d");
+ if(sizeof(e) != 4) runtime·throw("bad e");
+ if(sizeof(f) != 4) runtime·throw("bad f");
+ if(sizeof(g) != 8) runtime·throw("bad g");
+ if(sizeof(h) != 8) runtime·throw("bad h");
+ if(sizeof(i) != 4) runtime·throw("bad i");
+ if(sizeof(j) != 8) runtime·throw("bad j");
+ if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k");
+ if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l");
+ if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1");
+ if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y");
+ if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1");
+
+ uint32 z;
+ z = 1;
+ if(!runtime·cas(&z, 1, 2))
+ runtime·throw("cas1");
+ if(z != 2)
+ runtime·throw("cas2");
+
+ z = 4;
+ if(runtime·cas(&z, 5, 6))
+ runtime·throw("cas3");
+ if(z != 4)
+ runtime·throw("cas4");
+
+ runtime·initsig(0);
+}
+
+/*
+ * map and chan helpers for
+ * dealing with unknown types
+ */
+static uintptr
+memhash(uint32 s, void *a)
+{
+ byte *b;
+ uintptr hash;
+
+ b = a;
+ if(sizeof(hash) == 4)
+ hash = 2860486313U;
+ else
+ hash = 33054211828000289ULL;
+ while(s > 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;
+}