Left: | ||
Right: |
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 "defs_GOOS_GOARCH.h" | 7 #include "defs_GOOS_GOARCH.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 #include "os_GOOS.h" | 9 #include "os_GOOS.h" |
10 #include "stack.h" | 10 #include "stack.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 v = runtime·sched.atomic; | 158 v = runtime·sched.atomic; |
159 w = v; | 159 w = v; |
160 w &= ~(mcpuMask<<mcpumaxShift); | 160 w &= ~(mcpuMask<<mcpumaxShift); |
161 w |= n<<mcpumaxShift; | 161 w |= n<<mcpumaxShift; |
162 if(runtime·cas(&runtime·sched.atomic, v, w)) | 162 if(runtime·cas(&runtime·sched.atomic, v, w)) |
163 break; | 163 break; |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 // Keep trace of scavenger's goroutine for deadlock detection. | 167 // Keep trace of scavenger's goroutine for deadlock detection. |
168 G *scvg; | 168 static G *scvg; |
dvyukov
2011/12/22 12:50:37
static
| |
169 | 169 |
170 // The bootstrap sequence is: | 170 // The bootstrap sequence is: |
171 // | 171 // |
172 // call osinit | 172 // call osinit |
173 // call schedinit | 173 // call schedinit |
174 // make & queue new G | 174 // make & queue new G |
175 // call runtime·mstart | 175 // call runtime·mstart |
176 // | 176 // |
177 // The new G calls runtime·main. | 177 // The new G calls runtime·main. |
178 void | 178 void |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 mcommoninit(M *m) | 330 mcommoninit(M *m) |
331 { | 331 { |
332 // Add to runtime·allm so garbage collector doesn't free m | 332 // Add to runtime·allm so garbage collector doesn't free m |
333 // when it is just in a register or thread-local storage. | 333 // when it is just in a register or thread-local storage. |
334 m->alllink = runtime·allm; | 334 m->alllink = runtime·allm; |
335 // runtime·Cgocalls() iterates over allm w/o schedlock, | 335 // runtime·Cgocalls() iterates over allm w/o schedlock, |
336 // so we need to publish it safely. | 336 // so we need to publish it safely. |
337 runtime·atomicstorep(&runtime·allm, m); | 337 runtime·atomicstorep(&runtime·allm, m); |
338 | 338 |
339 m->id = runtime·sched.mcount++; | 339 m->id = runtime·sched.mcount++; |
340 » m->fastrand = 0x49f6428aUL + m->id; | 340 » m->fastrand = 0x49f6428aUL + m->id + runtime·cputicks(); |
341 m->stackalloc = runtime·malloc(sizeof(*m->stackalloc)); | 341 m->stackalloc = runtime·malloc(sizeof(*m->stackalloc)); |
342 runtime·FixAlloc_Init(m->stackalloc, FixedStack, runtime·SysAlloc, nil, nil); | 342 runtime·FixAlloc_Init(m->stackalloc, FixedStack, runtime·SysAlloc, nil, nil); |
343 | 343 |
344 if(m->mcache == nil) | 344 if(m->mcache == nil) |
345 m->mcache = runtime·allocmcache(); | 345 m->mcache = runtime·allocmcache(); |
346 } | 346 } |
347 | 347 |
348 // Try to increment mcpu. Report whether succeeded. | 348 // Try to increment mcpu. Report whether succeeded. |
349 static bool | 349 static bool |
350 canaddmcpu(void) | 350 canaddmcpu(void) |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 return gp; | 553 return gp; |
554 } | 554 } |
555 } | 555 } |
556 } else { | 556 } else { |
557 // Look for work on global queue. | 557 // Look for work on global queue. |
558 while(haveg() && canaddmcpu()) { | 558 while(haveg() && canaddmcpu()) { |
559 gp = gget(); | 559 gp = gget(); |
560 if(gp == nil) | 560 if(gp == nil) |
561 runtime·throw("gget inconsistency"); | 561 runtime·throw("gget inconsistency"); |
562 | 562 |
563 if (gp->goid == scvg->goid && runtime·sched.gwait == 0 & & runtime·sched.grunning == 0) | |
dvyukov
2011/12/22 12:55:39
Does it detect deadlocks in trivial cases?
I need
| |
564 runtime·throw("all goroutines are asleep - deadl ock!"); | |
565 | |
566 if(gp->lockedm) { | 563 if(gp->lockedm) { |
567 mnextg(gp->lockedm, gp); | 564 mnextg(gp->lockedm, gp); |
568 continue; | 565 continue; |
569 } | 566 } |
570 runtime·sched.grunning++; | 567 runtime·sched.grunning++; |
571 schedunlock(); | 568 schedunlock(); |
572 return gp; | 569 return gp; |
573 } | 570 } |
574 | 571 |
575 // The while loop ended either because the g queue is empty | 572 // The while loop ended either because the g queue is empty |
576 // or because we have maxed out our m procs running go | 573 // or because we have maxed out our m procs running go |
577 // code (mcpu >= mcpumax). We need to check that | 574 // code (mcpu >= mcpumax). We need to check that |
578 // concurrent actions by entersyscall/exitsyscall cannot | 575 // concurrent actions by entersyscall/exitsyscall cannot |
579 // invalidate the decision to end the loop. | 576 // invalidate the decision to end the loop. |
580 // | 577 // |
581 // We hold the sched lock, so no one else is manipulating the | 578 // We hold the sched lock, so no one else is manipulating the |
582 // g queue or changing mcpumax. Entersyscall can decrement | 579 // g queue or changing mcpumax. Entersyscall can decrement |
583 // mcpu, but if does so when there is something on the g queue, | 580 // mcpu, but if does so when there is something on the g queue, |
584 // the gwait bit will be set, so entersyscall will take the slow path | 581 // the gwait bit will be set, so entersyscall will take the slow path |
585 // and use the sched lock. So it cannot invalidate our decision . | 582 // and use the sched lock. So it cannot invalidate our decision . |
586 // | 583 // |
587 // Wait on global m queue. | 584 // Wait on global m queue. |
588 mput(m); | 585 mput(m); |
589 } | 586 } |
590 | 587 |
591 » v = runtime·atomicload(&runtime·sched.atomic); | 588 » // Look for deadlock situation: one single active g which happens to be scvg. |
589 » if(runtime·sched.grunning == 1 && runtime·sched.gwait == 0) { | |
590 » » if(scvg->status == Grunning || scvg->status == Gsyscall) | |
591 » » » runtime·throw("all goroutines are asleep - deadlock!"); | |
592 » } | |
593 | |
592 m->nextg = nil; | 594 m->nextg = nil; |
593 m->waitnextg = 1; | 595 m->waitnextg = 1; |
594 runtime·noteclear(&m->havenextg); | 596 runtime·noteclear(&m->havenextg); |
595 | 597 |
596 // Stoptheworld is waiting for all but its cpu to go to stop. | 598 // Stoptheworld is waiting for all but its cpu to go to stop. |
597 // Entersyscall might have decremented mcpu too, but if so | 599 // Entersyscall might have decremented mcpu too, but if so |
598 // it will see the waitstop and take the slow path. | 600 // it will see the waitstop and take the slow path. |
599 // Exitsyscall never increments mcpu beyond mcpumax. | 601 // Exitsyscall never increments mcpu beyond mcpumax. |
602 v = runtime·atomicload(&runtime·sched.atomic); | |
600 if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { | 603 if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { |
601 // set waitstop = 0 (known to be 1) | 604 // set waitstop = 0 (known to be 1) |
602 runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift); | 605 runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift); |
603 runtime·notewakeup(&runtime·sched.stopped); | 606 runtime·notewakeup(&runtime·sched.stopped); |
604 } | 607 } |
605 schedunlock(); | 608 schedunlock(); |
606 | 609 |
607 runtime·notesleep(&m->havenextg); | 610 runtime·notesleep(&m->havenextg); |
608 if(m->helpgc) { | 611 if(m->helpgc) { |
609 runtime·gchelper(); | 612 runtime·gchelper(); |
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1743 arg[0][k.len] = 0; | 1746 arg[0][k.len] = 0; |
1744 | 1747 |
1745 arg[1] = runtime·malloc(v.len + 1); | 1748 arg[1] = runtime·malloc(v.len + 1); |
1746 runtime·memmove(arg[1], v.str, v.len); | 1749 runtime·memmove(arg[1], v.str, v.len); |
1747 arg[1][v.len] = 0; | 1750 arg[1][v.len] = 0; |
1748 | 1751 |
1749 runtime·asmcgocall((void*)libcgo_setenv, arg); | 1752 runtime·asmcgocall((void*)libcgo_setenv, arg); |
1750 runtime·free(arg[0]); | 1753 runtime·free(arg[0]); |
1751 runtime·free(arg[1]); | 1754 runtime·free(arg[1]); |
1752 } | 1755 } |
LEFT | RIGHT |