Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(9)

Delta Between Two Patch Sets: src/pkg/runtime/stack.c

Issue 131580043: code review 131580043: runtime: Start and stop individual goroutines at gc saf... (Closed)
Left Patch Set: diff -r d999ebefa648465ac8e09a23763c0dda08b2a277 https://code.google.com/p/go/ Created 10 years, 6 months ago
Right Patch Set: diff -r 64d62375e7388afb5f049442321c026186d7679b https://code.google.com/p/go/ Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/runtime.h ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 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 "malloc.h" 7 #include "malloc.h"
8 #include "stack.h" 8 #include "stack.h"
9 #include "funcdata.h" 9 #include "funcdata.h"
10 #include "typekind.h" 10 #include "typekind.h"
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // Doing so would cause a deadlock (issue 1547). 199 // Doing so would cause a deadlock (issue 1547).
200 if(g != g->m->g0) 200 if(g != g->m->g0)
201 runtime·throw("stackalloc not on scheduler stack"); 201 runtime·throw("stackalloc not on scheduler stack");
202 if((n & (n-1)) != 0) 202 if((n & (n-1)) != 0)
203 runtime·throw("stack size not a power of 2"); 203 runtime·throw("stack size not a power of 2");
204 if(StackDebug >= 1) 204 if(StackDebug >= 1)
205 runtime·printf("stackalloc %d\n", n); 205 runtime·printf("stackalloc %d\n", n);
206 206
207 gp->stacksize += n; 207 gp->stacksize += n;
208 if(runtime·debug.efence || StackFromSystem) { 208 if(runtime·debug.efence || StackFromSystem) {
209 » » v = runtime·SysAlloc(ROUND(n, PageSize), &mstats.stacks_sys); 209 » » v = runtime·sysAlloc(ROUND(n, PageSize), &mstats.stacks_sys);
210 if(v == nil) 210 if(v == nil)
211 runtime·throw("out of memory (stackalloc)"); 211 runtime·throw("out of memory (stackalloc)");
212 return v; 212 return v;
213 } 213 }
214 214
215 // Small stacks are allocated with a fixed-size free-list allocator. 215 // Small stacks are allocated with a fixed-size free-list allocator.
216 // If we need a stack of a bigger size, we fall back on allocating 216 // If we need a stack of a bigger size, we fall back on allocating
217 // a dedicated span. 217 // a dedicated span.
218 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) { 218 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
219 order = 0; 219 order = 0;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 { 412 {
413 CopyableInfo *cinfo; 413 CopyableInfo *cinfo;
414 Func *f; 414 Func *f;
415 StackMap *stackmap; 415 StackMap *stackmap;
416 416
417 cinfo = arg; 417 cinfo = arg;
418 f = frame->fn; 418 f = frame->fn;
419 if(StackDebug >= 2) 419 if(StackDebug >= 2)
420 runtime·printf(" checking %s frame=[%p,%p] stk=[%p,%p]\n", ru ntime·funcname(f), frame->sp, frame->fp, cinfo->stk, cinfo->base); 420 runtime·printf(" checking %s frame=[%p,%p] stk=[%p,%p]\n", ru ntime·funcname(f), frame->sp, frame->fp, cinfo->stk, cinfo->base);
421 // if we're not in the segment any more, return immediately. 421 // if we're not in the segment any more, return immediately.
422 » if(frame->varp < cinfo->stk || frame->varp >= cinfo->base) { 422 » if((byte*)frame->varp < cinfo->stk || (byte*)frame->varp >= cinfo->base) {
423 if(StackDebug >= 2) 423 if(StackDebug >= 2)
424 runtime·printf(" <next segment>\n"); 424 runtime·printf(" <next segment>\n");
425 return false; // stop traceback 425 return false; // stop traceback
426 } 426 }
427 if(f->entry == (uintptr)runtime·main) { 427 if(f->entry == (uintptr)runtime·main) {
428 // A special routine at the TOS of the main routine. 428 // A special routine at the TOS of the main routine.
429 // We will allow it to be copied even though we don't 429 // We will allow it to be copied even though we don't
430 // have full GC info for it (because it is written in C). 430 // have full GC info for it (because it is written in C).
431 cinfo->frames++; 431 cinfo->frames++;
432 return false; // stop traceback 432 return false; // stop traceback
433 } 433 }
434 if(f->entry == (uintptr)runtime·switchtoM) { 434 if(f->entry == (uintptr)runtime·switchtoM) {
435 // A special routine at the bottom of stack of a goroutine that does onM call. 435 // A special routine at the bottom of stack of a goroutine that does onM call.
436 // We will allow it to be copied even though we don't 436 // We will allow it to be copied even though we don't
437 // have full GC info for it (because it is written in asm). 437 // have full GC info for it (because it is written in asm).
438 cinfo->frames++; 438 cinfo->frames++;
439 return true; 439 return true;
440 } 440 }
441 » if(frame->varp != (byte*)frame->sp) { // not in prologue (and has at lea st one local or outarg) 441 » if((byte*)frame->varp != (byte*)frame->sp) { // not in prologue (and has at least one local or outarg)
442 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); 442 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
443 if(stackmap == nil) { 443 if(stackmap == nil) {
444 cinfo->frames = -1; 444 cinfo->frames = -1;
445 if(StackDebug >= 1) 445 if(StackDebug >= 1)
446 runtime·printf("copystack: no locals info for %s \n", runtime·funcname(f)); 446 runtime·printf("copystack: no locals info for %s \n", runtime·funcname(f));
447 return false; 447 return false;
448 } 448 }
449 if(stackmap->n <= 0) { 449 if(stackmap->n <= 0) {
450 cinfo->frames = -1; 450 cinfo->frames = -1;
451 if(StackDebug >= 1) 451 if(StackDebug >= 1)
(...skipping 18 matching lines...) Expand all
470 // frame, return -1. Otherwise return the number of frames 470 // frame, return -1. Otherwise return the number of frames
471 // in the top segment, all of which are copyable. 471 // in the top segment, all of which are copyable.
472 static int32 472 static int32
473 copyabletopsegment(G *gp) 473 copyabletopsegment(G *gp)
474 { 474 {
475 CopyableInfo cinfo; 475 CopyableInfo cinfo;
476 Defer *d; 476 Defer *d;
477 Func *f; 477 Func *f;
478 FuncVal *fn; 478 FuncVal *fn;
479 StackMap *stackmap; 479 StackMap *stackmap;
480 bool (*cb)(Stkframe*, void*);
480 481
481 if(gp->stackbase == 0) 482 if(gp->stackbase == 0)
482 runtime·throw("stackbase == 0"); 483 runtime·throw("stackbase == 0");
483 cinfo.stk = (byte*)gp->stackguard - StackGuard; 484 cinfo.stk = (byte*)gp->stackguard - StackGuard;
484 cinfo.base = (byte*)gp->stackbase + sizeof(Stktop); 485 cinfo.base = (byte*)gp->stackbase + sizeof(Stktop);
485 cinfo.frames = 0; 486 cinfo.frames = 0;
486 487
487 // Check that each frame is copyable. As a side effect, 488 // Check that each frame is copyable. As a side effect,
488 // count the frames. 489 // count the frames.
489 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff , checkframecopy, &cinfo, false); 490 » cb = checkframecopy;
491 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff , &cb, &cinfo, false);
490 if(StackDebug >= 1 && cinfo.frames != -1) 492 if(StackDebug >= 1 && cinfo.frames != -1)
491 runtime·printf("copystack: %d copyable frames\n", cinfo.frames); 493 runtime·printf("copystack: %d copyable frames\n", cinfo.frames);
492 494
493 if(cinfo.frames == -1) 495 if(cinfo.frames == -1)
494 return -1; 496 return -1;
495 497
496 // Check to make sure all Defers are copyable 498 // Check to make sure all Defers are copyable
497 for(d = gp->defer; d != nil; d = d->link) { 499 for(d = gp->defer; d != nil; d = d->link) {
498 if(cinfo.stk <= (byte*)d && (byte*)d < cinfo.base) { 500 if(cinfo.stk <= (byte*)d && (byte*)d < cinfo.base) {
499 // Defer is on the stack. Its copyableness has 501 // Defer is on the stack. Its copyableness has
500 // been established during stack walking. 502 // been established during stack walking.
501 // For now, this only happens with the Defer in runtime. main. 503 // For now, this only happens with the Defer in runtime. main.
502 continue; 504 continue;
503 } 505 }
504 » » if(d->argp < cinfo.stk || cinfo.base <= d->argp) 506 » » if((byte*)d->argp < cinfo.stk || cinfo.base <= (byte*)d->argp)
505 break; // a defer for the next segment 507 break; // a defer for the next segment
506 fn = d->fn; 508 fn = d->fn;
507 if(fn == nil) // See issue 8047 509 if(fn == nil) // See issue 8047
508 continue; 510 continue;
509 f = runtime·findfunc((uintptr)fn->fn); 511 f = runtime·findfunc((uintptr)fn->fn);
510 if(f == nil) { 512 if(f == nil) {
511 if(StackDebug >= 1) 513 if(StackDebug >= 1)
512 runtime·printf("copystack: no func for deferred pc %p\n", fn->fn); 514 runtime·printf("copystack: no func for deferred pc %p\n", fn->fn);
513 return -1; 515 return -1;
514 } 516 }
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 // Frame is dead. 661 // Frame is dead.
660 return true; 662 return true;
661 } 663 }
662 if(targetpc != f->entry) 664 if(targetpc != f->entry)
663 targetpc--; 665 targetpc--;
664 pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc); 666 pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
665 if(pcdata == -1) 667 if(pcdata == -1)
666 pcdata = 0; // in prologue 668 pcdata = 0; // in prologue
667 669
668 // adjust local pointers 670 // adjust local pointers
669 » if(frame->varp != (byte*)frame->sp) { 671 » if((byte*)frame->varp != (byte*)frame->sp) {
670 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); 672 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
671 if(stackmap == nil) 673 if(stackmap == nil)
672 runtime·throw("no locals info"); 674 runtime·throw("no locals info");
673 if(stackmap->n <= 0) 675 if(stackmap->n <= 0)
674 runtime·throw("locals size info only"); 676 runtime·throw("locals size info only");
675 bv = runtime·stackmapdata(stackmap, pcdata); 677 bv = runtime·stackmapdata(stackmap, pcdata);
676 if(StackDebug >= 3) 678 if(StackDebug >= 3)
677 runtime·printf(" locals\n"); 679 runtime·printf(" locals\n");
678 adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f); 680 adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f);
679 } 681 }
680 // adjust inargs and outargs 682 // adjust inargs and outargs
681 if(frame->arglen != 0) { 683 if(frame->arglen != 0) {
682 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); 684 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
683 » » if(stackmap == nil) 685 » » if(stackmap == nil) {
686 » » » runtime·printf("size %d\n", (int32)frame->arglen);
684 runtime·throw("no arg info"); 687 runtime·throw("no arg info");
688 }
685 bv = runtime·stackmapdata(stackmap, pcdata); 689 bv = runtime·stackmapdata(stackmap, pcdata);
686 if(StackDebug >= 3) 690 if(StackDebug >= 3)
687 runtime·printf(" args\n"); 691 runtime·printf(" args\n");
688 adjustpointers((byte**)frame->argp, &bv, adjinfo, nil); 692 adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
689 } 693 }
690 return true; 694 return true;
691 } 695 }
692 696
693 static void 697 static void
694 adjustctxt(G *gp, AdjustInfo *adjinfo) 698 adjustctxt(G *gp, AdjustInfo *adjinfo)
(...skipping 13 matching lines...) Expand all
708 712
709 for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) { 713 for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) {
710 if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) { 714 if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) {
711 // The Defer record is on the stack. Its fields will 715 // The Defer record is on the stack. Its fields will
712 // get adjusted appropriately. 716 // get adjusted appropriately.
713 // This only happens for runtime.main now, but a compile r 717 // This only happens for runtime.main now, but a compile r
714 // optimization could do more of this. 718 // optimization could do more of this.
715 *dp = (Defer*)((byte*)d + adjinfo->delta); 719 *dp = (Defer*)((byte*)d + adjinfo->delta);
716 continue; 720 continue;
717 } 721 }
718 » » if(d->argp < adjinfo->oldstk || adjinfo->oldbase <= d->argp) 722 » » if((byte*)d->argp < adjinfo->oldstk || adjinfo->oldbase <= (byte *)d->argp)
719 break; // a defer for the next segment 723 break; // a defer for the next segment
720 fn = d->fn; 724 fn = d->fn;
721 if(fn == nil) { 725 if(fn == nil) {
722 // Defer of nil function. It will panic when run, and t here 726 // Defer of nil function. It will panic when run, and t here
723 // aren't any args to adjust. See issue 8047. 727 // aren't any args to adjust. See issue 8047.
724 d->argp += adjinfo->delta; 728 d->argp += adjinfo->delta;
725 continue; 729 continue;
726 } 730 }
727 f = runtime·findfunc((uintptr)fn->fn); 731 f = runtime·findfunc((uintptr)fn->fn);
728 if(f == nil) 732 if(f == nil)
(...skipping 24 matching lines...) Expand all
753 { 757 {
754 SudoG *s; 758 SudoG *s;
755 byte *e; 759 byte *e;
756 760
757 // the data elements pointed to by a SudoG structure 761 // the data elements pointed to by a SudoG structure
758 // might be in the stack. 762 // might be in the stack.
759 for(s = gp->waiting; s != nil; s = s->waitlink) { 763 for(s = gp->waiting; s != nil; s = s->waitlink) {
760 e = s->elem; 764 e = s->elem;
761 if(adjinfo->oldstk <= e && e < adjinfo->oldbase) 765 if(adjinfo->oldstk <= e && e < adjinfo->oldbase)
762 s->elem = e + adjinfo->delta; 766 s->elem = e + adjinfo->delta;
767 e = (byte*)s->selectdone;
768 if(adjinfo->oldstk <= e && e < adjinfo->oldbase)
769 s->selectdone = (uint32*)(e + adjinfo->delta);
763 } 770 }
764 } 771 }
765 772
766 // Copies the top stack segment of gp to a new stack segment of a 773 // Copies the top stack segment of gp to a new stack segment of a
767 // different size. The top segment must contain nframes frames. 774 // different size. The top segment must contain nframes frames.
768 static void 775 static void
769 copystack(G *gp, uintptr nframes, uintptr newsize) 776 copystack(G *gp, uintptr nframes, uintptr newsize)
770 { 777 {
771 byte *oldstk, *oldbase, *newstk, *newbase; 778 byte *oldstk, *oldbase, *newstk, *newbase;
772 uintptr oldsize, used; 779 uintptr oldsize, used;
773 AdjustInfo adjinfo; 780 AdjustInfo adjinfo;
774 Stktop *oldtop, *newtop; 781 Stktop *oldtop, *newtop;
775 uint32 oldstatus; 782 uint32 oldstatus;
783 bool (*cb)(Stkframe*, void*);
776 784
777 if(gp->syscallstack != 0) 785 if(gp->syscallstack != 0)
778 runtime·throw("can't handle stack copy in syscall yet"); 786 runtime·throw("can't handle stack copy in syscall yet");
779 oldstk = (byte*)gp->stackguard - StackGuard; 787 oldstk = (byte*)gp->stackguard - StackGuard;
780 if(gp->stackbase == 0) 788 if(gp->stackbase == 0)
781 runtime·throw("nil stackbase"); 789 runtime·throw("nil stackbase");
782 oldbase = (byte*)gp->stackbase + sizeof(Stktop); 790 oldbase = (byte*)gp->stackbase + sizeof(Stktop);
783 oldsize = oldbase - oldstk; 791 oldsize = oldbase - oldstk;
784 used = oldbase - (byte*)gp->sched.sp; 792 used = oldbase - (byte*)gp->sched.sp;
785 oldtop = (Stktop*)gp->stackbase; 793 oldtop = (Stktop*)gp->stackbase;
786 794
787 // allocate new stack 795 // allocate new stack
788 newstk = runtime·stackalloc(gp, newsize); 796 newstk = runtime·stackalloc(gp, newsize);
789 newbase = newstk + newsize; 797 newbase = newstk + newsize;
790 newtop = (Stktop*)(newbase - sizeof(Stktop)); 798 newtop = (Stktop*)(newbase - sizeof(Stktop));
791 799
792 if(StackDebug >= 1) 800 if(StackDebug >= 1)
793 runtime·printf("copystack gp=%p [%p %p]/%d -> [%p %p]/%d\n", gp, oldstk, oldbase, (int32)oldsize, newstk, newbase, (int32)newsize); 801 runtime·printf("copystack gp=%p [%p %p]/%d -> [%p %p]/%d\n", gp, oldstk, oldbase, (int32)oldsize, newstk, newbase, (int32)newsize);
794 USED(oldsize); 802 USED(oldsize);
795 ········ 803 ········
796 // adjust pointers in the to-be-copied frames 804 // adjust pointers in the to-be-copied frames
797 adjinfo.oldstk = oldstk; 805 adjinfo.oldstk = oldstk;
798 adjinfo.oldbase = oldbase; 806 adjinfo.oldbase = oldbase;
799 adjinfo.delta = newbase - oldbase; 807 adjinfo.delta = newbase - oldbase;
800 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, a djustframe, &adjinfo, false); 808 » cb = adjustframe;
809 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, & cb, &adjinfo, false);
801 ········ 810 ········
802 // adjust other miscellaneous things that have pointers into stacks. 811 // adjust other miscellaneous things that have pointers into stacks.
803 adjustctxt(gp, &adjinfo); 812 adjustctxt(gp, &adjinfo);
804 adjustdefers(gp, &adjinfo); 813 adjustdefers(gp, &adjinfo);
805 adjustsudogs(gp, &adjinfo); 814 adjustsudogs(gp, &adjinfo);
806 ········ 815 ········
807 // copy the stack (including Stktop) to the new location 816 // copy the stack (including Stktop) to the new location
808 runtime·memmove(newbase - used, oldbase - used, used); 817 runtime·memmove(newbase - used, oldbase - used, used);
809 oldstatus = runtime·readgstatus(gp); 818 oldstatus = runtime·readgstatus(gp);
810 oldstatus &= ~Gscan; 819 oldstatus &= ~Gscan;
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 if(gp->m != nil && gp->m->libcallsp != 0) 1115 if(gp->m != nil && gp->m->libcallsp != 0)
1107 return; 1116 return;
1108 #endif 1117 #endif
1109 if(StackDebug > 0) 1118 if(StackDebug > 0)
1110 runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uin t64)newsize); 1119 runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uin t64)newsize);
1111 nframes = copyabletopsegment(gp); 1120 nframes = copyabletopsegment(gp);
1112 if(nframes == -1) 1121 if(nframes == -1)
1113 return; 1122 return;
1114 copystack(gp, nframes, newsize); 1123 copystack(gp, nframes, newsize);
1115 } 1124 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b