github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/runtime.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "runtime.h"
     6  #include "arch_GOARCH.h"
     7  #include "../../cmd/ld/textflag.h"
     8  
     9  enum {
    10  	maxround = sizeof(uintptr),
    11  };
    12  
    13  /*
    14   * We assume that all architectures turn faults and the like
    15   * into apparent calls to runtime.sigpanic.  If we see a "call"
    16   * to runtime.sigpanic, we do not back up the PC to find the
    17   * line number of the CALL instruction, because there is no CALL.
    18   */
    19  void	runtime·sigpanic(void);
    20  
    21  // The GOTRACEBACK environment variable controls the
    22  // behavior of a Go program that is crashing and exiting.
    23  //	GOTRACEBACK=0   suppress all tracebacks
    24  //	GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
    25  //	GOTRACEBACK=2   show tracebacks including runtime frames
    26  //	GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
    27  int32
    28  runtime·gotraceback(bool *crash)
    29  {
    30  	byte *p;
    31  
    32  	if(crash != nil)
    33  		*crash = false;
    34  	p = runtime·getenv("GOTRACEBACK");
    35  	if(p == nil || p[0] == '\0')
    36  		return 1;	// default is on
    37  	if(runtime·strcmp(p, (byte*)"crash") == 0) {
    38  		if(crash != nil)
    39  			*crash = true;
    40  		return 2;	// extra information
    41  	}
    42  	return runtime·atoi(p);
    43  }
    44  
    45  int32
    46  runtime·mcmp(byte *s1, byte *s2, uintptr n)
    47  {
    48  	uintptr i;
    49  	byte c1, c2;
    50  
    51  	for(i=0; i<n; i++) {
    52  		c1 = s1[i];
    53  		c2 = s2[i];
    54  		if(c1 < c2)
    55  			return -1;
    56  		if(c1 > c2)
    57  			return +1;
    58  	}
    59  	return 0;
    60  }
    61  
    62  
    63  byte*
    64  runtime·mchr(byte *p, byte c, byte *ep)
    65  {
    66  	for(; p < ep; p++)
    67  		if(*p == c)
    68  			return p;
    69  	return nil;
    70  }
    71  
    72  static int32	argc;
    73  static uint8**	argv;
    74  
    75  Slice os·Args;
    76  Slice syscall·envs;
    77  
    78  void (*runtime·sysargs)(int32, uint8**);
    79  
    80  void
    81  runtime·args(int32 c, uint8 **v)
    82  {
    83  	argc = c;
    84  	argv = v;
    85  	if(runtime·sysargs != nil)
    86  		runtime·sysargs(c, v);
    87  }
    88  
    89  int32 runtime·isplan9;
    90  int32 runtime·iswindows;
    91  
    92  // Information about what cpu features are available.
    93  // Set on startup in asm_{x86/amd64}.s.
    94  uint32 runtime·cpuid_ecx;
    95  uint32 runtime·cpuid_edx;
    96  
    97  void
    98  runtime·goargs(void)
    99  {
   100  	String *s;
   101  	int32 i;
   102  
   103  	// for windows implementation see "os" package
   104  	if(Windows)
   105  		return;
   106  
   107  	s = runtime·malloc(argc*sizeof s[0]);
   108  	for(i=0; i<argc; i++)
   109  		s[i] = runtime·gostringnocopy(argv[i]);
   110  	os·Args.array = (byte*)s;
   111  	os·Args.len = argc;
   112  	os·Args.cap = argc;
   113  }
   114  
   115  void
   116  runtime·goenvs_unix(void)
   117  {
   118  	String *s;
   119  	int32 i, n;
   120  
   121  	for(n=0; argv[argc+1+n] != 0; n++)
   122  		;
   123  
   124  	s = runtime·malloc(n*sizeof s[0]);
   125  	for(i=0; i<n; i++)
   126  		s[i] = runtime·gostringnocopy(argv[argc+1+i]);
   127  	syscall·envs.array = (byte*)s;
   128  	syscall·envs.len = n;
   129  	syscall·envs.cap = n;
   130  }
   131  
   132  void
   133  runtime·getgoroot(String out)
   134  {
   135  	byte *p;
   136  
   137  	p = runtime·getenv("GOROOT");
   138  	out = runtime·gostringnocopy(p);
   139  	FLUSH(&out);
   140  }
   141  
   142  int32
   143  runtime·atoi(byte *p)
   144  {
   145  	int32 n;
   146  
   147  	n = 0;
   148  	while('0' <= *p && *p <= '9')
   149  		n = n*10 + *p++ - '0';
   150  	return n;
   151  }
   152  
   153  static void
   154  TestAtomic64(void)
   155  {
   156  	uint64 z64, x64;
   157  
   158  	z64 = 42;
   159  	x64 = 0;
   160  	PREFETCH(&z64);
   161  	if(runtime·cas64(&z64, x64, 1))
   162  		runtime·throw("cas64 failed");
   163  	if(x64 != 0)
   164  		runtime·throw("cas64 failed");
   165  	x64 = 42;
   166  	if(!runtime·cas64(&z64, x64, 1))
   167  		runtime·throw("cas64 failed");
   168  	if(x64 != 42 || z64 != 1)
   169  		runtime·throw("cas64 failed");
   170  	if(runtime·atomicload64(&z64) != 1)
   171  		runtime·throw("load64 failed");
   172  	runtime·atomicstore64(&z64, (1ull<<40)+1);
   173  	if(runtime·atomicload64(&z64) != (1ull<<40)+1)
   174  		runtime·throw("store64 failed");
   175  	if(runtime·xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2)
   176  		runtime·throw("xadd64 failed");
   177  	if(runtime·atomicload64(&z64) != (2ull<<40)+2)
   178  		runtime·throw("xadd64 failed");
   179  	if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
   180  		runtime·throw("xchg64 failed");
   181  	if(runtime·atomicload64(&z64) != (3ull<<40)+3)
   182  		runtime·throw("xchg64 failed");
   183  }
   184  
   185  void
   186  runtime·check(void)
   187  {
   188  	int8 a;
   189  	uint8 b;
   190  	int16 c;
   191  	uint16 d;
   192  	int32 e;
   193  	uint32 f;
   194  	int64 g;
   195  	uint64 h;
   196  	float32 i, i1;
   197  	float64 j, j1;
   198  	byte *k, *k1;
   199  	uint16* l;
   200  	struct x1 {
   201  		byte x;
   202  	};
   203  	struct y1 {
   204  		struct x1 x1;
   205  		byte y;
   206  	};
   207  
   208  	if(sizeof(a) != 1) runtime·throw("bad a");
   209  	if(sizeof(b) != 1) runtime·throw("bad b");
   210  	if(sizeof(c) != 2) runtime·throw("bad c");
   211  	if(sizeof(d) != 2) runtime·throw("bad d");
   212  	if(sizeof(e) != 4) runtime·throw("bad e");
   213  	if(sizeof(f) != 4) runtime·throw("bad f");
   214  	if(sizeof(g) != 8) runtime·throw("bad g");
   215  	if(sizeof(h) != 8) runtime·throw("bad h");
   216  	if(sizeof(i) != 4) runtime·throw("bad i");
   217  	if(sizeof(j) != 8) runtime·throw("bad j");
   218  	if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k");
   219  	if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l");
   220  	if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1");
   221  	if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y");
   222  	if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1");
   223  
   224  	if(runtime·timediv(12345LL*1000000000+54321, 1000000000, &e) != 12345 || e != 54321)
   225  		runtime·throw("bad timediv");
   226  
   227  	uint32 z;
   228  	z = 1;
   229  	if(!runtime·cas(&z, 1, 2))
   230  		runtime·throw("cas1");
   231  	if(z != 2)
   232  		runtime·throw("cas2");
   233  
   234  	z = 4;
   235  	if(runtime·cas(&z, 5, 6))
   236  		runtime·throw("cas3");
   237  	if(z != 4)
   238  		runtime·throw("cas4");
   239  
   240  	k = (byte*)0xfedcb123;
   241  	if(sizeof(void*) == 8)
   242  		k = (byte*)((uintptr)k<<10);
   243  	if(runtime·casp((void**)&k, nil, nil))
   244  		runtime·throw("casp1");
   245  	k1 = k+1;
   246  	if(!runtime·casp((void**)&k, k, k1))
   247  		runtime·throw("casp2");
   248  	if(k != k1)
   249  		runtime·throw("casp3");
   250  
   251  	*(uint64*)&j = ~0ULL;
   252  	if(j == j)
   253  		runtime·throw("float64nan");
   254  	if(!(j != j))
   255  		runtime·throw("float64nan1");
   256  
   257  	*(uint64*)&j1 = ~1ULL;
   258  	if(j == j1)
   259  		runtime·throw("float64nan2");
   260  	if(!(j != j1))
   261  		runtime·throw("float64nan3");
   262  
   263  	*(uint32*)&i = ~0UL;
   264  	if(i == i)
   265  		runtime·throw("float32nan");
   266  	if(!(i != i))
   267  		runtime·throw("float32nan1");
   268  
   269  	*(uint32*)&i1 = ~1UL;
   270  	if(i == i1)
   271  		runtime·throw("float32nan2");
   272  	if(!(i != i1))
   273  		runtime·throw("float32nan3");
   274  
   275  	TestAtomic64();
   276  }
   277  
   278  void
   279  runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool retbool)
   280  {
   281  	Func *f, *g;
   282  	uintptr pc;
   283  	uintptr rpc[2];
   284  
   285  	/*
   286  	 * Ask for two PCs: the one we were asked for
   287  	 * and what it called, so that we can see if it
   288  	 * "called" sigpanic.
   289  	 */
   290  	retpc = 0;
   291  	if(runtime·callers(1+skip-1, rpc, 2) < 2) {
   292  		retfile = runtime·emptystring;
   293  		retline = 0;
   294  		retbool = false;
   295  	} else if((f = runtime·findfunc(rpc[1])) == nil) {
   296  		retfile = runtime·emptystring;
   297  		retline = 0;
   298  		retbool = true;  // have retpc at least
   299  	} else {
   300  		retpc = rpc[1];
   301  		pc = retpc;
   302  		g = runtime·findfunc(rpc[0]);
   303  		if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
   304  			pc--;
   305  		retline = runtime·funcline(f, pc, &retfile);
   306  		retbool = true;
   307  	}
   308  	FLUSH(&retpc);
   309  	FLUSH(&retfile);
   310  	FLUSH(&retline);
   311  	FLUSH(&retbool);
   312  }
   313  
   314  void
   315  runtime·Callers(intgo skip, Slice pc, intgo retn)
   316  {
   317  	// runtime.callers uses pc.array==nil as a signal
   318  	// to print a stack trace.  Pick off 0-length pc here
   319  	// so that we don't let a nil pc slice get to it.
   320  	if(pc.len == 0)
   321  		retn = 0;
   322  	else
   323  		retn = runtime·callers(skip, (uintptr*)pc.array, pc.len);
   324  	FLUSH(&retn);
   325  }
   326  
   327  void
   328  runtime·FuncForPC(uintptr pc, void *retf)
   329  {
   330  	retf = runtime·findfunc(pc);
   331  	FLUSH(&retf);
   332  }
   333  
   334  uint32
   335  runtime·fastrand1(void)
   336  {
   337  	uint32 x;
   338  
   339  	x = m->fastrand;
   340  	x += x;
   341  	if(x & 0x80000000L)
   342  		x ^= 0x88888eefUL;
   343  	m->fastrand = x;
   344  	return x;
   345  }
   346  
   347  static Lock ticksLock;
   348  static int64 ticks;
   349  
   350  int64
   351  runtime·tickspersecond(void)
   352  {
   353  	int64 res, t0, t1, c0, c1;
   354  
   355  	res = (int64)runtime·atomicload64((uint64*)&ticks);
   356  	if(res != 0)
   357  		return ticks;
   358  	runtime·lock(&ticksLock);
   359  	res = ticks;
   360  	if(res == 0) {
   361  		t0 = runtime·nanotime();
   362  		c0 = runtime·cputicks();
   363  		runtime·usleep(100*1000);
   364  		t1 = runtime·nanotime();
   365  		c1 = runtime·cputicks();
   366  		if(t1 == t0)
   367  			t1++;
   368  		res = (c1-c0)*1000*1000*1000/(t1-t0);
   369  		if(res == 0)
   370  			res++;
   371  		runtime·atomicstore64((uint64*)&ticks, res);
   372  	}
   373  	runtime·unlock(&ticksLock);
   374  	return res;
   375  }
   376  
   377  void
   378  runtime∕pprof·runtime_cyclesPerSecond(int64 res)
   379  {
   380  	res = runtime·tickspersecond();
   381  	FLUSH(&res);
   382  }
   383  
   384  DebugVars	runtime·debug;
   385  
   386  static struct {
   387  	int8*	name;
   388  	int32*	value;
   389  } dbgvar[] = {
   390  	{"gctrace", &runtime·debug.gctrace},
   391  	{"schedtrace", &runtime·debug.schedtrace},
   392  	{"scheddetail", &runtime·debug.scheddetail},
   393  };
   394  
   395  void
   396  runtime·parsedebugvars(void)
   397  {
   398  	byte *p;
   399  	intgo i, n;
   400  
   401  	p = runtime·getenv("GODEBUG");
   402  	if(p == nil)
   403  		return;
   404  	for(;;) {
   405  		for(i=0; i<nelem(dbgvar); i++) {
   406  			n = runtime·findnull((byte*)dbgvar[i].name);
   407  			if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
   408  				*dbgvar[i].value = runtime·atoi(p+n+1);
   409  		}
   410  		p = runtime·strstr(p, (byte*)",");
   411  		if(p == nil)
   412  			break;
   413  		p++;
   414  	}
   415  }
   416  
   417  // Poor mans 64-bit division.
   418  // This is a very special function, do not use it if you are not sure what you are doing.
   419  // int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
   420  // Handles overflow in a time-specific manner.
   421  #pragma textflag NOSPLIT
   422  int32
   423  runtime·timediv(int64 v, int32 div, int32 *rem)
   424  {
   425  	int32 res, bit;
   426  
   427  	if(v >= (int64)div*0x7fffffffLL) {
   428  		if(rem != nil)
   429  			*rem = 0;
   430  		return 0x7fffffff;
   431  	}
   432  	res = 0;
   433  	for(bit = 30; bit >= 0; bit--) {
   434  		if(v >= ((int64)div<<bit)) {
   435  			v = v - ((int64)div<<bit);
   436  			res += 1<<bit;
   437  		}
   438  	}
   439  	if(rem != nil)
   440  		*rem = v;
   441  	return res;
   442  }