1
0
mirror of https://github.com/golang/go synced 2024-10-04 18:21:21 -06:00
go/src/pkg/runtime/runtime.c

729 lines
12 KiB
C
Raw Normal View History

2008-06-05 20:38:39 -06:00
// 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"
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
#include "stack.h"
2008-06-05 20:38:39 -06:00
enum {
maxround = sizeof(uintptr),
};
uint32 runtime·panicking;
void (*runtime·destroylock)(Lock*);
2008-06-05 20:38:39 -06:00
/*
* 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;
2008-06-16 18:04:30 -06:00
void
runtime·startpanic(void)
2008-06-16 18:04:30 -06:00
{
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);
2008-06-16 18:04:30 -06:00
}
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");
}
2008-06-16 23:34:50 -06:00
void
runtime·throw(int8 *s)
2008-06-05 20:38:39 -06:00
{
runtime·startpanic();
runtime·printf("throw: %s\n", s);
runtime·dopanic(0);
*(int32*)0 = 0; // not reached
runtime·exit(1); // even more not reached
2008-06-05 20:38:39 -06:00
}
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;
}
2008-07-13 15:29:46 -06:00
uint32
runtime·rnd(uint32 n, uint32 m)
2008-07-13 15:29:46 -06:00
{
uint32 r;
2008-11-05 22:50:28 -07:00
if(m > maxround)
m = maxround;
2008-07-13 15:29:46 -06:00
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);
}
2008-07-13 15:29:46 -06:00
/*
* map and chan helpers for
* dealing with unknown types
*/
static uintptr
2008-07-13 15:29:46 -06:00
memhash(uint32 s, void *a)
{
2008-11-13 11:35:44 -07:00
byte *b;
uintptr hash;
2008-11-13 11:35:44 -07:00
b = a;
if(sizeof(hash) == 4)
hash = 2860486313U;
else
hash = 33054211828000289ULL;
2008-11-13 11:35:44 -07:00
while(s > 0) {
if(sizeof(hash) == 4)
hash = (hash ^ *b) * 3267000013UL;
else
hash = (hash ^ *b) * 23344194077549503ULL;
2008-11-13 11:35:44 -07:00
b++;
s--;
}
return hash;
2008-07-13 15:29:46 -06:00
}
static uint32
memequal(uint32 s, void *a, void *b)
{
byte *ba, *bb, *aend;
2008-07-13 15:29:46 -06:00
if(a == b)
return 1;
2008-07-13 15:29:46 -06:00
ba = a;
bb = b;
aend = ba+s;
while(ba != aend) {
if(*ba != *bb)
2008-07-13 15:29:46 -06:00
return 0;
ba++;
bb++;
}
2008-07-13 15:29:46 -06:00
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);
2008-07-13 15:29:46 -06:00
}
static void
memcopy(uint32 s, void *a, void *b)
{
if(b == nil) {
runtime·memclr(a,s);
2008-07-13 15:29:46 -06:00
return;
}
runtime·memmove(a,b,s);
2008-07-13 15:29:46 -06:00
}
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)
2008-07-13 15:29:46 -06:00
{
USED(s);
return memhash((*a).len, (*a).str);
2008-07-13 15:29:46 -06:00
}
static uint32
strequal(uint32 s, String *a, String *b)
2008-07-13 15:29:46 -06:00
{
int32 alen;
USED(s);
alen = a->len;
if(alen != b->len)
return false;
return memequal(alen, a->str, b->str);
2008-07-13 15:29:46 -06:00
}
static void
strprint(uint32 s, String *a)
2008-07-13 15:29:46 -06:00
{
USED(s);
runtime·printstring(*a);
2008-07-13 15:29:46 -06:00
}
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)
2008-07-13 15:29:46 -06:00
{
USED(s);
return runtime·ifacehash(*a);
2008-07-13 15:29:46 -06:00
}
static void
interprint(uint32 s, Iface *a)
2008-07-13 15:29:46 -06:00
{
USED(s);
runtime·printiface(*a);
2008-07-13 15:29:46 -06:00
}
static uint32
interequal(uint32 s, Iface *a, Iface *b)
2008-07-13 15:29:46 -06:00
{
USED(s);
return runtime·ifaceeq_c(*a, *b);
2008-07-13 15:29:46 -06:00
}
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)
2008-07-13 15:29:46 -06:00
{
USED(s);
USED(a);
runtime·panicstring("hash of unhashable type");
return 0;
2008-07-13 15:29:46 -06:00
}
uint32
runtime·noequal(uint32 s, void *a, void *b)
2008-07-13 15:29:46 -06:00
{
USED(s);
USED(a);
USED(b);
runtime·panicstring("comparing uncomparable types");
return 0;
2008-07-13 15:29:46 -06:00
}
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 },
2008-07-13 15:29:46 -06:00
};
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;
2011-02-02 14:44:20 -07:00
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) {
2011-02-02 14:44:20 -07:00
retfile = runtime·emptystring;
retline = 0;
retbool = true; // have retpc at least
} else {
retpc = rpc[1];
retfile = f->src;
2011-02-02 14:44:20 -07:00
pc = retpc;
g = runtime·findfunc(rpc[0]);
if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
2011-02-02 14:44:20 -07:00
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;
}