LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "zaexperiment.h" | 7 #include "zaexperiment.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 #include "stack.h" | 9 #include "stack.h" |
10 #include "race.h" | 10 #include "race.h" |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 // In particular, it must be done before mallocinit below calls racemaps
hadow. | 151 // In particular, it must be done before mallocinit below calls racemaps
hadow. |
152 if(raceenabled) | 152 if(raceenabled) |
153 g->racectx = runtime·raceinit(); | 153 g->racectx = runtime·raceinit(); |
154 | 154 |
155 runtime·sched.maxmcount = 10000; | 155 runtime·sched.maxmcount = 10000; |
156 runtime·precisestack = true; // haveexperiment("precisestack"); | 156 runtime·precisestack = true; // haveexperiment("precisestack"); |
157 | 157 |
158 runtime·symtabinit(); | 158 runtime·symtabinit(); |
159 runtime·stackinit(); | 159 runtime·stackinit(); |
160 runtime·mallocinit(); | 160 runtime·mallocinit(); |
161 runtime·gcinit(); | |
162 runtime·chaninit(); | 161 runtime·chaninit(); |
163 mcommoninit(g->m); | 162 mcommoninit(g->m); |
164 ········ | 163 ········ |
165 // Initialize the itable value for newErrorCString, | 164 // Initialize the itable value for newErrorCString, |
166 // so that the next time it gets called, possibly | 165 // so that the next time it gets called, possibly |
167 // in a fault during a garbage collection, it will not | 166 // in a fault during a garbage collection, it will not |
168 // need to allocated memory. | 167 // need to allocated memory. |
169 runtime·newErrorCString(0, &i); | 168 runtime·newErrorCString(0, &i); |
170 ········ | 169 ········ |
171 // Initialize the cached gotraceback value, since | |
172 // gotraceback calls getenv, which mallocs on Plan 9. | |
173 runtime·gotraceback(nil); | |
174 | |
175 runtime·goargs(); | 170 runtime·goargs(); |
176 runtime·goenvs(); | 171 runtime·goenvs(); |
177 runtime·parsedebugvars(); | 172 runtime·parsedebugvars(); |
| 173 runtime·gcinit(); |
178 | 174 |
179 runtime·sched.lastpoll = runtime·nanotime(); | 175 runtime·sched.lastpoll = runtime·nanotime(); |
180 procs = 1; | 176 procs = 1; |
181 p = runtime·getenv("GOMAXPROCS"); | 177 p = runtime·getenv("GOMAXPROCS"); |
182 if(p != nil && (n = runtime·atoi(p)) > 0) { | 178 if(p != nil && (n = runtime·atoi(p)) > 0) { |
183 if(n > MaxGomaxprocs) | 179 if(n > MaxGomaxprocs) |
184 n = MaxGomaxprocs; | 180 n = MaxGomaxprocs; |
185 procs = n; | 181 procs = n; |
186 } | 182 } |
187 runtime·allp = runtime·mallocgc((MaxGomaxprocs+1)*sizeof(runtime·allp[0]
), nil, 0); | 183 runtime·allp = runtime·mallocgc((MaxGomaxprocs+1)*sizeof(runtime·allp[0]
), nil, 0); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 258 |
263 main·main(); | 259 main·main(); |
264 if(raceenabled) | 260 if(raceenabled) |
265 runtime·racefini(); | 261 runtime·racefini(); |
266 | 262 |
267 // Make racy client program work: if panicking on | 263 // Make racy client program work: if panicking on |
268 // another goroutine at the same time as main returns, | 264 // another goroutine at the same time as main returns, |
269 // let the other goroutine finish printing the panic trace. | 265 // let the other goroutine finish printing the panic trace. |
270 // Once it does, it will exit. See issue 3934. | 266 // Once it does, it will exit. See issue 3934. |
271 if(runtime·panicking) | 267 if(runtime·panicking) |
272 » » runtime·park(nil, nil, "panicwait"); | 268 » » runtime·park(nil, nil, runtime·gostringnocopy((byte*)"panicwait"
)); |
273 | 269 |
274 runtime·exit(0); | 270 runtime·exit(0); |
275 for(;;) | 271 for(;;) |
276 *(int32*)runtime·main = 0; | 272 *(int32*)runtime·main = 0; |
277 } | 273 } |
278 | 274 |
279 void | 275 void |
280 runtime·goroutineheader(G *gp) | 276 runtime·goroutineheader(G *gp) |
281 { | 277 { |
282 » int8 *status; | 278 » String status; |
283 int64 waitfor; | 279 int64 waitfor; |
284 | 280 |
285 switch(gp->status) { | 281 switch(gp->status) { |
286 case Gidle: | 282 case Gidle: |
287 » » status = "idle"; | 283 » » status = runtime·gostringnocopy((byte*)"idle"); |
288 break; | 284 break; |
289 case Grunnable: | 285 case Grunnable: |
290 » » status = "runnable"; | 286 » » status = runtime·gostringnocopy((byte*)"runnable"); |
291 break; | 287 break; |
292 case Grunning: | 288 case Grunning: |
293 » » status = "running"; | 289 » » status = runtime·gostringnocopy((byte*)"running"); |
294 break; | 290 break; |
295 case Gsyscall: | 291 case Gsyscall: |
296 » » status = "syscall"; | 292 » » status = runtime·gostringnocopy((byte*)"syscall"); |
297 break; | 293 break; |
298 case Gwaiting: | 294 case Gwaiting: |
299 » » if(gp->waitreason) | 295 » » if(gp->waitreason.str != nil) |
300 status = gp->waitreason; | 296 status = gp->waitreason; |
301 else | 297 else |
302 » » » status = "waiting"; | 298 » » » status = runtime·gostringnocopy((byte*)"waiting"); |
303 break; | 299 break; |
304 default: | 300 default: |
305 » » status = "???"; | 301 » » status = runtime·gostringnocopy((byte*)"???"); |
306 break; | 302 break; |
307 } | 303 } |
308 | 304 |
309 // approx time the G is blocked, in minutes | 305 // approx time the G is blocked, in minutes |
310 waitfor = 0; | 306 waitfor = 0; |
311 if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince !
= 0) | 307 if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince !
= 0) |
312 waitfor = (runtime·nanotime() - gp->waitsince) / (60LL*1000*1000
*1000); | 308 waitfor = (runtime·nanotime() - gp->waitsince) / (60LL*1000*1000
*1000); |
313 | 309 |
314 » runtime·printf("goroutine %D [%s", gp->goid, status); | 310 » runtime·printf("goroutine %D [%S", gp->goid, status); |
315 if(waitfor >= 1) | 311 if(waitfor >= 1) |
316 runtime·printf(", %D minutes", waitfor); | 312 runtime·printf(", %D minutes", waitfor); |
317 if(gp->lockedm != nil) | 313 if(gp->lockedm != nil) |
318 runtime·printf(", locked to thread"); | 314 runtime·printf(", locked to thread"); |
319 runtime·printf("]:\n"); | 315 runtime·printf("]:\n"); |
320 } | 316 } |
321 | 317 |
322 void | 318 void |
323 runtime·tracebackothers(G *me) | 319 runtime·tracebackothers(G *me) |
324 { | 320 { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 } | 497 } |
502 | 498 |
503 void | 499 void |
504 runtime·stoptheworld(void) | 500 runtime·stoptheworld(void) |
505 { | 501 { |
506 int32 i; | 502 int32 i; |
507 uint32 s; | 503 uint32 s; |
508 P *p; | 504 P *p; |
509 bool wait; | 505 bool wait; |
510 | 506 |
| 507 // If we hold a lock, then we won't be able to stop another M |
| 508 // that is blocked trying to acquire the lock. |
| 509 if(g->m->locks > 0) |
| 510 runtime·throw("stoptheworld: holding locks"); |
| 511 // There is no evidence that stoptheworld on g0 does not work, |
| 512 // we just don't do it today. |
| 513 if(g == g->m->g0) |
| 514 runtime·throw("stoptheworld: on g0"); |
511 runtime·lock(&runtime·sched.lock); | 515 runtime·lock(&runtime·sched.lock); |
512 runtime·sched.stopwait = runtime·gomaxprocs; | 516 runtime·sched.stopwait = runtime·gomaxprocs; |
513 runtime·atomicstore((uint32*)&runtime·sched.gcwaiting, 1); | 517 runtime·atomicstore((uint32*)&runtime·sched.gcwaiting, 1); |
514 preemptall(); | 518 preemptall(); |
515 // stop current P | 519 // stop current P |
516 g->m->p->status = Pgcstop; | 520 g->m->p->status = Pgcstop; |
517 runtime·sched.stopwait--; | 521 runtime·sched.stopwait--; |
518 // try to retake all P's in Psyscall status | 522 // try to retake all P's in Psyscall status |
519 for(i = 0; i < runtime·gomaxprocs; i++) { | 523 for(i = 0; i < runtime·gomaxprocs; i++) { |
520 p = runtime·allp[i]; | 524 p = runtime·allp[i]; |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1400 { | 1404 { |
1401 if(g->m->lockedg == nil) { | 1405 if(g->m->lockedg == nil) { |
1402 g->m->curg->m = nil; | 1406 g->m->curg->m = nil; |
1403 g->m->curg = nil; | 1407 g->m->curg = nil; |
1404 } | 1408 } |
1405 } | 1409 } |
1406 | 1410 |
1407 // Puts the current goroutine into a waiting state and calls unlockf. | 1411 // Puts the current goroutine into a waiting state and calls unlockf. |
1408 // If unlockf returns false, the goroutine is resumed. | 1412 // If unlockf returns false, the goroutine is resumed. |
1409 void | 1413 void |
1410 runtime·park(bool(*unlockf)(G*, void*), void *lock, int8 *reason) | 1414 runtime·park(bool(*unlockf)(G*, void*), void *lock, String reason) |
1411 { | 1415 { |
1412 if(g->status != Grunning) | 1416 if(g->status != Grunning) |
1413 runtime·throw("bad g status"); | 1417 runtime·throw("bad g status"); |
1414 g->m->waitlock = lock; | 1418 g->m->waitlock = lock; |
1415 g->m->waitunlockf = unlockf; | 1419 g->m->waitunlockf = unlockf; |
1416 g->waitreason = reason; | 1420 g->waitreason = reason; |
1417 runtime·mcall(runtime·park_m); | 1421 runtime·mcall(runtime·park_m); |
1418 } | 1422 } |
1419 | 1423 |
1420 bool | 1424 bool |
1421 runtime·parkunlock_c(G *gp, void *lock) | 1425 runtime·parkunlock_c(G *gp, void *lock) |
1422 { | 1426 { |
1423 USED(gp); | 1427 USED(gp); |
1424 runtime·unlock(lock); | 1428 runtime·unlock(lock); |
1425 return true; | 1429 return true; |
1426 } | 1430 } |
1427 | 1431 |
1428 // Puts the current goroutine into a waiting state and unlocks the lock. | 1432 // Puts the current goroutine into a waiting state and unlocks the lock. |
1429 // The goroutine can be made runnable again by calling runtime·ready(gp). | 1433 // The goroutine can be made runnable again by calling runtime·ready(gp). |
1430 void | 1434 void |
1431 runtime·parkunlock(Lock *lock, int8 *reason) | 1435 runtime·parkunlock(Lock *lock, String reason) |
1432 { | 1436 { |
1433 runtime·park(runtime·parkunlock_c, lock, reason); | 1437 runtime·park(runtime·parkunlock_c, lock, reason); |
1434 } | 1438 } |
1435 | 1439 |
1436 // runtime·park continuation on g0. | 1440 // runtime·park continuation on g0. |
1437 void | 1441 void |
1438 runtime·park_m(G *gp) | 1442 runtime·park_m(G *gp) |
1439 { | 1443 { |
1440 bool ok; | 1444 bool ok; |
1441 | 1445 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 { | 1502 { |
1499 gp->status = Gdead; | 1503 gp->status = Gdead; |
1500 gp->m = nil; | 1504 gp->m = nil; |
1501 gp->lockedm = nil; | 1505 gp->lockedm = nil; |
1502 g->m->lockedg = nil; | 1506 g->m->lockedg = nil; |
1503 gp->paniconfault = 0; | 1507 gp->paniconfault = 0; |
1504 gp->defer = nil; // should be true already but just in case. | 1508 gp->defer = nil; // should be true already but just in case. |
1505 gp->panic = nil; // non-nil for Goexit during panic. points at stack-all
ocated data. | 1509 gp->panic = nil; // non-nil for Goexit during panic. points at stack-all
ocated data. |
1506 gp->writenbuf = 0; | 1510 gp->writenbuf = 0; |
1507 gp->writebuf = nil; | 1511 gp->writebuf = nil; |
1508 » gp->waitreason = nil; | 1512 » gp->waitreason.str = nil; |
| 1513 » gp->waitreason.len = 0; |
1509 gp->param = nil; | 1514 gp->param = nil; |
1510 ········ | 1515 ········ |
1511 dropg(); | 1516 dropg(); |
1512 | 1517 |
1513 if(g->m->locked & ~LockExternal) { | 1518 if(g->m->locked & ~LockExternal) { |
1514 runtime·printf("invalid m->locked = %d\n", g->m->locked); | 1519 runtime·printf("invalid m->locked = %d\n", g->m->locked); |
1515 runtime·throw("internal lockOSThread error"); | 1520 runtime·throw("internal lockOSThread error"); |
1516 }······· | 1521 }······· |
1517 g->m->locked = 0; | 1522 g->m->locked = 0; |
1518 runtime·unwindstack(gp, nil); | 1523 runtime·unwindstack(gp, nil); |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2818 " locks=%d dying=%d helpgc=%d spinning=%d blocked=%d loc
kedg=%D\n", | 2823 " locks=%d dying=%d helpgc=%d spinning=%d blocked=%d loc
kedg=%D\n", |
2819 mp->id, id1, id2, | 2824 mp->id, id1, id2, |
2820 mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->d
ying, mp->helpgc, | 2825 mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->d
ying, mp->helpgc, |
2821 mp->spinning, g->m->blocked, id3); | 2826 mp->spinning, g->m->blocked, id3); |
2822 } | 2827 } |
2823 runtime·lock(&allglock); | 2828 runtime·lock(&allglock); |
2824 for(gi = 0; gi < runtime·allglen; gi++) { | 2829 for(gi = 0; gi < runtime·allglen; gi++) { |
2825 gp = runtime·allg[gi]; | 2830 gp = runtime·allg[gi]; |
2826 mp = gp->m; | 2831 mp = gp->m; |
2827 lockedm = gp->lockedm; | 2832 lockedm = gp->lockedm; |
2828 » » runtime·printf(" G%D: status=%d(%s) m=%d lockedm=%d\n", | 2833 » » runtime·printf(" G%D: status=%d(%S) m=%d lockedm=%d\n", |
2829 gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1, | 2834 gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1, |
2830 lockedm ? lockedm->id : -1); | 2835 lockedm ? lockedm->id : -1); |
2831 } | 2836 } |
2832 runtime·unlock(&allglock); | 2837 runtime·unlock(&allglock); |
2833 runtime·unlock(&runtime·sched.lock); | 2838 runtime·unlock(&runtime·sched.lock); |
2834 } | 2839 } |
2835 | 2840 |
2836 // Put mp on midle list. | 2841 // Put mp on midle list. |
2837 // Sched must be locked. | 2842 // Sched must be locked. |
2838 static void | 2843 static void |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3172 if(experiment[i+j] != name[j]) | 3177 if(experiment[i+j] != name[j]) |
3173 goto nomatch; | 3178 goto nomatch; |
3174 if(experiment[i+j] != '\0' && experiment[i+j] != ',') | 3179 if(experiment[i+j] != '\0' && experiment[i+j] != ',') |
3175 goto nomatch; | 3180 goto nomatch; |
3176 return 1; | 3181 return 1; |
3177 } | 3182 } |
3178 nomatch:; | 3183 nomatch:; |
3179 } | 3184 } |
3180 return 0; | 3185 return 0; |
3181 } | 3186 } |
LEFT | RIGHT |