This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes#1644.
Fixes#1731.
Fixes#2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
runtime knows how to get the time of day
without allocating memory.
R=golang-dev, dsymonds, dave, hectorchu, r, cw
CC=golang-dev
https://golang.org/cl/5297078
We only guarantee that the main goroutine runs on the
main OS thread for initialization. Programs that wish to
preserve that property for main.main can call runtime.LockOSThread.
This is what programs used to do before we unleashed
goroutines during init, so it is both a simple fix and keeps
existing programs working.
R=iant, r, dave, dvyukov
CC=golang-dev
https://golang.org/cl/5309070
Running test/garbage/parser.out.
On a 4-core Lenovo X201s (Linux):
31.12u 0.60s 31.74r 1 cpu, no atomics
32.27u 0.58s 32.86r 1 cpu, atomic instructions
33.04u 0.83s 27.47r 2 cpu
On a 16-core Xeon (Linux):
33.08u 0.65s 33.80r 1 cpu, no atomics
34.87u 1.12s 29.60r 2 cpu
36.00u 1.87s 28.43r 3 cpu
36.46u 2.34s 27.10r 4 cpu
38.28u 3.85s 26.92r 5 cpu
37.72u 5.25s 26.73r 6 cpu
39.63u 7.11s 26.95r 7 cpu
39.67u 8.10s 26.68r 8 cpu
On a 2-core MacBook Pro Core 2 Duo 2.26 (circa 2009, MacBookPro5,5):
39.43u 1.45s 41.27r 1 cpu, no atomics
43.98u 2.95s 38.69r 2 cpu
On a 2-core Mac Mini Core 2 Duo 1.83 (circa 2008; Macmini2,1):
48.81u 2.12s 51.76r 1 cpu, no atomics
57.15u 4.72s 51.54r 2 cpu
The handoff algorithm is really only good for two cores.
Beyond that we will need to so something more sophisticated,
like have each core hand off to the next one, around a circle.
Even so, the code is a good checkpoint; for now we'll limit the
number of gc procs to at most 2.
R=dvyukov
CC=golang-dev
https://golang.org/cl/4641082
The Windows implementation of the net package churns through a couple of channels for every read/write operation. This translates into a lot of time spent in the kernel creating and deleting event objects.
R=rsc, dvyukov, alex.brainman, jp
CC=golang-dev
https://golang.org/cl/4997044
Make the stack traces more readable for new
Go programmers while preserving their utility for old hands.
- Change status number [4] to string.
- Elide frames in runtime package (internal details).
- Swap file:line and arguments.
- Drop 'created by' for main goroutine.
- Show goroutines in order of allocation:
implies main goroutine first if nothing else.
There is no option to get the extra frames back.
Uncomment 'return 1' at the bottom of symtab.c.
$ 6.out
throw: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/rsc/g/go/src/pkg/runtime/x.go:22 +0x8a
goroutine 2 [select (no cases)]:
main.sel()
/Users/rsc/g/go/src/pkg/runtime/x.go:11 +0x18
created by main.main
/Users/rsc/g/go/src/pkg/runtime/x.go:19 +0x23
goroutine 3 [chan receive]:
main.recv(0xf8400010a0, 0x0)
/Users/rsc/g/go/src/pkg/runtime/x.go:15 +0x2e
created by main.main
/Users/rsc/g/go/src/pkg/runtime/x.go:20 +0x50
goroutine 4 [chan receive (nil chan)]:
main.recv(0x0, 0x0)
/Users/rsc/g/go/src/pkg/runtime/x.go:15 +0x2e
created by main.main
/Users/rsc/g/go/src/pkg/runtime/x.go:21 +0x66
$
$ 6.out index
panic: runtime error: index out of range
goroutine 1 [running]:
main.main()
/Users/rsc/g/go/src/pkg/runtime/x.go:25 +0xb9
$
$ 6.out nil
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x22ca]
goroutine 1 [running]:
main.main()
/Users/rsc/g/go/src/pkg/runtime/x.go:28 +0x211
$
$ 6.out panic
panic: panic
goroutine 1 [running]:
main.main()
/Users/rsc/g/go/src/pkg/runtime/x.go:30 +0x101
$
R=golang-dev, qyzhai, n13m3y3r, r
CC=golang-dev
https://golang.org/cl/4907048
Allocate Defer on stack during cgo calls, as suggested
by dvyukov. Also includes some comment corrections.
benchmark old,ns/op new,ns/op
BenchmarkCgoCall 669 330
(Intel Xeon CPU 1.80GHz * 4, Linux 386)
R=dvyukov, rsc
CC=golang-dev
https://golang.org/cl/4910041
The corruption can occur when GOMAXPROCS
is changed from >1 to 1, since GOMAXPROCS=1
does not imply there is only 1 goroutine running,
other goroutines can still be not parked after
the change.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4873050
Every time we enter callback from Windows, it is
possible that go exception handler is not at the top
of per-thread exception handlers chain. So it needs
to be installed again. At this moment this is done
by replacing top SEH frame with SEH frame as at time
of syscall for the time of callback. This is incorrect,
because, if exception strike, we won't be able to call
any exception handlers installed inside syscall,
because they are not in the chain. This changes
procedure to add new SEH frame on top of existing
chain instead.
I also removed m sehframe field, because I don't
think it is needed. We use single global exception
handler everywhere.
R=golang-dev, r
CC=golang-dev, hectorchu
https://golang.org/cl/4832060
The change adds specialized type algorithms
for slices and types of size 8/16/32/64/128.
It significantly accelerates chan and map operations
for most builtin types as well as user structs.
benchmark old,ns/op new,ns/op
BenchmarkChanUncontended 226 94
(on Intel Xeon E5620, 2.4GHz, Linux 64 bit)
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4815087
The data race can lead to reads of partially
initialized concurrently mutated symbol data.
The change also adds a simple sanity test
for Caller() and FuncForPC().
R=rsc
CC=golang-dev
https://golang.org/cl/4817058
The data race is on newly published Itab nodes, which are
both unsafely published and unsafely acquired. It can
break on IA-32/Intel64 due to compiler optimizations
(most likely not an issue as of now) and on ARM due to
hardware memory access reorderings.
R=rsc
CC=golang-dev
https://golang.org/cl/4673055
runtime.goidgen can be quite frequently modified and
shares cache line with the following variables,
it leads to false sharing.
50c6b0 b nfname
50c6b4 b nfunc
50c6b8 b nfunc$17
50c6bc b nhist$17
50c6c0 B runtime.checking
50c6c4 B runtime.gcwaiting
50c6c8 B runtime.goidgen
50c6cc B runtime.gomaxprocs
50c6d0 B runtime.panicking
50c6d4 B strconv.IntSize
50c6d8 B src/pkg/runtime/_xtest_.ss
50c6e0 B src/pkg/runtime/_xtest_.stop
50c6e8 b addrfree
50c6f0 b addrmem
50c6f8 b argv
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4673054
This change was adapted from gccgo's libgo/runtime/mem.c at
Ian Taylor's suggestion. It fixes all.bash failing with
"address space conflict: map() =" on amd64 Linux with kernel
version 2.6.32.8-grsec-2.1.14-modsign-xeon-64.
With this change, SysMap will use MAP_FIXED to allocate its desired
address space, after first calling mincore to check that there is
nothing else mapped there.
R=iant, dave, n13m3y3r, rsc
CC=golang-dev
https://golang.org/cl/4438091
The g->sched.sp saved stack pointer and the
g->stackbase and g->stackguard stack bounds
can change even while "the world is stopped",
because a goroutine has to call functions (and
therefore might split its stack) when exiting a
system call to check whether the world is stopped
(and if so, wait until the world continues).
That means the garbage collector cannot access
those values safely (without a race) for goroutines
executing system calls. Instead, save a consistent
triple in g->gcsp, g->gcstack, g->gcguard during
entersyscall and have the garbage collector refer
to those.
The old code was occasionally seeing (because of
the race) an sp and stk that did not correspond to
each other, so that stk - sp was not the number of
stack bytes following sp. In that case, if sp < stk
then the call scanblock(sp, stk - sp) scanned too
many bytes (anything between the two pointers,
which pointed into different allocation blocks).
If sp > stk then stk - sp wrapped around.
On 32-bit, stk - sp is a uintptr (uint32) converted
to int64 in the call to scanblock, so a large (~4G)
but positive number. Scanblock would try to scan
that many bytes and eventually fault accessing
unmapped memory. On 64-bit, stk - sp is a uintptr (uint64)
promoted to int64 in the call to scanblock, so a negative
number. Scanblock would not scan anything, possibly
causing in-use blocks to be freed.
In short, 32-bit platforms would have seen either
ineffective garbage collection or crashes during garbage
collection, while 64-bit platforms would have seen
either ineffective or incorrect garbage collection.
You can see the invalid arguments to scanblock in the
stack traces in issue 1620.
Fixes#1620.
Fixes#1746.
R=iant, r
CC=golang-dev
https://golang.org/cl/4437075
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
* Change use of m->g0 stack (aka scheduler stack).
* Provide runtime.mcall(f) to invoke f() on m->g0 stack.
* Replace scheduler loop entry with runtime.mcall(schedule).
Runtime.mcall eliminates the need for fake scheduler states that
exist just to run a bit of code on the m->g0 stack
(Grecovery, Gstackalloc).
The elimination of the scheduler as a loop that stops and
starts using gosave and gogo fixes a bad interaction with the
way cgo uses the m->g0 stack. Cgo runs external (gcc-compiled)
C functions on that stack, and then when calling back into Go,
it sets m->g0->sched.sp below the added call frames, so that
other uses of m->g0's stack will not interfere with those frames.
Unfortunately, gogo (longjmp) back to the scheduler loop at
this point would end up running scheduler with the lower
sp, which no longer points at a valid stack frame for
a call to scheduler. If scheduler then wrote any function call
arguments or local variables to where it expected the stack
frame to be, it would overwrite other data on the stack.
I realized this possibility while debugging a problem with
calling complex Go code in a Go -> C -> Go cgo callback.
This wasn't the bug I was looking for, it turns out, but I believe
it is a real bug nonetheless. Switching to runtime.mcall, which
only adds new frames to the stack and never jumps into
functions running in existing ones, fixes this bug.
* Move cgo-related code out of proc.c into cgocall.c.
* Add very large comment describing cgo call sequences.
* Simpilify, regularize cgo function implementations and names.
* Add test suite as misc/cgo/test.
Now the Go -> C path calls cgocall, which calls asmcgocall,
and the C -> Go path calls cgocallback, which calls cgocallbackg.
The shuffling, which affects mainly the callback case, moves
most of the callback implementation to cgocallback running
on the m->curg stack (not the m->g0 scheduler stack) and
only while accounted for with $GOMAXPROCS (between calls
to exitsyscall and entersyscall).
The previous callback code did not block in startcgocallback's
approximation to exitsyscall, so if, say, the garbage collector
were running, it would still barge in and start doing things
like call malloc. Similarly endcgocallback's approximation of
entersyscall did not call matchmg to kick off new OS threads
when necessary, which caused the bug in issue 1560.
Fixes#1560.
R=iant
CC=golang-dev
https://golang.org/cl/4253054
This functionality might be used in environments
where programs are limited to a single thread,
to simulate a select-driven network server. It is
not exposed via the standard runtime API.
R=r, r2
CC=golang-dev
https://golang.org/cl/4254041
Avoids deadlocks like the one below, in which a stack split happened
in order to call lock(&stacks), but then the stack unsplit cannot run
because stacks is now locked.
The only code calling stackalloc that wasn't on a scheduler
stack already was malg, which creates a new goroutine.
runtime.futex+0x23 /home/rsc/g/go/src/pkg/runtime/linux/amd64/sys.s:139
runtime.futex()
futexsleep+0x50 /home/rsc/g/go/src/pkg/runtime/linux/thread.c:51
futexsleep(0x5b0188, 0x300000003, 0x100020000, 0x4159e2)
futexlock+0x85 /home/rsc/g/go/src/pkg/runtime/linux/thread.c:119
futexlock(0x5b0188, 0x5b0188)
runtime.lock+0x56 /home/rsc/g/go/src/pkg/runtime/linux/thread.c:158
runtime.lock(0x5b0188, 0x7f0d27b4a000)
runtime.stackfree+0x4d /home/rsc/g/go/src/pkg/runtime/malloc.goc:336
runtime.stackfree(0x7f0d27b4a000, 0x1000, 0x8, 0x7fff37e1e218)
runtime.oldstack+0xa6 /home/rsc/g/go/src/pkg/runtime/proc.c:705
runtime.oldstack()
runtime.lessstack+0x22 /home/rsc/g/go/src/pkg/runtime/amd64/asm.s:224
runtime.lessstack()
----- lessstack called from goroutine 2 -----
runtime.lock+0x56 /home/rsc/g/go/src/pkg/runtime/linux/thread.c:158
runtime.lock(0x5b0188, 0x40a5e2)
runtime.stackalloc+0x55 /home/rsc/g/go/src/pkg/runtime/malloc.c:316
runtime.stackalloc(0x1000, 0x4055b0)
runtime.malg+0x3d /home/rsc/g/go/src/pkg/runtime/proc.c:803
runtime.malg(0x1000, 0x40add9)
runtime.newproc1+0x12b /home/rsc/g/go/src/pkg/runtime/proc.c:854
runtime.newproc1(0xf840027440, 0x7f0d27b49230, 0x0, 0x49f238, 0x40, ...)
runtime.newproc+0x2f /home/rsc/g/go/src/pkg/runtime/proc.c:831
runtime.newproc(0x0, 0xf840027440, 0xf800000010, 0x44b059)
...
R=r, r2
CC=golang-dev
https://golang.org/cl/4216045
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
Follow morestack, so that crashes during a stack split
give complete traces. Also mark stack segment boundaries
as an aid to debugging.
Correct various line number bugs with yet another attempt
at interpreting the pc/ln table. This one has a chance at
being correct, because I based it on reading src/cmd/ld/lib.c
instead of on reading the documentation.
Fixes#1138.
Fixes#1430.
Fixes#1461.
throw: runtime: split stack overflow
runtime.throw+0x3e /home/rsc/g/go2/src/pkg/runtime/runtime.c:78
runtime.throw(0x81880af, 0xf75c8b18)
runtime.newstack+0xad /home/rsc/g/go2/src/pkg/runtime/proc.c:728
runtime.newstack()
runtime.morestack+0x4f /home/rsc/g/go2/src/pkg/runtime/386/asm.s:184
runtime.morestack()
----- morestack called from stack: -----
runtime.new+0x1a /home/rsc/g/go2/src/pkg/runtime/malloc.c:288
runtime.new(0x1, 0x0, 0x0)
gongo.makeBoard+0x33 /tmp/Gongo/gongo_robot_test.go:344
gongo.makeBoard(0x809d238, 0x1, 0xf76092c8, 0x1)
----- stack segment boundary -----
gongo.checkEasyScore+0xcc /tmp/Gongo/gongo_robot_test.go:287
gongo.checkEasyScore(0xf764b710, 0x0, 0x809d238, 0x1)
gongo.TestEasyScore+0x8c /tmp/Gongo/gongo_robot_test.go:255
gongo.TestEasyScore(0xf764b710, 0x818a990)
testing.tRunner+0x2f /home/rsc/g/go2/src/pkg/testing/testing.go:132
testing.tRunner(0xf764b710, 0xf763b5dc, 0x0)
runtime.goexit /home/rsc/g/go2/src/pkg/runtime/proc.c:149
runtime.goexit()
R=ken2, r
CC=golang-dev
https://golang.org/cl/4000053
The callback mechanism has been made more flexible.
Eliminated one round of argument copying in Syscall.
Faster Get/SetLastError implemented.
Added gettime for gc perf profiling.
R=rsc, brainman, mattn, rog
CC=golang-dev
https://golang.org/cl/4058046
The old heap maps used a multilevel table, but that
was overkill: there are only 1M entries on a 32-bit
machine and we can arrange to use a dense address
range on a 64-bit machine.
The heap map is in bss. The assumption is that if
we don't touch the pages they won't be mapped in.
Also moved some duplicated memory allocation
code out of the OS-specific files.
R=r
CC=golang-dev
https://golang.org/cl/4118042