Left: | ||
Right: |
OLD | NEW |
---|---|
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.h" | 6 #include "arch.h" |
7 #include "defs.h" | 7 #include "defs.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 #include "os.h" | 9 #include "os.h" |
10 #include "stack.h" | 10 #include "stack.h" |
11 | 11 |
12 bool runtime·iscgo; | 12 bool runtime·iscgo; |
13 | 13 |
14 static void unwindstack(G*, byte*); | 14 static void unwindstack(G*, byte*); |
15 static void schedule(G*); | 15 static void schedule(G*); |
16 static void acquireproc(void); | 16 static void acquireproc(void); |
17 static void releaseproc(void); | 17 static void releaseproc(void); |
18 static M *startm(void); | |
19 | 18 |
20 typedef struct Sched Sched; | 19 typedef struct Sched Sched; |
21 | 20 |
22 M runtime·m0; | 21 M runtime·m0; |
23 G runtime·g0; // idle goroutine for m0 | 22 G runtime·g0; // idle goroutine for m0 |
24 | 23 |
25 static int32 debug = 0; | 24 static int32 debug = 0; |
26 | 25 |
27 int32 runtime·gcwaiting; | 26 int32 runtime·gcwaiting; |
28 | 27 |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
577 // g queue or changing mcpumax. Entersyscall can decrement | 576 // g queue or changing mcpumax. Entersyscall can decrement |
578 // mcpu, but if does so when there is something on the g queue, | 577 // mcpu, but if does so when there is something on the g queue, |
579 // the gwait bit will be set, so entersyscall will take the slow path | 578 // the gwait bit will be set, so entersyscall will take the slow path |
580 // and use the sched lock. So it cannot invalidate our decision . | 579 // and use the sched lock. So it cannot invalidate our decision . |
581 // | 580 // |
582 // Wait on global m queue. | 581 // Wait on global m queue. |
583 mput(m); | 582 mput(m); |
584 } | 583 } |
585 | 584 |
586 v = runtime·atomicload(&runtime·sched.atomic); | 585 v = runtime·atomicload(&runtime·sched.atomic); |
587 » if(runtime·sched.grunning == 0) | 586 » if(runtime·sched.grunning == 0 && !runtime·havetimers()) |
dvyukov
2011/11/07 10:54:15
Need to re-check the condition in time.goc when ha
| |
588 runtime·throw("all goroutines are asleep - deadlock!"); | 587 runtime·throw("all goroutines are asleep - deadlock!"); |
589 m->nextg = nil; | 588 m->nextg = nil; |
590 m->waitnextg = 1; | 589 m->waitnextg = 1; |
591 runtime·noteclear(&m->havenextg); | 590 runtime·noteclear(&m->havenextg); |
592 | 591 |
593 // Stoptheworld is waiting for all but its cpu to go to stop. | 592 // Stoptheworld is waiting for all but its cpu to go to stop. |
594 // Entersyscall might have decremented mcpu too, but if so | 593 // Entersyscall might have decremented mcpu too, but if so |
595 // it will see the waitstop and take the slow path. | 594 // it will see the waitstop and take the slow path. |
596 // Exitsyscall never increments mcpu beyond mcpumax. | 595 // Exitsyscall never increments mcpu beyond mcpumax. |
597 if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { | 596 if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
694 if(extra && canaddmcpu()) { | 693 if(extra && canaddmcpu()) { |
695 // Start a new m that will (we hope) be idle | 694 // Start a new m that will (we hope) be idle |
696 // and so available to help when the next | 695 // and so available to help when the next |
697 // garbage collection happens. | 696 // garbage collection happens. |
698 // canaddmcpu above did mcpu++ | 697 // canaddmcpu above did mcpu++ |
699 // (necessary, because m will be doing various | 698 // (necessary, because m will be doing various |
700 // initialization work so is definitely running), | 699 // initialization work so is definitely running), |
701 // but m is not running a specific goroutine, | 700 // but m is not running a specific goroutine, |
702 // so set the helpgc flag as a signal to m's | 701 // so set the helpgc flag as a signal to m's |
703 // first schedule(nil) to mcpu-- and grunning--. | 702 // first schedule(nil) to mcpu-- and grunning--. |
704 » » m = startm(); | 703 » » m = runtime·newm(nil); |
705 m->helpgc = 1; | 704 m->helpgc = 1; |
706 runtime·sched.grunning++; | 705 runtime·sched.grunning++; |
707 } | 706 } |
708 schedunlock(); | 707 schedunlock(); |
709 } | 708 } |
710 | 709 |
711 // Called to start an M. | 710 // Called to start an M. |
712 void | 711 void |
713 runtime·mstart(void) | 712 runtime·mstart(void) |
714 { | 713 { |
715 if(g != m->g0) | 714 if(g != m->g0) |
716 runtime·throw("bad runtime·mstart"); | 715 runtime·throw("bad runtime·mstart"); |
717 | 716 |
718 // Record top of stack for use by mcall. | 717 // Record top of stack for use by mcall. |
719 // Once we call schedule we're never coming back, | 718 // Once we call schedule we're never coming back, |
720 // so other calls can reuse this stack space. | 719 // so other calls can reuse this stack space. |
721 runtime·gosave(&m->g0->sched); | 720 runtime·gosave(&m->g0->sched); |
722 m->g0->sched.pc = (void*)-1; // make sure it is never used | 721 m->g0->sched.pc = (void*)-1; // make sure it is never used |
723 | 722 |
724 runtime·minit(); | 723 runtime·minit(); |
724 if(m->procfn) | |
725 m->procfn(); | |
dvyukov
2011/11/07 10:35:02
I think as of now it will throw if fall through to
| |
725 schedule(nil); | 726 schedule(nil); |
726 } | 727 } |
727 | 728 |
728 // When running with cgo, we call libcgo_thread_start | 729 // When running with cgo, we call libcgo_thread_start |
729 // to start threads for us so that we can play nicely with | 730 // to start threads for us so that we can play nicely with |
730 // foreign code. | 731 // foreign code. |
731 void (*libcgo_thread_start)(void*); | 732 void (*libcgo_thread_start)(void*); |
732 | 733 |
733 typedef struct CgoThreadStart CgoThreadStart; | 734 typedef struct CgoThreadStart CgoThreadStart; |
734 struct CgoThreadStart | 735 struct CgoThreadStart |
(...skipping 16 matching lines...) Expand all Loading... | |
751 if(m->mallocing || m->gcing) | 752 if(m->mallocing || m->gcing) |
752 return; | 753 return; |
753 | 754 |
754 while(haveg() && canaddmcpu()) { | 755 while(haveg() && canaddmcpu()) { |
755 gp = gget(); | 756 gp = gget(); |
756 if(gp == nil) | 757 if(gp == nil) |
757 runtime·throw("gget inconsistency"); | 758 runtime·throw("gget inconsistency"); |
758 | 759 |
759 // Find the m that will run gp. | 760 // Find the m that will run gp. |
760 if((mp = mget(gp)) == nil) | 761 if((mp = mget(gp)) == nil) |
761 » » » mp = startm(); | 762 » » » mp = runtime·newm(nil); |
762 mnextg(mp, gp); | 763 mnextg(mp, gp); |
763 } | 764 } |
764 } | 765 } |
765 | 766 |
766 static M* | 767 M* |
767 startm(void) | 768 runtime·newm(void (*procfn)(void)) |
768 { | 769 { |
769 M *m; | 770 M *m; |
770 | 771 |
771 m = runtime·malloc(sizeof(M)); | 772 m = runtime·malloc(sizeof(M)); |
772 mcommoninit(m); | 773 mcommoninit(m); |
774 m->procfn = procfn; | |
dvyukov
2011/11/07 10:35:02
It is quite fragile. See newm comment in time.goc.
| |
773 | 775 |
774 if(runtime·iscgo) { | 776 if(runtime·iscgo) { |
775 CgoThreadStart ts; | 777 CgoThreadStart ts; |
776 | 778 |
777 if(libcgo_thread_start == nil) | 779 if(libcgo_thread_start == nil) |
778 runtime·throw("libcgo_thread_start missing"); | 780 runtime·throw("libcgo_thread_start missing"); |
779 // pthread_create will make us a stack. | 781 // pthread_create will make us a stack. |
780 m->g0 = runtime·malg(-1); | 782 m->g0 = runtime·malg(-1); |
781 ts.m = m; | 783 ts.m = m; |
782 ts.g = m->g0; | 784 ts.g = m->g0; |
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1688 arg[0][k.len] = 0; | 1690 arg[0][k.len] = 0; |
1689 | 1691 |
1690 arg[1] = runtime·malloc(v.len + 1); | 1692 arg[1] = runtime·malloc(v.len + 1); |
1691 runtime·memmove(arg[1], v.str, v.len); | 1693 runtime·memmove(arg[1], v.str, v.len); |
1692 arg[1][v.len] = 0; | 1694 arg[1][v.len] = 0; |
1693 | 1695 |
1694 runtime·asmcgocall((void*)libcgo_setenv, arg); | 1696 runtime·asmcgocall((void*)libcgo_setenv, arg); |
1695 runtime·free(arg[0]); | 1697 runtime·free(arg[0]); |
1696 runtime·free(arg[1]); | 1698 runtime·free(arg[1]); |
1697 } | 1699 } |
OLD | NEW |