aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/stack.h
AgeCommit message (Collapse)Author
2014-05-20runtime: switch default stack size back to 8kBRuss Cox
The move from 4kB to 8kB in Go 1.2 was to eliminate many stack split hot spots. The move back to 4kB was predicated on copying stacks eliminating the potential for hot spots. Unfortunately, the fact that stacks do not copy 100% of the time means that hot spots can still happen under the right conditions, and the slowdown is worse now than it was in Go 1.2. There is a real program in issue 8030 that sees about a 30x slowdown: it has a reflect call near the top of the stack which inhibits any stack copying on that segment. Go back to 8kB until stack copying can be used 100% of the time. Fixes #8030. LGTM=khr, dave, iant R=iant, khr, r, bradfitz, dave CC=golang-codereviews https://golang.org/cl/92540043
2014-03-07runtime: round stack size to power of 2.Shenghou Ma
Fixes build on windows/386 and plan9/386. Fixes #7487. LGTM=mattn.jp, dvyukov, rsc R=golang-codereviews, mattn.jp, dvyukov, 0intro, rsc CC=golang-codereviews https://golang.org/cl/72360043
2014-03-07runtime: fix windows/386 buildRuss Cox
From the trace it appears that stackalloc is being called with 0x1800 which is 6k = 4k + (StackSystem=2k). Make StackSystem 4k too, to make stackalloc happy. It's already 4k on windows/amd64. TBR=khr CC=golang-codereviews https://golang.org/cl/72600043
2014-03-07runtime: refactor and fix stack management codeDmitriy Vyukov
There are at least 3 bugs: 1. g->stacksize accounting is broken during copystack/shrinkstack 2. stktop->free is not properly maintained during copystack/shrinkstack 3. stktop->free logic is broken: we can have stktop->free==FixedStack, and we will free it into stack cache, but it actually comes from heap as the result of non-copying segment shrink This shows as at least spurious races on race builders (maybe something else as well I don't know). The idea behind the refactoring is to consolidate stacksize and segment origin logic in stackalloc/stackfree. Fixes #7490. LGTM=rsc, khr R=golang-codereviews, rsc, khr CC=golang-codereviews https://golang.org/cl/72440043
2014-02-26runtime: grow stack by copyingKeith Randall
On stack overflow, if all frames on the stack are copyable, we copy the frames to a new stack twice as large as the old one. During GC, if a G is using less than 1/4 of its stack, copy the stack to a stack half its size. TODO - Do something about C frames. When a C frame is in the stack segment, it isn't copyable. We allocate a new segment in this case. - For idempotent C code, we can abort it, copy the stack, then retry. I'm working on a separate CL for this. - For other C code, we can raise the stackguard to the lowest Go frame so the next call that Go frame makes triggers a copy, which will then succeed. - Pick a starting stack size? The plan is that eventually we reach a point where the stack contains only copyable frames. LGTM=rsc R=dvyukov, rsc CC=golang-codereviews https://golang.org/cl/54650044
2013-10-03runtime: change default stack segment size to 8 kBRuss Cox
Changing from 4 kB to 8 kB brings significant improvement on a variety of the Go 1 benchmarks, on both amd64 and 386 systems. Significant runtime reductions: amd64 386 GoParse -14% -1% GobDecode -12% -20% GobEncode -64% -1% JSONDecode -9% -4% JSONEncode -15% -5% Template -17% -14% In the longer term, khr's new stacks will avoid needing to make this decision at all, but for Go 1.2 this is a reasonable stopgap that makes performance significantly better. Demand paging should mean that if the second 4 kB is not used, it will not be brought into memory, so the change should not adversely affect resident set size. The same argument could justify bumping as high as 64 kB on 64-bit machines, but there are diminishing returns after 8 kB, and using 8 kB limits the possible unintended memory overheads we are not aware of. Benchmark graphs at http://swtch.com/~rsc/gostackamd64.html http://swtch.com/~rsc/gostack386.html Full data at http://swtch.com/~rsc/gostack.zip R=golang-dev, khr, dave, bradfitz, dvyukov CC=golang-dev https://golang.org/cl/14317043
2013-07-12cmd/ld: fix large stack split for preempt checkRuss Cox
If the stack frame size is larger than the known-unmapped region at the bottom of the address space, then the stack split prologue cannot use the usual condition: SP - size >= stackguard because SP - size may wrap around to a very large number. Instead, if the stack frame is large, the prologue tests: SP - stackguard >= size (This ends up being a few instructions more expensive, so we don't do it always.) Preemption requests register by setting stackguard to a very large value, so that the first test (SP - size >= stackguard) cannot possibly succeed. Unfortunately, that same very large value causes a wraparound in the second test (SP - stackguard >= size), making it succeed incorrectly. To avoid *that* wraparound, we have to amend the test: stackguard != StackPreempt && SP - stackguard >= size This test is only used for functions with large frames, which essentially always split the stack, so the cost of the few instructions is noise. This CL and CL 11085043 together fix the known issues with preemption, at the beginning of a function, so we will be able to try turning it on again. R=ken2 CC=golang-dev https://golang.org/cl/11205043
2013-06-28runtime: preempt goroutines for GCDmitriy Vyukov
The last patch for preemptive scheduler, with this change stoptheworld issues preemption requests every 100us. Update #543. R=golang-dev, daniel.morsing, rsc CC=golang-dev https://golang.org/cl/10264044
2013-06-27runtime: record proper goroutine state during stack splitRuss Cox
Until now, the goroutine state has been scattered during the execution of newstack and oldstack. It's all there, and those routines know how to get back to a working goroutine, but other pieces of the system, like stack traces, do not. If something does interrupt the newstack or oldstack execution, the rest of the system can't understand the goroutine. For example, if newstack decides there is an overflow and calls throw, the stack tracer wouldn't dump the goroutine correctly. For newstack to save a useful state snapshot, it needs to be able to rewind the PC in the function that triggered the split back to the beginning of the function. (The PC is a few instructions in, just after the call to morestack.) To make that possible, we change the prologues to insert a jmp back to the beginning of the function after the call to morestack. That is, the prologue used to be roughly: TEXT myfunc check for split jmpcond nosplit call morestack nosplit: sub $xxx, sp Now an extra instruction is inserted after the call: TEXT myfunc start: check for split jmpcond nosplit call morestack jmp start nosplit: sub $xxx, sp The jmp is not executed directly. It is decoded and simulated by runtime.rewindmorestack to discover the beginning of the function, and then the call to morestack returns directly to the start label instead of to the jump instruction. So logically the jmp is still executed, just not by the cpu. The prologue thus repeats in the case of a function that needs a stack split, but against the cost of the split itself, the extra few instructions are noise. The repeated prologue has the nice effect of making a stack split double-check that the new stack is big enough: if morestack happens to return on a too-small stack, we'll now notice before corruption happens. The ability for newstack to rewind to the beginning of the function should help preemption too. If newstack decides that it was called for preemption instead of a stack split, it now has the goroutine state correctly paused if rescheduling is needed, and when the goroutine can run again, it can return to the start label on its original stack and re-execute the split check. Here is an example of a split stack overflow showing the full trace, without any special cases in the stack printer. (This one was triggered by making the split check incorrect.) runtime: newstack framesize=0x0 argsize=0x18 sp=0x6aebd0 stack=[0x6b0000, 0x6b0fa0] morebuf={pc:0x69f5b sp:0x6aebd8 lr:0x0} sched={pc:0x68880 sp:0x6aebd0 lr:0x0 ctxt:0x34e700} runtime: split stack overflow: 0x6aebd0 < 0x6b0000 fatal error: runtime: split stack overflow goroutine 1 [stack split]: runtime.mallocgc(0x290, 0x100000000, 0x1) /Users/rsc/g/go/src/pkg/runtime/zmalloc_darwin_amd64.c:21 fp=0x6aebd8 runtime.new() /Users/rsc/g/go/src/pkg/runtime/zmalloc_darwin_amd64.c:682 +0x5b fp=0x6aec08 go/build.(*Context).Import(0x5ae340, 0xc210030c71, 0xa, 0xc2100b4380, 0x1b, ...) /Users/rsc/g/go/src/pkg/go/build/build.go:424 +0x3a fp=0x6b00a0 main.loadImport(0xc210030c71, 0xa, 0xc2100b4380, 0x1b, 0xc2100b42c0, ...) /Users/rsc/g/go/src/cmd/go/pkg.go:249 +0x371 fp=0x6b01a8 main.(*Package).load(0xc21017c800, 0xc2100b42c0, 0xc2101828c0, 0x0, 0x0, ...) /Users/rsc/g/go/src/cmd/go/pkg.go:431 +0x2801 fp=0x6b0c98 main.loadPackage(0x369040, 0x7, 0xc2100b42c0, 0x0) /Users/rsc/g/go/src/cmd/go/pkg.go:709 +0x857 fp=0x6b0f80 ----- stack segment boundary ----- main.(*builder).action(0xc2100902a0, 0x0, 0x0, 0xc2100e6c00, 0xc2100e5750, ...) /Users/rsc/g/go/src/cmd/go/build.go:539 +0x437 fp=0x6b14a0 main.(*builder).action(0xc2100902a0, 0x0, 0x0, 0xc21015b400, 0x2, ...) /Users/rsc/g/go/src/cmd/go/build.go:528 +0x1d2 fp=0x6b1658 main.(*builder).test(0xc2100902a0, 0xc210092000, 0x0, 0x0, 0xc21008ff60, ...) /Users/rsc/g/go/src/cmd/go/test.go:622 +0x1b53 fp=0x6b1f68 ----- stack segment boundary ----- main.runTest(0x5a6b20, 0xc21000a020, 0x2, 0x2) /Users/rsc/g/go/src/cmd/go/test.go:366 +0xd09 fp=0x6a5cf0 main.main() /Users/rsc/g/go/src/cmd/go/main.go:161 +0x4f9 fp=0x6a5f78 runtime.main() /Users/rsc/g/go/src/pkg/runtime/proc.c:183 +0x92 fp=0x6a5fa0 runtime.goexit() /Users/rsc/g/go/src/pkg/runtime/proc.c:1266 fp=0x6a5fa8 And here is a seg fault during oldstack: SIGSEGV: segmentation violation PC=0x1b2a6 runtime.oldstack() /Users/rsc/g/go/src/pkg/runtime/stack.c:159 +0x76 runtime.lessstack() /Users/rsc/g/go/src/pkg/runtime/asm_amd64.s:270 +0x22 goroutine 1 [stack unsplit]: fmt.(*pp).printArg(0x2102e64e0, 0xe5c80, 0x2102c9220, 0x73, 0x0, ...) /Users/rsc/g/go/src/pkg/fmt/print.go:818 +0x3d3 fp=0x221031e6f8 fmt.(*pp).doPrintf(0x2102e64e0, 0x12fb20, 0x2, 0x221031eb98, 0x1, ...) /Users/rsc/g/go/src/pkg/fmt/print.go:1183 +0x15cb fp=0x221031eaf0 fmt.Sprintf(0x12fb20, 0x2, 0x221031eb98, 0x1, 0x1, ...) /Users/rsc/g/go/src/pkg/fmt/print.go:234 +0x67 fp=0x221031eb40 flag.(*stringValue).String(0x2102c9210, 0x1, 0x0) /Users/rsc/g/go/src/pkg/flag/flag.go:180 +0xb3 fp=0x221031ebb0 flag.(*FlagSet).Var(0x2102f6000, 0x293d38, 0x2102c9210, 0x143490, 0xa, ...) /Users/rsc/g/go/src/pkg/flag/flag.go:633 +0x40 fp=0x221031eca0 flag.(*FlagSet).StringVar(0x2102f6000, 0x2102c9210, 0x143490, 0xa, 0x12fa60, ...) /Users/rsc/g/go/src/pkg/flag/flag.go:550 +0x91 fp=0x221031ece8 flag.(*FlagSet).String(0x2102f6000, 0x143490, 0xa, 0x12fa60, 0x0, ...) /Users/rsc/g/go/src/pkg/flag/flag.go:563 +0x87 fp=0x221031ed38 flag.String(0x143490, 0xa, 0x12fa60, 0x0, 0x161950, ...) /Users/rsc/g/go/src/pkg/flag/flag.go:570 +0x6b fp=0x221031ed80 testing.init() /Users/rsc/g/go/src/pkg/testing/testing.go:-531 +0xbb fp=0x221031edc0 strings_test.init() /Users/rsc/g/go/src/pkg/strings/strings_test.go:1115 +0x62 fp=0x221031ef70 main.init() strings/_test/_testmain.go:90 +0x3d fp=0x221031ef78 runtime.main() /Users/rsc/g/go/src/pkg/runtime/proc.c:180 +0x8a fp=0x221031efa0 runtime.goexit() /Users/rsc/g/go/src/pkg/runtime/proc.c:1269 fp=0x221031efa8 goroutine 2 [runnable]: runtime.MHeap_Scavenger() /Users/rsc/g/go/src/pkg/runtime/mheap.c:438 runtime.goexit() /Users/rsc/g/go/src/pkg/runtime/proc.c:1269 created by runtime.main /Users/rsc/g/go/src/pkg/runtime/proc.c:166 rax 0x23ccc0 rbx 0x23ccc0 rcx 0x0 rdx 0x38 rdi 0x2102c0170 rsi 0x221032cfe0 rbp 0x221032cfa0 rsp 0x7fff5fbff5b0 r8 0x2102c0120 r9 0x221032cfa0 r10 0x221032c000 r11 0x104ce8 r12 0xe5c80 r13 0x1be82baac718 r14 0x13091135f7d69200 r15 0x0 rip 0x1b2a6 rflags 0x10246 cs 0x2b fs 0x0 gs 0x0 Fixes #5723. R=r, dvyukov, go.peter.90, dave, iant CC=golang-dev https://golang.org/cl/10360048
2013-06-12runtime: add lr, ctxt, ret to GobufRuss Cox
Add gostartcall and gostartcallfn. The old gogocall = gostartcall + gogo. The old gogocallfn = gostartcallfn + gogo. R=dvyukov, minux.ma CC=golang-dev https://golang.org/cl/10036044
2013-06-03runtime: introduce preemption function (not used for now)Dmitriy Vyukov
This is part of preemptive scheduler. R=golang-dev, cshapiro, iant CC=golang-dev https://golang.org/cl/9843046
2013-01-30runtime: add support for panic/recover in Plan 9 note handlerAkshat Kumar
This change also resolves some issues with note handling: we now make sure that there is enough room at the bottom of every goroutine to execute the note handler, and the `exitstatus' is no longer a global entity, which resolves some race conditions. R=rminnich, npe, rsc, ality CC=golang-dev https://golang.org/cl/6569068
2012-03-155l, 6l, 8l: fix stack split logic for stacks near default segment sizeRuss Cox
Fixes #3310. R=golang-dev, r CC=golang-dev https://golang.org/cl/5823051
2011-12-16runtime: make more build-friendlyRuss Cox
Collapse the arch,os-specific directories into the main directory by renaming xxx/foo.c to foo_xxx.c, and so on. There are no substantial edits here, except to the Makefile. The assumption is that the Go tool will #define GOOS_darwin and GOARCH_amd64 and will make any file named something like signals_darwin.h available as signals_GOOS.h during the build. This replaces what used to be done with -I$(GOOS). There is still work to be done to make runtime build with standard tools, but this is a big step. After this we will have to write a script to generate all the generated files so they can be checked in (instead of generated during the build). R=r, iant, r, lucio.dere CC=golang-dev https://golang.org/cl/5490053
2011-09-17runtime: increase stack system space on windows/amd64Hector Chu
gotest src/pkg/exp/template/html was crashing because the exception handler overflowed the goroutine stack. R=alex.brainman, golang-dev CC=golang-dev https://golang.org/cl/5031049
2011-07-14runtime: correct FixedStack value (fixes windows build)Alex Brainman
Fixes #2068. R=rsc CC=golang-dev https://golang.org/cl/4705046
2011-07-12runtime: eliminate contention during stack allocationDmitriy Vyukov
Standard-sized stack frames use plain malloc/free instead of centralized lock-protected FixAlloc. Benchmark results on HP Z600 (2 x Xeon E5620, 8 HT cores, 2.40GHz) are as follows: benchmark old ns/op new ns/op delta BenchmarkStackGrowth 1045.00 949.00 -9.19% BenchmarkStackGrowth-2 3450.00 800.00 -76.81% BenchmarkStackGrowth-4 5076.00 513.00 -89.89% BenchmarkStackGrowth-8 7805.00 471.00 -93.97% BenchmarkStackGrowth-16 11751.00 321.00 -97.27% R=golang-dev, rsc CC=golang-dev https://golang.org/cl/4657091
2011-05-16runtime: make StackSystem part of StackGuardAlexey Borzenkov
Fixes #1779 R=rsc CC=golang-dev https://golang.org/cl/4543052
2011-02-22ld: detect stack overflow due to NOSPLITRuss Cox
Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061