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.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" |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 m->helpgc = 0; | 594 m->helpgc = 0; |
595 runtime·lock(&runtime·sched); | 595 runtime·lock(&runtime·sched); |
596 goto top; | 596 goto top; |
597 } | 597 } |
598 if((gp = m->nextg) == nil) | 598 if((gp = m->nextg) == nil) |
599 runtime·throw("bad m->nextg in nextgoroutine"); | 599 runtime·throw("bad m->nextg in nextgoroutine"); |
600 m->nextg = nil; | 600 m->nextg = nil; |
601 return gp; | 601 return gp; |
602 } | 602 } |
603 | 603 |
604 static int32 | 604 int32 |
605 maxgcprocs(void) | 605 runtime·helpgc(bool *extra) |
606 { | 606 { |
607 » int32 max; | 607 » M *mp; |
| 608 » int32 n, max; |
608 | 609 |
609 // Figure out how many CPUs to use. | 610 // Figure out how many CPUs to use. |
610 // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc. | 611 // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc. |
611 max = runtime·gomaxprocs; | 612 max = runtime·gomaxprocs; |
612 if(max > runtime·ncpu) | 613 if(max > runtime·ncpu) |
613 max = runtime·ncpu; | 614 max = runtime·ncpu; |
614 if(max > MaxGcproc) | 615 if(max > MaxGcproc) |
615 max = MaxGcproc; | 616 max = MaxGcproc; |
616 return max; | |
617 } | |
618 | |
619 int32 | |
620 runtime·helpgc(void) | |
621 { | |
622 M *mp; | |
623 int32 n, max; | |
624 | |
625 max = maxgcprocs(); | |
626 | 617 |
627 // We're going to use one CPU no matter what. | 618 // We're going to use one CPU no matter what. |
628 // Figure out the max number of additional CPUs. | 619 // Figure out the max number of additional CPUs. |
629 max--; | 620 max--; |
630 | 621 |
631 runtime·lock(&runtime·sched); | 622 runtime·lock(&runtime·sched); |
632 n = 0; | 623 n = 0; |
633 while(n < max && (mp = mget(nil)) != nil) { | 624 while(n < max && (mp = mget(nil)) != nil) { |
634 n++; | 625 n++; |
635 mp->helpgc = 1; | 626 mp->helpgc = 1; |
636 mp->waitnextg = 0; | 627 mp->waitnextg = 0; |
637 runtime·notewakeup(&mp->havenextg); | 628 runtime·notewakeup(&mp->havenextg); |
638 } | 629 } |
639 runtime·unlock(&runtime·sched); | 630 runtime·unlock(&runtime·sched); |
| 631 if(extra) |
| 632 *extra = n != max; |
640 return n; | 633 return n; |
641 } | 634 } |
642 | 635 |
643 void | 636 void |
644 runtime·stoptheworld(void) | 637 runtime·stoptheworld(void) |
645 { | 638 { |
646 uint32 v; | 639 uint32 v; |
647 | 640 |
648 schedlock(); | 641 schedlock(); |
649 runtime·gcwaiting = 1; | 642 runtime·gcwaiting = 1; |
(...skipping 20 matching lines...) Expand all Loading... |
670 | 663 |
671 schedunlock(); | 664 schedunlock(); |
672 runtime·notesleep(&runtime·sched.stopped); | 665 runtime·notesleep(&runtime·sched.stopped); |
673 schedlock(); | 666 schedlock(); |
674 } | 667 } |
675 runtime·singleproc = runtime·gomaxprocs == 1; | 668 runtime·singleproc = runtime·gomaxprocs == 1; |
676 schedunlock(); | 669 schedunlock(); |
677 } | 670 } |
678 | 671 |
679 void | 672 void |
680 runtime·starttheworld(void) | 673 runtime·starttheworld(bool extra) |
681 { | 674 { |
682 M *m; | 675 M *m; |
683 | 676 |
684 schedlock(); | 677 schedlock(); |
685 runtime·gcwaiting = 0; | 678 runtime·gcwaiting = 0; |
686 setmcpumax(runtime·gomaxprocs); | 679 setmcpumax(runtime·gomaxprocs); |
687 matchmg(); | 680 matchmg(); |
688 » // If GC could have used another helper proc, start one now, | 681 » if(extra && canaddmcpu()) { |
689 » // in the hope that it will be available next time. | |
690 » // It would have been even better to start it before the collection, | |
691 » // but doing so requires allocating memory, so it's tricky to | |
692 » // coordinate. This lazy approach works out in practice: | |
693 » // we don't mind if the first couple gc rounds don't have quite | |
694 » // the maximum number of procs. | |
695 » if(runtime·sched.mcount < maxgcprocs() && canaddmcpu()) { | |
696 // Start a new m that will (we hope) be idle | 682 // Start a new m that will (we hope) be idle |
697 // and so available to help when the next | 683 // and so available to help when the next |
698 // garbage collection happens. | 684 // garbage collection happens. |
699 // canaddmcpu above did mcpu++ | 685 // canaddmcpu above did mcpu++ |
700 // (necessary, because m will be doing various | 686 // (necessary, because m will be doing various |
701 // initialization work so is definitely running), | 687 // initialization work so is definitely running), |
702 // but m is not running a specific goroutine, | 688 // but m is not running a specific goroutine, |
703 // so set the helpgc flag as a signal to m's | 689 // so set the helpgc flag as a signal to m's |
704 // first schedule(nil) to mcpu-- and grunning--. | 690 // first schedule(nil) to mcpu-- and grunning--. |
705 m = startm(); | 691 m = startm(); |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1687 arg[0][k.len] = 0; | 1673 arg[0][k.len] = 0; |
1688 | 1674 |
1689 arg[1] = runtime·malloc(v.len + 1); | 1675 arg[1] = runtime·malloc(v.len + 1); |
1690 runtime·memmove(arg[1], v.str, v.len); | 1676 runtime·memmove(arg[1], v.str, v.len); |
1691 arg[1][v.len] = 0; | 1677 arg[1][v.len] = 0; |
1692 | 1678 |
1693 runtime·asmcgocall((void*)libcgo_setenv, arg); | 1679 runtime·asmcgocall((void*)libcgo_setenv, arg); |
1694 runtime·free(arg[0]); | 1680 runtime·free(arg[0]); |
1695 runtime·free(arg[1]); | 1681 runtime·free(arg[1]); |
1696 } | 1682 } |
LEFT | RIGHT |