github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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 8 enum { 9 maxround = sizeof(uintptr), 10 }; 11 12 /* 13 * We assume that all architectures turn faults and the like 14 * into apparent calls to runtime.sigpanic. If we see a "call" 15 * to runtime.sigpanic, we do not back up the PC to find the 16 * line number of the CALL instruction, because there is no CALL. 17 */ 18 void runtime·sigpanic(void); 19 20 // The GOTRACEBACK environment variable controls the 21 // behavior of a Go program that is crashing and exiting. 22 // GOTRACEBACK=0 suppress all tracebacks 23 // GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames 24 // GOTRACEBACK=2 show tracebacks including runtime frames 25 // GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc) 26 int32 27 runtime·gotraceback(bool *crash) 28 { 29 byte *p; 30 31 if(crash != nil) 32 *crash = false; 33 p = runtime·getenv("GOTRACEBACK"); 34 if(p == nil || p[0] == '\0') 35 return 1; // default is on 36 if(runtime·strcmp(p, (byte*)"crash") == 0) { 37 if(crash != nil) 38 *crash = true; 39 return 2; // extra information 40 } 41 return runtime·atoi(p); 42 } 43 44 int32 45 runtime·mcmp(byte *s1, byte *s2, uintptr n) 46 { 47 uintptr i; 48 byte c1, c2; 49 50 for(i=0; i<n; i++) { 51 c1 = s1[i]; 52 c2 = s2[i]; 53 if(c1 < c2) 54 return -1; 55 if(c1 > c2) 56 return +1; 57 } 58 return 0; 59 } 60 61 62 byte* 63 runtime·mchr(byte *p, byte c, byte *ep) 64 { 65 for(; p < ep; p++) 66 if(*p == c) 67 return p; 68 return nil; 69 } 70 71 static int32 argc; 72 static uint8** argv; 73 74 Slice os·Args; 75 Slice syscall·envs; 76 77 void (*runtime·sysargs)(int32, uint8**); 78 79 void 80 runtime·args(int32 c, uint8 **v) 81 { 82 argc = c; 83 argv = v; 84 if(runtime·sysargs != nil) 85 runtime·sysargs(c, v); 86 } 87 88 int32 runtime·isplan9; 89 int32 runtime·iswindows; 90 91 // Information about what cpu features are available. 92 // Set on startup in asm_{x86/amd64}.s. 93 uint32 runtime·cpuid_ecx; 94 uint32 runtime·cpuid_edx; 95 96 void 97 runtime·goargs(void) 98 { 99 String *s; 100 int32 i; 101 102 // for windows implementation see "os" package 103 if(Windows) 104 return; 105 106 s = runtime·malloc(argc*sizeof s[0]); 107 for(i=0; i<argc; i++) 108 s[i] = runtime·gostringnocopy(argv[i]); 109 os·Args.array = (byte*)s; 110 os·Args.len = argc; 111 os·Args.cap = argc; 112 } 113 114 void 115 runtime·goenvs_unix(void) 116 { 117 String *s; 118 int32 i, n; 119 120 for(n=0; argv[argc+1+n] != 0; n++) 121 ; 122 123 s = runtime·malloc(n*sizeof s[0]); 124 for(i=0; i<n; i++) 125 s[i] = runtime·gostringnocopy(argv[argc+1+i]); 126 syscall·envs.array = (byte*)s; 127 syscall·envs.len = n; 128 syscall·envs.cap = n; 129 } 130 131 void 132 runtime·getgoroot(String out) 133 { 134 byte *p; 135 136 p = runtime·getenv("GOROOT"); 137 out = runtime·gostringnocopy(p); 138 FLUSH(&out); 139 } 140 141 int32 142 runtime·atoi(byte *p) 143 { 144 int32 n; 145 146 n = 0; 147 while('0' <= *p && *p <= '9') 148 n = n*10 + *p++ - '0'; 149 return n; 150 } 151 152 static void 153 TestAtomic64(void) 154 { 155 uint64 z64, x64; 156 157 z64 = 42; 158 x64 = 0; 159 PREFETCH(&z64); 160 if(runtime·cas64(&z64, &x64, 1)) 161 runtime·throw("cas64 failed"); 162 if(x64 != 42) 163 runtime·throw("cas64 failed"); 164 if(!runtime·cas64(&z64, &x64, 1)) 165 runtime·throw("cas64 failed"); 166 if(x64 != 42 || z64 != 1) 167 runtime·throw("cas64 failed"); 168 if(runtime·atomicload64(&z64) != 1) 169 runtime·throw("load64 failed"); 170 runtime·atomicstore64(&z64, (1ull<<40)+1); 171 if(runtime·atomicload64(&z64) != (1ull<<40)+1) 172 runtime·throw("store64 failed"); 173 if(runtime·xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2) 174 runtime·throw("xadd64 failed"); 175 if(runtime·atomicload64(&z64) != (2ull<<40)+2) 176 runtime·throw("xadd64 failed"); 177 if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2) 178 runtime·throw("xchg64 failed"); 179 if(runtime·atomicload64(&z64) != (3ull<<40)+3) 180 runtime·throw("xchg64 failed"); 181 } 182 183 void 184 runtime·check(void) 185 { 186 int8 a; 187 uint8 b; 188 int16 c; 189 uint16 d; 190 int32 e; 191 uint32 f; 192 int64 g; 193 uint64 h; 194 float32 i, i1; 195 float64 j, j1; 196 void* k; 197 uint16* l; 198 struct x1 { 199 byte x; 200 }; 201 struct y1 { 202 struct x1 x1; 203 byte y; 204 }; 205 206 if(sizeof(a) != 1) runtime·throw("bad a"); 207 if(sizeof(b) != 1) runtime·throw("bad b"); 208 if(sizeof(c) != 2) runtime·throw("bad c"); 209 if(sizeof(d) != 2) runtime·throw("bad d"); 210 if(sizeof(e) != 4) runtime·throw("bad e"); 211 if(sizeof(f) != 4) runtime·throw("bad f"); 212 if(sizeof(g) != 8) runtime·throw("bad g"); 213 if(sizeof(h) != 8) runtime·throw("bad h"); 214 if(sizeof(i) != 4) runtime·throw("bad i"); 215 if(sizeof(j) != 8) runtime·throw("bad j"); 216 if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k"); 217 if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l"); 218 if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1"); 219 if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y"); 220 if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1"); 221 222 uint32 z; 223 z = 1; 224 if(!runtime·cas(&z, 1, 2)) 225 runtime·throw("cas1"); 226 if(z != 2) 227 runtime·throw("cas2"); 228 229 z = 4; 230 if(runtime·cas(&z, 5, 6)) 231 runtime·throw("cas3"); 232 if(z != 4) 233 runtime·throw("cas4"); 234 235 *(uint64*)&j = ~0ULL; 236 if(j == j) 237 runtime·throw("float64nan"); 238 if(!(j != j)) 239 runtime·throw("float64nan1"); 240 241 *(uint64*)&j1 = ~1ULL; 242 if(j == j1) 243 runtime·throw("float64nan2"); 244 if(!(j != j1)) 245 runtime·throw("float64nan3"); 246 247 *(uint32*)&i = ~0UL; 248 if(i == i) 249 runtime·throw("float32nan"); 250 if(!(i != i)) 251 runtime·throw("float32nan1"); 252 253 *(uint32*)&i1 = ~1UL; 254 if(i == i1) 255 runtime·throw("float32nan2"); 256 if(!(i != i1)) 257 runtime·throw("float32nan3"); 258 259 TestAtomic64(); 260 } 261 262 void 263 runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool retbool) 264 { 265 Func *f, *g; 266 uintptr pc; 267 uintptr rpc[2]; 268 269 /* 270 * Ask for two PCs: the one we were asked for 271 * and what it called, so that we can see if it 272 * "called" sigpanic. 273 */ 274 retpc = 0; 275 if(runtime·callers(1+skip-1, rpc, 2) < 2) { 276 retfile = runtime·emptystring; 277 retline = 0; 278 retbool = false; 279 } else if((f = runtime·findfunc(rpc[1])) == nil) { 280 retfile = runtime·emptystring; 281 retline = 0; 282 retbool = true; // have retpc at least 283 } else { 284 retpc = rpc[1]; 285 retfile = f->src; 286 pc = retpc; 287 g = runtime·findfunc(rpc[0]); 288 if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic)) 289 pc--; 290 retline = runtime·funcline(f, pc); 291 retbool = true; 292 } 293 FLUSH(&retpc); 294 FLUSH(&retfile); 295 FLUSH(&retline); 296 FLUSH(&retbool); 297 } 298 299 void 300 runtime·Callers(intgo skip, Slice pc, intgo retn) 301 { 302 // runtime.callers uses pc.array==nil as a signal 303 // to print a stack trace. Pick off 0-length pc here 304 // so that we don't let a nil pc slice get to it. 305 if(pc.len == 0) 306 retn = 0; 307 else 308 retn = runtime·callers(skip, (uintptr*)pc.array, pc.len); 309 FLUSH(&retn); 310 } 311 312 void 313 runtime·FuncForPC(uintptr pc, void *retf) 314 { 315 retf = runtime·findfunc(pc); 316 FLUSH(&retf); 317 } 318 319 uint32 320 runtime·fastrand1(void) 321 { 322 uint32 x; 323 324 x = m->fastrand; 325 x += x; 326 if(x & 0x80000000L) 327 x ^= 0x88888eefUL; 328 m->fastrand = x; 329 return x; 330 } 331 332 static Lock ticksLock; 333 static int64 ticks; 334 335 int64 336 runtime·tickspersecond(void) 337 { 338 int64 res, t0, t1, c0, c1; 339 340 res = (int64)runtime·atomicload64((uint64*)&ticks); 341 if(res != 0) 342 return ticks; 343 runtime·lock(&ticksLock); 344 res = ticks; 345 if(res == 0) { 346 t0 = runtime·nanotime(); 347 c0 = runtime·cputicks(); 348 runtime·usleep(100*1000); 349 t1 = runtime·nanotime(); 350 c1 = runtime·cputicks(); 351 if(t1 == t0) 352 t1++; 353 res = (c1-c0)*1000*1000*1000/(t1-t0); 354 if(res == 0) 355 res++; 356 runtime·atomicstore64((uint64*)&ticks, res); 357 } 358 runtime·unlock(&ticksLock); 359 return res; 360 } 361 362 void 363 runtime∕pprof·runtime_cyclesPerSecond(int64 res) 364 { 365 res = runtime·tickspersecond(); 366 FLUSH(&res); 367 }