2009-05-26 12:18:42 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2011-12-19 13:51:13 -07:00
|
|
|
#include "zasm_GOOS_GOARCH.h"
|
2013-07-16 14:24:09 -06:00
|
|
|
#include "funcdata.h"
|
2013-08-07 11:23:24 -06:00
|
|
|
#include "../../cmd/ld/textflag.h"
|
2009-06-23 12:54:23 -06:00
|
|
|
|
|
|
|
// using frame size $-4 means do not save LR on stack.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT _rt0_go(SB),NOSPLIT,$-4
|
2010-10-17 09:41:23 -06:00
|
|
|
MOVW $0xcafebabe, R12
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// copy arguments forward on an even stack
|
2009-06-23 12:54:23 -06:00
|
|
|
// use R13 instead of SP to avoid linker rewriting the offsets
|
|
|
|
MOVW 0(R13), R0 // argc
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
MOVW 4(R13), R1 // argv
|
2011-02-22 15:40:40 -07:00
|
|
|
SUB $64, R13 // plenty of scratch
|
2009-06-23 12:54:23 -06:00
|
|
|
AND $~7, R13
|
2011-02-22 15:40:40 -07:00
|
|
|
MOVW R0, 60(R13) // save argc, argv away
|
|
|
|
MOVW R1, 64(R13)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
// set up g register
|
|
|
|
// g is R10
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
MOVW $runtime·g0(SB), g
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW $runtime·m0(SB), R8
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// save m->g0 = g0
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g, m_g0(R8)
|
|
|
|
// save g->m = m0
|
|
|
|
MOVW R8, g_m(g)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// create istack out of the OS stack
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW $(-8192+104)(R13), R0
|
|
|
|
MOVW R0, g_stackguard(g) // (w 104b guard)
|
2013-06-03 02:28:24 -06:00
|
|
|
MOVW R0, g_stackguard0(g)
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW R13, g_stackbase(g)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·emptyfunc(SB) // fault if stack check is wrong
|
2009-06-16 12:25:58 -06:00
|
|
|
|
2014-07-10 13:14:49 -06:00
|
|
|
#ifndef GOOS_nacl
|
2013-02-28 14:24:38 -07:00
|
|
|
// if there is an _cgo_init, call it.
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
MOVW _cgo_init(SB), R4
|
|
|
|
CMP $0, R4
|
|
|
|
B.EQ nocgo
|
cmd/go, cmd/ld, runtime, os/user: TLS emulation for android
Based on cl/69170045 by Elias Naur.
There are currently several schemes for acquiring a TLS
slot to save the g register. None of them appear to work
for android. The closest are linux and darwin.
Linux uses a linker TLS relocation. This is not supported
by the android linker.
Darwin uses a fixed offset, and calls pthread_key_create
until it gets the slot it wants. As the runtime loads
late in the android process lifecycle, after an
arbitrary number of other libraries, we cannot rely on
any particular slot being available.
So we call pthread_key_create, take the first slot we are
given, and put it in runtime.tlsg, which we turn into a
regular variable in cmd/ld.
Makes android/arm cgo binaries work.
LGTM=minux
R=elias.naur, minux, dave, josharian
CC=golang-codereviews
https://golang.org/cl/106380043
2014-07-03 14:14:34 -06:00
|
|
|
MRC 15, 0, R0, C13, C0, 3 // load TLS base pointer
|
|
|
|
MOVW R0, R3 // arg 3: TLS base pointer
|
|
|
|
MOVW $runtime·tlsg(SB), R2 // arg 2: tlsg
|
|
|
|
MOVW $setg_gcc<>(SB), R1 // arg 1: setg
|
|
|
|
MOVW g, R0 // arg 0: G
|
|
|
|
BL (R4) // will clobber R0-R3
|
2014-07-10 13:14:49 -06:00
|
|
|
#endif
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
|
|
|
|
nocgo:
|
2013-06-03 02:28:24 -06:00
|
|
|
// update stackguard after _cgo_init
|
|
|
|
MOVW g_stackguard0(g), R0
|
|
|
|
MOVW R0, g_stackguard(g)
|
2012-05-04 04:20:09 -06:00
|
|
|
|
2012-09-06 22:26:42 -06:00
|
|
|
BL runtime·checkgoarm(SB)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·check(SB)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// saved argc, argv
|
2011-02-22 15:40:40 -07:00
|
|
|
MOVW 60(R13), R0
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW R0, 4(R13)
|
2011-02-22 15:40:40 -07:00
|
|
|
MOVW 64(R13), R1
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW R1, 8(R13)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·args(SB)
|
|
|
|
BL runtime·osinit(SB)
|
2013-03-12 11:47:44 -06:00
|
|
|
BL runtime·hashinit(SB)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·schedinit(SB)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// create a new goroutine to start program
|
2013-02-21 15:01:13 -07:00
|
|
|
MOVW $runtime·main·f(SB), R0
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW.W R0, -4(R13)
|
2009-06-16 12:25:58 -06:00
|
|
|
MOVW $8, R0
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW.W R0, -4(R13)
|
2009-06-16 12:25:58 -06:00
|
|
|
MOVW $0, R0
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW.W R0, -4(R13) // push $0 as guard
|
2013-07-16 14:24:09 -06:00
|
|
|
ARGSIZE(12)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·newproc(SB)
|
2013-07-16 14:24:09 -06:00
|
|
|
ARGSIZE(-1)
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW $12(R13), R13 // pop args and LR
|
2009-06-16 12:25:58 -06:00
|
|
|
|
|
|
|
// start this M
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL runtime·mstart(SB)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
2009-10-29 22:21:14 -06:00
|
|
|
MOVW $1234, R0
|
|
|
|
MOVW $1000, R1
|
|
|
|
MOVW R0, (R1) // fail hard
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2013-02-21 15:01:13 -07:00
|
|
|
DATA runtime·main·f+0(SB)/4,$runtime·main(SB)
|
2013-08-07 11:23:24 -06:00
|
|
|
GLOBL runtime·main·f(SB),RODATA,$4
|
2013-02-21 15:01:13 -07:00
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
|
2012-04-24 09:19:44 -06:00
|
|
|
// gdb won't skip this breakpoint instruction automatically,
|
|
|
|
// so you must manually "set $pc+=4" to skip it and continue.
|
2014-07-10 13:14:49 -06:00
|
|
|
#ifdef GOOS_nacl
|
|
|
|
WORD $0xe125be7f // BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
|
|
|
|
#else
|
2013-08-12 11:36:33 -06:00
|
|
|
WORD $0xe1200071 // BKPT 0x0001
|
2014-07-10 13:14:49 -06:00
|
|
|
#endif
|
2010-04-05 13:51:09 -06:00
|
|
|
RET
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·asminit(SB),NOSPLIT,$0-0
|
2013-02-12 10:00:04 -07:00
|
|
|
// disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
|
2013-12-28 21:25:34 -07:00
|
|
|
MOVB runtime·goarm(SB), R11
|
2013-08-12 11:36:33 -06:00
|
|
|
CMP $5, R11
|
|
|
|
BLE 4(PC)
|
|
|
|
WORD $0xeef1ba10 // vmrs r11, fpscr
|
|
|
|
BIC $(1<<24), R11
|
|
|
|
WORD $0xeee1ba10 // vmsr fpscr, r11
|
2012-02-13 23:23:15 -07:00
|
|
|
RET
|
|
|
|
|
2009-06-23 12:54:23 -06:00
|
|
|
/*
|
|
|
|
* go-routine
|
|
|
|
*/
|
2009-06-10 12:53:07 -06:00
|
|
|
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// void gosave(Gobuf*)
|
2009-06-23 12:54:23 -06:00
|
|
|
// save state in Gobuf; setjmp
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·gosave(SB), NOSPLIT, $-4-4
|
2010-10-08 17:46:05 -06:00
|
|
|
MOVW 0(FP), R0 // gobuf
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW SP, gobuf_sp(R0)
|
|
|
|
MOVW LR, gobuf_pc(R0)
|
|
|
|
MOVW g, gobuf_g(R0)
|
2013-06-12 13:22:26 -06:00
|
|
|
MOVW $0, R11
|
|
|
|
MOVW R11, gobuf_lr(R0)
|
|
|
|
MOVW R11, gobuf_ret(R0)
|
|
|
|
MOVW R11, gobuf_ctxt(R0)
|
2009-06-23 12:54:23 -06:00
|
|
|
RET
|
|
|
|
|
2013-06-12 16:05:10 -06:00
|
|
|
// void gogo(Gobuf*)
|
2009-06-23 12:54:23 -06:00
|
|
|
// restore state from Gobuf; longjmp
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·gogo(SB), NOSPLIT, $-4-4
|
2010-10-08 17:46:05 -06:00
|
|
|
MOVW 0(FP), R1 // gobuf
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW gobuf_g(R1), g
|
|
|
|
MOVW 0(g), R2 // make sure g != nil
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
MOVB runtime·iscgo(SB), R2
|
2014-06-30 17:10:41 -06:00
|
|
|
CMP $0, R2 // if in Cgo, we have to save g
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
BL.NE runtime·save_g(SB) // this call will clobber R0
|
2009-06-23 12:54:23 -06:00
|
|
|
MOVW gobuf_sp(R1), SP // restore SP
|
2013-06-12 13:22:26 -06:00
|
|
|
MOVW gobuf_lr(R1), LR
|
|
|
|
MOVW gobuf_ret(R1), R0
|
|
|
|
MOVW gobuf_ctxt(R1), R7
|
|
|
|
MOVW $0, R11
|
|
|
|
MOVW R11, gobuf_sp(R1) // clear to help garbage collector
|
|
|
|
MOVW R11, gobuf_ret(R1)
|
|
|
|
MOVW R11, gobuf_lr(R1)
|
|
|
|
MOVW R11, gobuf_ctxt(R1)
|
runtime: record proper goroutine state during stack split
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-27 09:32:01 -06:00
|
|
|
CMP R11, R11 // set condition codes for == test, needed by stack split
|
2014-07-10 13:14:49 -06:00
|
|
|
MOVW gobuf_pc(R1), R11
|
|
|
|
B (R11)
|
2009-06-23 12:54:23 -06:00
|
|
|
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// void mcall(void (*fn)(G*))
|
|
|
|
// Switch to m->g0's stack, call fn(g).
|
runtime: stack split + garbage collection bug
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
2011-04-27 21:21:12 -06:00
|
|
|
// Fn must never return. It should gogo(&g->sched)
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// to keep running g.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·mcall(SB), NOSPLIT, $-4-4
|
2013-06-05 05:16:53 -06:00
|
|
|
// Save caller state in g->sched.
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW SP, (g_sched+gobuf_sp)(g)
|
|
|
|
MOVW LR, (g_sched+gobuf_pc)(g)
|
runtime: record proper goroutine state during stack split
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-27 09:32:01 -06:00
|
|
|
MOVW $0, R11
|
|
|
|
MOVW R11, (g_sched+gobuf_lr)(g)
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW g, (g_sched+gobuf_g)(g)
|
|
|
|
|
|
|
|
// Switch to m->g0 & its stack, call fn.
|
|
|
|
MOVW g, R1
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW m_g0(R8), g
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
CMP g, R1
|
2013-08-29 16:53:34 -06:00
|
|
|
B.NE 2(PC)
|
|
|
|
B runtime·badmcall(SB)
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVB runtime·iscgo(SB), R11
|
|
|
|
CMP $0, R11
|
|
|
|
BL.NE runtime·save_g(SB)
|
|
|
|
MOVW fn+0(FP), R0
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), SP
|
|
|
|
SUB $8, SP
|
|
|
|
MOVW R1, 4(SP)
|
|
|
|
BL (R0)
|
2013-08-29 16:53:34 -06:00
|
|
|
B runtime·badmcall2(SB)
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
RET
|
|
|
|
|
2014-07-30 10:01:52 -06:00
|
|
|
// switchtoM is a dummy routine that onM leaves at the bottom
|
|
|
|
// of the G stack. We need to distinguish the routine that
|
|
|
|
// lives at the bottom of the G stack from the one that lives
|
|
|
|
// at the top of the M stack because the one at the top of
|
|
|
|
// the M stack terminates the stack walk (see topofstack()).
|
|
|
|
TEXT runtime·switchtoM(SB), NOSPLIT, $0-4
|
|
|
|
MOVW $0, R0
|
|
|
|
BL (R0) // clobber lr to ensure push {lr} is kept
|
|
|
|
RET
|
|
|
|
|
|
|
|
// void onM(void (*fn)())
|
|
|
|
// calls fn() on the M stack.
|
|
|
|
// switches to the M stack if not already on it, and
|
|
|
|
// switches back when fn() returns.
|
|
|
|
TEXT runtime·onM(SB), NOSPLIT, $0-4
|
|
|
|
MOVW fn+0(FP), R0 // R0 = fn
|
|
|
|
MOVW g_m(g), R1 // R1 = m
|
|
|
|
MOVW m_g0(R1), R2 // R2 = g0
|
|
|
|
CMP g, R2
|
|
|
|
B.EQ onm
|
|
|
|
|
|
|
|
// save our state in g->sched. Pretend to
|
|
|
|
// be switchtoM if the G stack is scanned.
|
|
|
|
MOVW $runtime·switchtoM(SB), R3
|
|
|
|
ADD $4, R3, R3 // get past push {lr}
|
|
|
|
MOVW R3, (g_sched+gobuf_pc)(g)
|
|
|
|
MOVW SP, (g_sched+gobuf_sp)(g)
|
|
|
|
MOVW LR, (g_sched+gobuf_lr)(g)
|
|
|
|
MOVW g, (g_sched+gobuf_g)(g)
|
|
|
|
|
|
|
|
// switch to g0
|
|
|
|
MOVW R2, g
|
|
|
|
MOVW (g_sched+gobuf_sp)(R2), SP
|
|
|
|
|
|
|
|
// call target function
|
|
|
|
ARGSIZE(0)
|
|
|
|
BL (R0)
|
|
|
|
|
|
|
|
// switch back to g
|
|
|
|
MOVW g_m(g), R1
|
|
|
|
MOVW m_curg(R1), g
|
|
|
|
MOVW (g_sched+gobuf_sp)(g), SP
|
|
|
|
MOVW $0, R3
|
|
|
|
MOVW R3, (g_sched+gobuf_sp)(g)
|
|
|
|
RET
|
|
|
|
|
|
|
|
onm:
|
|
|
|
BL (R0)
|
|
|
|
RET
|
|
|
|
|
2009-06-23 12:54:23 -06:00
|
|
|
/*
|
|
|
|
* support for morestack
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Called during function prolog when more stack is needed.
|
|
|
|
// R1 frame size
|
|
|
|
// R2 arg size
|
|
|
|
// R3 prolog's LR
|
2010-04-05 13:51:09 -06:00
|
|
|
// NB. we do not save R0 because we've forced 5c to pass all arguments
|
2009-10-23 11:59:31 -06:00
|
|
|
// on the stack.
|
2009-06-23 12:54:23 -06:00
|
|
|
// using frame size $-4 means do not save LR on stack.
|
2013-07-18 14:53:45 -06:00
|
|
|
//
|
|
|
|
// The traceback routines see morestack on a g0 as being
|
|
|
|
// the top of a stack (for example, morestack calling newstack
|
|
|
|
// calling the scheduler calling newm calling gc), so we must
|
|
|
|
// record an argument size. For that purpose, it has no arguments.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·morestack(SB),NOSPLIT,$-4-0
|
2009-06-23 12:54:23 -06:00
|
|
|
// Cannot grow scheduler stack (m->g0).
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW m_g0(R8), R4
|
2009-06-23 12:54:23 -06:00
|
|
|
CMP g, R4
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
BL.EQ runtime·abort(SB)
|
2009-06-10 12:53:07 -06:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW R1, m_moreframesize(R8)
|
|
|
|
MOVW R2, m_moreargsize(R8)
|
2009-06-23 12:54:23 -06:00
|
|
|
|
runtime: record proper goroutine state during stack split
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-27 09:32:01 -06:00
|
|
|
// Called from f.
|
|
|
|
// Set g->sched to context in f.
|
|
|
|
MOVW R7, (g_sched+gobuf_ctxt)(g)
|
|
|
|
MOVW SP, (g_sched+gobuf_sp)(g)
|
|
|
|
MOVW LR, (g_sched+gobuf_pc)(g)
|
|
|
|
MOVW R3, (g_sched+gobuf_lr)(g)
|
|
|
|
|
2009-06-23 12:54:23 -06:00
|
|
|
// Called from f.
|
|
|
|
// Set m->morebuf to f's caller.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC
|
|
|
|
MOVW SP, (m_morebuf+gobuf_sp)(R8) // f's caller's SP
|
2011-01-14 12:05:20 -07:00
|
|
|
MOVW $4(SP), R3 // f's argument pointer
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW R3, m_moreargp(R8)
|
|
|
|
MOVW g, (m_morebuf+gobuf_g)(R8)
|
2009-06-23 12:54:23 -06:00
|
|
|
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// Call newstack on m->g0's stack.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW m_g0(R8), g
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), SP
|
2013-07-18 14:53:45 -06:00
|
|
|
BL runtime·newstack(SB)
|
2009-06-23 12:54:23 -06:00
|
|
|
|
2013-08-01 16:51:55 -06:00
|
|
|
// Not reached, but make sure the return PC from the call to newstack
|
|
|
|
// is still in this function, and not the beginning of the next.
|
|
|
|
RET
|
|
|
|
|
2014-03-04 11:53:08 -07:00
|
|
|
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0
|
|
|
|
MOVW $0, R7
|
2014-03-04 12:03:39 -07:00
|
|
|
B runtime·morestack(SB)
|
2014-03-04 11:53:08 -07:00
|
|
|
|
2013-08-02 14:03:14 -06:00
|
|
|
// Called from panic. Mimics morestack,
|
2009-07-08 19:16:09 -06:00
|
|
|
// reuses stack growth code to create a frame
|
|
|
|
// with the desired args running the desired function.
|
|
|
|
//
|
|
|
|
// func call(fn *byte, arg *byte, argsize uint32).
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·newstackcall(SB), NOSPLIT, $-4-12
|
2009-07-08 19:16:09 -06:00
|
|
|
// Save our caller's state as the PC and SP to
|
|
|
|
// restore when returning from f.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW LR, (m_morebuf+gobuf_pc)(R8) // our caller's PC
|
|
|
|
MOVW SP, (m_morebuf+gobuf_sp)(R8) // our caller's SP
|
|
|
|
MOVW g, (m_morebuf+gobuf_g)(R8)
|
2009-07-08 19:16:09 -06:00
|
|
|
|
2013-06-27 14:51:06 -06:00
|
|
|
// Save our own state as the PC and SP to restore
|
|
|
|
// if this goroutine needs to be restarted.
|
2013-08-02 14:03:14 -06:00
|
|
|
MOVW $runtime·newstackcall(SB), R11
|
2013-06-27 14:51:06 -06:00
|
|
|
MOVW R11, (g_sched+gobuf_pc)(g)
|
|
|
|
MOVW LR, (g_sched+gobuf_lr)(g)
|
|
|
|
MOVW SP, (g_sched+gobuf_sp)(g)
|
|
|
|
|
2009-07-08 19:16:09 -06:00
|
|
|
// Set up morestack arguments to call f on a new stack.
|
2010-03-29 22:48:22 -06:00
|
|
|
// We set f's frame size to 1, as a hint to newstack
|
2013-08-02 14:03:14 -06:00
|
|
|
// that this is a call from runtime·newstackcall.
|
2010-03-29 22:48:22 -06:00
|
|
|
// If it turns out that f needs a larger frame than
|
|
|
|
// the default stack, f's usual stack growth prolog will
|
|
|
|
// allocate a new segment (and recopy the arguments).
|
2010-10-08 17:46:05 -06:00
|
|
|
MOVW 4(SP), R0 // fn
|
|
|
|
MOVW 8(SP), R1 // arg frame
|
|
|
|
MOVW 12(SP), R2 // arg size
|
2009-07-08 19:16:09 -06:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW R0, m_cret(R8) // f's PC
|
|
|
|
MOVW R1, m_moreargp(R8) // f's argument pointer
|
|
|
|
MOVW R2, m_moreargsize(R8) // f's argument size
|
2010-03-29 22:48:22 -06:00
|
|
|
MOVW $1, R3
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW R3, m_moreframesize(R8) // f's frame size
|
2009-07-08 19:16:09 -06:00
|
|
|
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// Call newstack on m->g0's stack.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW m_g0(R8), g
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), SP
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
B runtime·newstack(SB)
|
2009-07-08 19:16:09 -06:00
|
|
|
|
2013-08-02 14:03:14 -06:00
|
|
|
// reflect·call: call a function with the given argument list
|
|
|
|
// func call(f *FuncVal, arg *byte, argsize uint32).
|
|
|
|
// we don't have variable-sized frames, so we use a small number
|
|
|
|
// of constant-sized-frame functions to encode a few bits of size in the pc.
|
|
|
|
// Caution: ugly multiline assembly macros in your future!
|
|
|
|
|
|
|
|
#define DISPATCH(NAME,MAXSIZE) \
|
|
|
|
CMP $MAXSIZE, R0; \
|
|
|
|
B.HI 3(PC); \
|
2014-07-30 11:11:44 -06:00
|
|
|
MOVW $NAME(SB), R1; \
|
2013-08-02 14:03:14 -06:00
|
|
|
B (R1)
|
|
|
|
|
reflect, runtime: fix crash in GC due to reflect.call + precise GC
Given
type Outer struct {
*Inner
...
}
the compiler generates the implementation of (*Outer).M dispatching to
the embedded Inner. The implementation is logically:
func (p *Outer) M() {
(p.Inner).M()
}
but since the only change here is the replacement of one pointer
receiver with another, the actual generated code overwrites the
original receiver with the p.Inner pointer and then jumps to the M
method expecting the *Inner receiver.
During reflect.Value.Call, we create an argument frame and the
associated data structures to describe it to the garbage collector,
populate the frame, call reflect.call to run a function call using
that frame, and then copy the results back out of the frame. The
reflect.call function does a memmove of the frame structure onto the
stack (to set up the inputs), runs the call, and the memmoves the
stack back to the frame structure (to preserve the outputs).
Originally reflect.call did not distinguish inputs from outputs: both
memmoves were for the full stack frame. However, in the case where the
called function was one of these wrappers, the rewritten receiver is
almost certainly a different type than the original receiver. This is
not a problem on the stack, where we use the program counter to
determine the type information and understand that during (*Outer).M
the receiver is an *Outer while during (*Inner).M the receiver in the
same memory word is now an *Inner. But in the statically typed
argument frame created by reflect, the receiver is always an *Outer.
Copying the modified receiver pointer off the stack into the frame
will store an *Inner there, and then if a garbage collection happens
to scan that argument frame before it is discarded, it will scan the
*Inner memory as if it were an *Outer. If the two have different
memory layouts, the collection will intepret the memory incorrectly.
Fix by only copying back the results.
Fixes #7725.
LGTM=khr
R=khr
CC=dave, golang-codereviews
https://golang.org/cl/85180043
2014-04-08 09:11:35 -06:00
|
|
|
TEXT reflect·call(SB), NOSPLIT, $-4-16
|
2013-08-02 14:03:14 -06:00
|
|
|
MOVW argsize+8(FP), R0
|
2014-07-30 11:11:44 -06:00
|
|
|
DISPATCH(runtime·call16, 16)
|
|
|
|
DISPATCH(runtime·call32, 32)
|
|
|
|
DISPATCH(runtime·call64, 64)
|
|
|
|
DISPATCH(runtime·call128, 128)
|
|
|
|
DISPATCH(runtime·call256, 256)
|
|
|
|
DISPATCH(runtime·call512, 512)
|
|
|
|
DISPATCH(runtime·call1024, 1024)
|
|
|
|
DISPATCH(runtime·call2048, 2048)
|
|
|
|
DISPATCH(runtime·call4096, 4096)
|
|
|
|
DISPATCH(runtime·call8192, 8192)
|
|
|
|
DISPATCH(runtime·call16384, 16384)
|
|
|
|
DISPATCH(runtime·call32768, 32768)
|
|
|
|
DISPATCH(runtime·call65536, 65536)
|
|
|
|
DISPATCH(runtime·call131072, 131072)
|
|
|
|
DISPATCH(runtime·call262144, 262144)
|
|
|
|
DISPATCH(runtime·call524288, 524288)
|
|
|
|
DISPATCH(runtime·call1048576, 1048576)
|
|
|
|
DISPATCH(runtime·call2097152, 2097152)
|
|
|
|
DISPATCH(runtime·call4194304, 4194304)
|
|
|
|
DISPATCH(runtime·call8388608, 8388608)
|
|
|
|
DISPATCH(runtime·call16777216, 16777216)
|
|
|
|
DISPATCH(runtime·call33554432, 33554432)
|
|
|
|
DISPATCH(runtime·call67108864, 67108864)
|
|
|
|
DISPATCH(runtime·call134217728, 134217728)
|
|
|
|
DISPATCH(runtime·call268435456, 268435456)
|
|
|
|
DISPATCH(runtime·call536870912, 536870912)
|
|
|
|
DISPATCH(runtime·call1073741824, 1073741824)
|
2013-08-02 14:03:14 -06:00
|
|
|
MOVW $runtime·badreflectcall(SB), R1
|
|
|
|
B (R1)
|
|
|
|
|
2014-05-21 15:28:34 -06:00
|
|
|
// Argument map for the callXX frames. Each has one
|
|
|
|
// stack map (for the single call) with 3 arguments.
|
|
|
|
DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
|
|
|
|
DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
|
|
|
|
DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
|
|
|
|
GLOBL gcargs_reflectcall<>(SB),RODATA,$12
|
|
|
|
|
|
|
|
// callXX frames have no locals
|
|
|
|
DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
|
|
|
|
DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
|
|
|
|
GLOBL gclocals_reflectcall<>(SB),RODATA,$8
|
|
|
|
|
2013-08-06 15:33:55 -06:00
|
|
|
#define CALLFN(NAME,MAXSIZE) \
|
2014-07-30 11:11:44 -06:00
|
|
|
TEXT NAME(SB), WRAPPER, $MAXSIZE-16; \
|
2014-05-21 15:28:34 -06:00
|
|
|
FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
|
|
|
|
FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
|
2013-08-02 14:03:14 -06:00
|
|
|
/* copy arguments to stack */ \
|
|
|
|
MOVW argptr+4(FP), R0; \
|
|
|
|
MOVW argsize+8(FP), R2; \
|
|
|
|
ADD $4, SP, R1; \
|
|
|
|
CMP $0, R2; \
|
|
|
|
B.EQ 5(PC); \
|
|
|
|
MOVBU.P 1(R0), R5; \
|
|
|
|
MOVBU.P R5, 1(R1); \
|
|
|
|
SUB $1, R2, R2; \
|
|
|
|
B -5(PC); \
|
|
|
|
/* call function */ \
|
|
|
|
MOVW f+0(FP), R7; \
|
|
|
|
MOVW (R7), R0; \
|
2014-05-21 15:28:34 -06:00
|
|
|
PCDATA $PCDATA_StackMapIndex, $0; \
|
2013-08-02 14:03:14 -06:00
|
|
|
BL (R0); \
|
|
|
|
/* copy return values back */ \
|
|
|
|
MOVW argptr+4(FP), R0; \
|
|
|
|
MOVW argsize+8(FP), R2; \
|
reflect, runtime: fix crash in GC due to reflect.call + precise GC
Given
type Outer struct {
*Inner
...
}
the compiler generates the implementation of (*Outer).M dispatching to
the embedded Inner. The implementation is logically:
func (p *Outer) M() {
(p.Inner).M()
}
but since the only change here is the replacement of one pointer
receiver with another, the actual generated code overwrites the
original receiver with the p.Inner pointer and then jumps to the M
method expecting the *Inner receiver.
During reflect.Value.Call, we create an argument frame and the
associated data structures to describe it to the garbage collector,
populate the frame, call reflect.call to run a function call using
that frame, and then copy the results back out of the frame. The
reflect.call function does a memmove of the frame structure onto the
stack (to set up the inputs), runs the call, and the memmoves the
stack back to the frame structure (to preserve the outputs).
Originally reflect.call did not distinguish inputs from outputs: both
memmoves were for the full stack frame. However, in the case where the
called function was one of these wrappers, the rewritten receiver is
almost certainly a different type than the original receiver. This is
not a problem on the stack, where we use the program counter to
determine the type information and understand that during (*Outer).M
the receiver is an *Outer while during (*Inner).M the receiver in the
same memory word is now an *Inner. But in the statically typed
argument frame created by reflect, the receiver is always an *Outer.
Copying the modified receiver pointer off the stack into the frame
will store an *Inner there, and then if a garbage collection happens
to scan that argument frame before it is discarded, it will scan the
*Inner memory as if it were an *Outer. If the two have different
memory layouts, the collection will intepret the memory incorrectly.
Fix by only copying back the results.
Fixes #7725.
LGTM=khr
R=khr
CC=dave, golang-codereviews
https://golang.org/cl/85180043
2014-04-08 09:11:35 -06:00
|
|
|
MOVW retoffset+12(FP), R3; \
|
2013-08-02 14:03:14 -06:00
|
|
|
ADD $4, SP, R1; \
|
reflect, runtime: fix crash in GC due to reflect.call + precise GC
Given
type Outer struct {
*Inner
...
}
the compiler generates the implementation of (*Outer).M dispatching to
the embedded Inner. The implementation is logically:
func (p *Outer) M() {
(p.Inner).M()
}
but since the only change here is the replacement of one pointer
receiver with another, the actual generated code overwrites the
original receiver with the p.Inner pointer and then jumps to the M
method expecting the *Inner receiver.
During reflect.Value.Call, we create an argument frame and the
associated data structures to describe it to the garbage collector,
populate the frame, call reflect.call to run a function call using
that frame, and then copy the results back out of the frame. The
reflect.call function does a memmove of the frame structure onto the
stack (to set up the inputs), runs the call, and the memmoves the
stack back to the frame structure (to preserve the outputs).
Originally reflect.call did not distinguish inputs from outputs: both
memmoves were for the full stack frame. However, in the case where the
called function was one of these wrappers, the rewritten receiver is
almost certainly a different type than the original receiver. This is
not a problem on the stack, where we use the program counter to
determine the type information and understand that during (*Outer).M
the receiver is an *Outer while during (*Inner).M the receiver in the
same memory word is now an *Inner. But in the statically typed
argument frame created by reflect, the receiver is always an *Outer.
Copying the modified receiver pointer off the stack into the frame
will store an *Inner there, and then if a garbage collection happens
to scan that argument frame before it is discarded, it will scan the
*Inner memory as if it were an *Outer. If the two have different
memory layouts, the collection will intepret the memory incorrectly.
Fix by only copying back the results.
Fixes #7725.
LGTM=khr
R=khr
CC=dave, golang-codereviews
https://golang.org/cl/85180043
2014-04-08 09:11:35 -06:00
|
|
|
ADD R3, R1; \
|
|
|
|
ADD R3, R0; \
|
|
|
|
SUB R3, R2; \
|
2013-08-02 14:03:14 -06:00
|
|
|
CMP $0, R2; \
|
|
|
|
RET.EQ ; \
|
|
|
|
MOVBU.P 1(R1), R5; \
|
|
|
|
MOVBU.P R5, 1(R0); \
|
|
|
|
SUB $1, R2, R2; \
|
|
|
|
B -5(PC) \
|
|
|
|
|
2014-07-30 11:11:44 -06:00
|
|
|
CALLFN(runtime·call16, 16)
|
|
|
|
CALLFN(runtime·call32, 32)
|
|
|
|
CALLFN(runtime·call64, 64)
|
|
|
|
CALLFN(runtime·call128, 128)
|
|
|
|
CALLFN(runtime·call256, 256)
|
|
|
|
CALLFN(runtime·call512, 512)
|
|
|
|
CALLFN(runtime·call1024, 1024)
|
|
|
|
CALLFN(runtime·call2048, 2048)
|
|
|
|
CALLFN(runtime·call4096, 4096)
|
|
|
|
CALLFN(runtime·call8192, 8192)
|
|
|
|
CALLFN(runtime·call16384, 16384)
|
|
|
|
CALLFN(runtime·call32768, 32768)
|
|
|
|
CALLFN(runtime·call65536, 65536)
|
|
|
|
CALLFN(runtime·call131072, 131072)
|
|
|
|
CALLFN(runtime·call262144, 262144)
|
|
|
|
CALLFN(runtime·call524288, 524288)
|
|
|
|
CALLFN(runtime·call1048576, 1048576)
|
|
|
|
CALLFN(runtime·call2097152, 2097152)
|
|
|
|
CALLFN(runtime·call4194304, 4194304)
|
|
|
|
CALLFN(runtime·call8388608, 8388608)
|
|
|
|
CALLFN(runtime·call16777216, 16777216)
|
|
|
|
CALLFN(runtime·call33554432, 33554432)
|
|
|
|
CALLFN(runtime·call67108864, 67108864)
|
|
|
|
CALLFN(runtime·call134217728, 134217728)
|
|
|
|
CALLFN(runtime·call268435456, 268435456)
|
|
|
|
CALLFN(runtime·call536870912, 536870912)
|
|
|
|
CALLFN(runtime·call1073741824, 1073741824)
|
2013-08-02 14:03:14 -06:00
|
|
|
|
2009-06-23 12:54:23 -06:00
|
|
|
// Return point when leaving stack.
|
|
|
|
// using frame size $-4 means do not save LR on stack.
|
2013-07-18 14:53:45 -06:00
|
|
|
//
|
|
|
|
// Lessstack can appear in stack traces for the same reason
|
|
|
|
// as morestack; in that context, it has 0 arguments.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·lessstack(SB), NOSPLIT, $-4-0
|
2009-06-23 12:54:23 -06:00
|
|
|
// Save return value in m->cret
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW R0, m_cret(R8)
|
2009-06-23 12:54:23 -06:00
|
|
|
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
// Call oldstack on m->g0's stack.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW m_g0(R8), g
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), SP
|
2013-07-18 14:53:45 -06:00
|
|
|
BL runtime·oldstack(SB)
|
2009-06-16 12:25:58 -06:00
|
|
|
|
2009-06-10 12:53:07 -06:00
|
|
|
// void jmpdefer(fn, sp);
|
|
|
|
// called from deferreturn.
|
2009-10-05 22:52:10 -06:00
|
|
|
// 1. grab stored LR for caller
|
|
|
|
// 2. sub 4 bytes to get back to BL deferreturn
|
|
|
|
// 3. B to fn
|
2014-06-12 14:34:54 -06:00
|
|
|
// TODO(rsc): Push things on stack and then use pop
|
|
|
|
// to load all registers simultaneously, so that a profiling
|
|
|
|
// interrupt can never see mismatched SP/LR/PC.
|
|
|
|
// (And double-check that pop is atomic in that way.)
|
2013-08-07 15:03:50 -06:00
|
|
|
TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
|
2009-10-05 22:52:10 -06:00
|
|
|
MOVW 0(SP), LR
|
|
|
|
MOVW $-4(LR), LR // BL deferreturn
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
MOVW fv+0(FP), R7
|
2011-01-14 12:05:20 -07:00
|
|
|
MOVW argp+4(FP), SP
|
|
|
|
MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR
|
2013-02-22 12:25:50 -07:00
|
|
|
MOVW 0(R7), R1
|
2013-02-21 15:01:13 -07:00
|
|
|
B (R1)
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2013-06-12 13:22:26 -06:00
|
|
|
// Save state of caller into g->sched. Smashes R11.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT gosave<>(SB),NOSPLIT,$0
|
2013-06-12 13:22:26 -06:00
|
|
|
MOVW LR, (g_sched+gobuf_pc)(g)
|
|
|
|
MOVW R13, (g_sched+gobuf_sp)(g)
|
|
|
|
MOVW $0, R11
|
|
|
|
MOVW R11, (g_sched+gobuf_lr)(g)
|
|
|
|
MOVW R11, (g_sched+gobuf_ret)(g)
|
|
|
|
MOVW R11, (g_sched+gobuf_ctxt)(g)
|
2012-05-04 04:20:09 -06:00
|
|
|
RET
|
|
|
|
|
|
|
|
// asmcgocall(void(*fn)(void*), void *arg)
|
|
|
|
// Call fn(arg) on the scheduler stack,
|
|
|
|
// aligned appropriately for the gcc ABI.
|
|
|
|
// See cgocall.c for more details.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW fn+0(FP), R1
|
|
|
|
MOVW arg+4(FP), R0
|
|
|
|
MOVW R13, R2
|
|
|
|
MOVW g, R5
|
|
|
|
|
|
|
|
// Figure out if we need to switch to m->g0 stack.
|
|
|
|
// We get called to create new OS threads too, and those
|
|
|
|
// come in on the m->g0 stack already.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW m_g0(R8), R3
|
2012-05-04 04:20:09 -06:00
|
|
|
CMP R3, g
|
2013-06-12 13:22:26 -06:00
|
|
|
BEQ 4(PC)
|
|
|
|
BL gosave<>(SB)
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW R3, g
|
|
|
|
MOVW (g_sched+gobuf_sp)(g), R13
|
|
|
|
|
|
|
|
// Now on a scheduling stack (a pthread-created stack).
|
|
|
|
SUB $24, R13
|
|
|
|
BIC $0x7, R13 // alignment for gcc ABI
|
|
|
|
MOVW R5, 20(R13) // save old g
|
|
|
|
MOVW R2, 16(R13) // save old SP
|
|
|
|
// R0 already contains the first argument
|
|
|
|
BL (R1)
|
|
|
|
|
|
|
|
// Restore registers, g, stack pointer.
|
|
|
|
MOVW 20(R13), g
|
|
|
|
MOVW 16(R13), R13
|
|
|
|
RET
|
|
|
|
|
|
|
|
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
|
2013-02-22 14:08:56 -07:00
|
|
|
// Turn the fn into a Go func (by taking its address) and call
|
|
|
|
// cgocallback_gofunc.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·cgocallback(SB),NOSPLIT,$12-12
|
2013-02-22 14:08:56 -07:00
|
|
|
MOVW $fn+0(FP), R0
|
|
|
|
MOVW R0, 4(R13)
|
|
|
|
MOVW frame+4(FP), R0
|
|
|
|
MOVW R0, 8(R13)
|
|
|
|
MOVW framesize+8(FP), R0
|
|
|
|
MOVW R0, 12(R13)
|
2013-02-22 14:38:44 -07:00
|
|
|
MOVW $runtime·cgocallback_gofunc(SB), R0
|
2013-02-22 14:08:56 -07:00
|
|
|
BL (R0)
|
|
|
|
RET
|
|
|
|
|
|
|
|
// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
|
2012-05-04 04:20:09 -06:00
|
|
|
// See cgocall.c for more details.
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12
|
2013-02-20 15:48:23 -07:00
|
|
|
// Load m and g from thread-local storage.
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
MOVB runtime·iscgo(SB), R0
|
2013-02-20 15:48:23 -07:00
|
|
|
CMP $0, R0
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
BL.NE runtime·load_g(SB)
|
2013-02-20 15:48:23 -07:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
// If g is nil, Go did not create the current thread.
|
2013-02-20 15:48:23 -07:00
|
|
|
// Call needm to obtain one for temporary use.
|
|
|
|
// In this case, we're running on the thread stack, so there's
|
|
|
|
// lots of space, but the linker doesn't know. Hide the call from
|
|
|
|
// the linker analysis by using an indirect call.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
CMP $0, g
|
2013-08-12 11:36:33 -06:00
|
|
|
B.NE havem
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g, savedm-4(SP) // g is zero, so is m.
|
2013-02-20 15:48:23 -07:00
|
|
|
MOVW $runtime·needm(SB), R0
|
|
|
|
BL (R0)
|
|
|
|
|
|
|
|
havem:
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW R8, savedm-4(SP)
|
2013-02-20 15:48:23 -07:00
|
|
|
// Now there's a valid m, and we're running on its m->g0.
|
|
|
|
// Save current m->g0->sched.sp on stack and then set it to SP.
|
|
|
|
// Save current sp in m->g0->sched.sp in preparation for
|
|
|
|
// switch back to m->curg stack.
|
2013-07-23 16:40:02 -06:00
|
|
|
// NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP).
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW m_g0(R8), R3
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW (g_sched+gobuf_sp)(R3), R4
|
2013-07-23 16:40:02 -06:00
|
|
|
MOVW R4, savedsp-8(SP)
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW R13, (g_sched+gobuf_sp)(R3)
|
|
|
|
|
2013-07-23 16:40:02 -06:00
|
|
|
// Switch to m->curg stack and call runtime.cgocallbackg.
|
|
|
|
// Because we are taking over the execution of m->curg
|
|
|
|
// but *not* resuming what had been running, we need to
|
|
|
|
// save that information (m->curg->sched) so we can restore it.
|
2013-06-05 05:16:53 -06:00
|
|
|
// We can restore m->curg->sched.sp easily, because calling
|
2012-05-04 04:20:09 -06:00
|
|
|
// runtime.cgocallbackg leaves SP unchanged upon return.
|
2013-06-05 05:16:53 -06:00
|
|
|
// To save m->curg->sched.pc, we push it onto the stack.
|
2012-05-04 04:20:09 -06:00
|
|
|
// This has the added benefit that it looks to the traceback
|
|
|
|
// routine like cgocallbackg is going to return to that
|
2013-07-23 16:40:02 -06:00
|
|
|
// PC (because the frame we allocate below has the same
|
|
|
|
// size as cgocallback_gofunc's frame declared above)
|
2012-05-04 04:20:09 -06:00
|
|
|
// so that the traceback will seamlessly trace back into
|
|
|
|
// the earlier calls.
|
2013-07-23 16:40:02 -06:00
|
|
|
//
|
|
|
|
// In the new goroutine, -8(SP) and -4(SP) are unused.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW m_curg(R8), g
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
|
|
|
|
MOVW (g_sched+gobuf_pc)(g), R5
|
2013-07-23 16:40:02 -06:00
|
|
|
MOVW R5, -12(R4)
|
|
|
|
MOVW $-12(R4), R13
|
2012-05-04 04:20:09 -06:00
|
|
|
BL runtime·cgocallbackg(SB)
|
|
|
|
|
2013-06-05 05:16:53 -06:00
|
|
|
// Restore g->sched (== m->curg->sched) from saved values.
|
2013-03-25 15:10:28 -06:00
|
|
|
MOVW 0(R13), R5
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW R5, (g_sched+gobuf_pc)(g)
|
2013-07-23 16:40:02 -06:00
|
|
|
MOVW $12(R13), R4
|
2013-03-25 15:10:28 -06:00
|
|
|
MOVW R4, (g_sched+gobuf_sp)(g)
|
2012-05-04 04:20:09 -06:00
|
|
|
|
|
|
|
// Switch back to m->g0's stack and restore m->g0->sched.sp.
|
|
|
|
// (Unlike m->curg, the g0 goroutine never uses sched.pc,
|
|
|
|
// so we do not have to restore it.)
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW g_m(g), R8
|
|
|
|
MOVW m_g0(R8), g
|
2012-05-04 04:20:09 -06:00
|
|
|
MOVW (g_sched+gobuf_sp)(g), R13
|
2013-07-23 16:40:02 -06:00
|
|
|
MOVW savedsp-8(SP), R4
|
|
|
|
MOVW R4, (g_sched+gobuf_sp)(g)
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
|
2013-02-20 15:48:23 -07:00
|
|
|
// If the m on entry was nil, we called needm above to borrow an m
|
|
|
|
// for the duration of the call. Since the call is over, return it with dropm.
|
2013-07-23 16:40:02 -06:00
|
|
|
MOVW savedm-4(SP), R6
|
2013-02-20 15:48:23 -07:00
|
|
|
CMP $0, R6
|
|
|
|
B.NE 3(PC)
|
|
|
|
MOVW $runtime·dropm(SB), R0
|
|
|
|
BL (R0)
|
|
|
|
|
2012-05-04 04:20:09 -06:00
|
|
|
// Done!
|
|
|
|
RET
|
runtime: scheduler, cgo reorganization
* 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
2011-03-07 08:37:42 -07:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
// void setg(G*); set g. for use by needm.
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
TEXT runtime·setg(SB), NOSPLIT, $0-4
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
MOVW gg+0(FP), g
|
2013-02-20 15:48:23 -07:00
|
|
|
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
// Save g to thread-local storage.
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
MOVB runtime·iscgo(SB), R0
|
2013-02-20 15:48:23 -07:00
|
|
|
CMP $0, R0
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
BL.NE runtime·save_g(SB)
|
2013-02-20 15:48:23 -07:00
|
|
|
|
|
|
|
RET
|
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
|
2009-10-19 22:58:16 -06:00
|
|
|
MOVW 0(SP), R0
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
MOVW R0, ret+4(FP)
|
2009-10-19 22:58:16 -06:00
|
|
|
RET
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2014-06-17 00:03:03 -06:00
|
|
|
TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-4-8
|
2014-06-17 22:59:50 -06:00
|
|
|
MOVW R14, ret+4(FP)
|
2014-06-17 00:03:03 -06:00
|
|
|
RET
|
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·setcallerpc(SB),NOSPLIT,$-4-8
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
MOVW pc+4(FP), R0
|
2009-10-19 22:58:16 -06:00
|
|
|
MOVW R0, 0(SP)
|
|
|
|
RET
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4
|
2010-04-05 13:51:09 -06:00
|
|
|
MOVW 0(FP), R0
|
|
|
|
MOVW $-4(R0), R0
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
MOVW R0, ret+4(FP)
|
2010-04-05 13:51:09 -06:00
|
|
|
RET
|
|
|
|
|
2014-08-26 00:34:46 -06:00
|
|
|
// func gogetcallersp(p unsafe.Pointer) uintptr
|
|
|
|
TEXT runtime·gogetcallersp(SB),NOSPLIT,$-4-8
|
|
|
|
MOVW 0(FP), R0
|
|
|
|
MOVW $-4(R0), R0
|
|
|
|
MOVW R0, ret+4(FP)
|
|
|
|
RET
|
|
|
|
|
2013-07-16 14:24:09 -06:00
|
|
|
TEXT runtime·emptyfunc(SB),0,$0-0
|
2009-06-16 12:25:58 -06:00
|
|
|
RET
|
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·abort(SB),NOSPLIT,$-4-0
|
2009-06-16 12:25:58 -06:00
|
|
|
MOVW $0, R0
|
|
|
|
MOVW (R0), R1
|
2009-06-10 12:53:07 -06:00
|
|
|
|
2011-02-25 12:29:55 -07:00
|
|
|
// bool armcas(int32 *val, int32 old, int32 new)
|
|
|
|
// Atomically:
|
|
|
|
// if(*val == old){
|
|
|
|
// *val = new;
|
|
|
|
// return 1;
|
|
|
|
// }else
|
|
|
|
// return 0;
|
|
|
|
//
|
2012-01-22 11:34:17 -07:00
|
|
|
// To implement runtime·cas in sys_$GOOS_arm.s
|
2011-02-25 12:29:55 -07:00
|
|
|
// using the native instructions, use:
|
|
|
|
//
|
2013-08-07 11:23:24 -06:00
|
|
|
// TEXT runtime·cas(SB),NOSPLIT,$0
|
2011-02-25 12:29:55 -07:00
|
|
|
// B runtime·armcas(SB)
|
|
|
|
//
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·armcas(SB),NOSPLIT,$0-12
|
2011-02-25 12:29:55 -07:00
|
|
|
MOVW valptr+0(FP), R1
|
|
|
|
MOVW old+4(FP), R2
|
|
|
|
MOVW new+8(FP), R3
|
|
|
|
casl:
|
|
|
|
LDREX (R1), R0
|
2013-08-12 11:36:33 -06:00
|
|
|
CMP R0, R2
|
|
|
|
BNE casfail
|
2011-02-25 12:29:55 -07:00
|
|
|
STREX R3, (R1), R0
|
2013-08-12 11:36:33 -06:00
|
|
|
CMP $0, R0
|
|
|
|
BNE casl
|
2011-02-25 12:29:55 -07:00
|
|
|
MOVW $1, R0
|
|
|
|
RET
|
|
|
|
casfail:
|
|
|
|
MOVW $0, R0
|
|
|
|
RET
|
2012-03-15 13:22:30 -06:00
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·stackguard(SB),NOSPLIT,$0-8
|
2012-03-15 15:40:17 -06:00
|
|
|
MOVW R13, R1
|
|
|
|
MOVW g_stackguard(g), R2
|
|
|
|
MOVW R1, sp+0(FP)
|
|
|
|
MOVW R2, limit+4(FP)
|
2012-03-15 13:22:30 -06:00
|
|
|
RET
|
2013-03-12 11:47:44 -06:00
|
|
|
|
2013-04-02 17:26:15 -06:00
|
|
|
// AES hashing not implemented for ARM
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·aeshash(SB),NOSPLIT,$-4-0
|
2013-03-12 11:47:44 -06:00
|
|
|
MOVW $0, R0
|
|
|
|
MOVW (R0), R1
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0
|
2013-03-12 11:47:44 -06:00
|
|
|
MOVW $0, R0
|
|
|
|
MOVW (R0), R1
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0
|
2013-03-12 11:47:44 -06:00
|
|
|
MOVW $0, R0
|
|
|
|
MOVW (R0), R1
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0
|
2013-03-12 11:47:44 -06:00
|
|
|
MOVW $0, R0
|
|
|
|
MOVW (R0), R1
|
2013-04-02 17:26:15 -06:00
|
|
|
|
2014-08-07 15:52:55 -06:00
|
|
|
TEXT runtime·memeq(SB),NOSPLIT,$-4-13
|
2014-07-16 15:16:19 -06:00
|
|
|
MOVW a+0(FP), R1
|
|
|
|
MOVW b+4(FP), R2
|
|
|
|
MOVW size+8(FP), R3
|
|
|
|
ADD R1, R3, R6
|
|
|
|
MOVW $1, R0
|
|
|
|
MOVB R0, ret+12(FP)
|
|
|
|
_next2:
|
|
|
|
CMP R1, R6
|
|
|
|
RET.EQ
|
|
|
|
MOVBU.P 1(R1), R4
|
|
|
|
MOVBU.P 1(R2), R5
|
|
|
|
CMP R4, R5
|
|
|
|
BEQ _next2
|
|
|
|
|
|
|
|
MOVW $0, R0
|
|
|
|
MOVB R0, ret+12(FP)
|
|
|
|
RET
|
|
|
|
|
2014-06-16 22:00:37 -06:00
|
|
|
// eqstring tests whether two strings are equal.
|
|
|
|
// See runtime_test.go:eqstring_generic for
|
2014-08-19 09:50:35 -06:00
|
|
|
// equivalent Go code.
|
2014-06-16 22:00:37 -06:00
|
|
|
TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
|
|
|
|
MOVW s1len+4(FP), R0
|
|
|
|
MOVW s2len+12(FP), R1
|
|
|
|
MOVW $0, R7
|
|
|
|
CMP R0, R1
|
|
|
|
MOVB.NE R7, v+16(FP)
|
|
|
|
RET.NE
|
|
|
|
MOVW s1str+0(FP), R2
|
|
|
|
MOVW s2str+8(FP), R3
|
|
|
|
MOVW $1, R8
|
|
|
|
MOVB R8, v+16(FP)
|
|
|
|
CMP R2, R3
|
|
|
|
RET.EQ
|
|
|
|
ADD R2, R0, R6
|
|
|
|
_eqnext:
|
|
|
|
CMP R2, R6
|
|
|
|
RET.EQ
|
|
|
|
MOVBU.P 1(R2), R4
|
|
|
|
MOVBU.P 1(R3), R5
|
|
|
|
CMP R4, R5
|
|
|
|
BEQ _eqnext
|
|
|
|
MOVB R7, v+16(FP)
|
|
|
|
RET
|
|
|
|
|
2014-06-30 17:10:41 -06:00
|
|
|
// void setg_gcc(G*); set g called from gcc.
|
all: remove 'extern register M *m' from runtime
The runtime has historically held two dedicated values g (current goroutine)
and m (current thread) in 'extern register' slots (TLS on x86, real registers
backed by TLS on ARM).
This CL removes the extern register m; code now uses g->m.
On ARM, this frees up the register that formerly held m (R9).
This is important for NaCl, because NaCl ARM code cannot use R9 at all.
The Go 1 macrobenchmarks (those with per-op times >= 10 µs) are unaffected:
BenchmarkBinaryTree17 5491374955 5471024381 -0.37%
BenchmarkFannkuch11 4357101311 4275174828 -1.88%
BenchmarkGobDecode 11029957 11364184 +3.03%
BenchmarkGobEncode 6852205 6784822 -0.98%
BenchmarkGzip 650795967 650152275 -0.10%
BenchmarkGunzip 140962363 141041670 +0.06%
BenchmarkHTTPClientServer 71581 73081 +2.10%
BenchmarkJSONEncode 31928079 31913356 -0.05%
BenchmarkJSONDecode 117470065 113689916 -3.22%
BenchmarkMandelbrot200 6008923 5998712 -0.17%
BenchmarkGoParse 6310917 6327487 +0.26%
BenchmarkRegexpMatchMedium_1K 114568 114763 +0.17%
BenchmarkRegexpMatchHard_1K 168977 169244 +0.16%
BenchmarkRevcomp 935294971 914060918 -2.27%
BenchmarkTemplate 145917123 148186096 +1.55%
Minux previous reported larger variations, but these were caused by
run-to-run noise, not repeatable slowdowns.
Actual code changes by Minux.
I only did the docs and the benchmarking.
LGTM=dvyukov, iant, minux
R=minux, josharian, iant, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/109050043
2014-06-26 09:54:39 -06:00
|
|
|
TEXT setg_gcc<>(SB),NOSPLIT,$0
|
|
|
|
MOVW R0, g
|
|
|
|
B runtime·save_g(SB)
|
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
2013-08-14 09:38:54 -06:00
|
|
|
|
2013-08-01 17:11:19 -06:00
|
|
|
// TODO: share code with memeq?
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT bytes·Equal(SB),NOSPLIT,$0
|
2013-08-01 17:11:19 -06:00
|
|
|
MOVW a_len+4(FP), R1
|
|
|
|
MOVW b_len+16(FP), R3
|
|
|
|
|
|
|
|
CMP R1, R3 // unequal lengths are not equal
|
|
|
|
B.NE _notequal
|
|
|
|
|
|
|
|
MOVW a+0(FP), R0
|
|
|
|
MOVW b+12(FP), R2
|
|
|
|
ADD R0, R1 // end
|
|
|
|
|
|
|
|
_byteseq_next:
|
|
|
|
CMP R0, R1
|
|
|
|
B.EQ _equal // reached the end
|
|
|
|
MOVBU.P 1(R0), R4
|
|
|
|
MOVBU.P 1(R2), R5
|
|
|
|
CMP R4, R5
|
|
|
|
B.EQ _byteseq_next
|
|
|
|
|
|
|
|
_notequal:
|
|
|
|
MOVW $0, R0
|
|
|
|
MOVBU R0, ret+24(FP)
|
|
|
|
RET
|
|
|
|
|
|
|
|
_equal:
|
|
|
|
MOVW $1, R0
|
|
|
|
MOVBU R0, ret+24(FP)
|
|
|
|
RET
|
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT bytes·IndexByte(SB),NOSPLIT,$0
|
2013-08-01 17:11:19 -06:00
|
|
|
MOVW s+0(FP), R0
|
|
|
|
MOVW s_len+4(FP), R1
|
|
|
|
MOVBU c+12(FP), R2 // byte to find
|
|
|
|
MOVW R0, R4 // store base for later
|
|
|
|
ADD R0, R1 // end
|
|
|
|
|
|
|
|
_loop:
|
|
|
|
CMP R0, R1
|
|
|
|
B.EQ _notfound
|
|
|
|
MOVBU.P 1(R0), R3
|
|
|
|
CMP R2, R3
|
|
|
|
B.NE _loop
|
|
|
|
|
|
|
|
SUB $1, R0 // R0 will be one beyond the position we want
|
|
|
|
SUB R4, R0 // remove base
|
|
|
|
MOVW R0, ret+16(FP)
|
|
|
|
RET
|
|
|
|
|
|
|
|
_notfound:
|
|
|
|
MOVW $-1, R0
|
|
|
|
MOVW R0, ret+16(FP)
|
|
|
|
RET
|
2013-08-05 16:04:05 -06:00
|
|
|
|
2013-08-07 11:23:24 -06:00
|
|
|
TEXT strings·IndexByte(SB),NOSPLIT,$0
|
2013-08-05 16:04:05 -06:00
|
|
|
MOVW s+0(FP), R0
|
|
|
|
MOVW s_len+4(FP), R1
|
|
|
|
MOVBU c+8(FP), R2 // byte to find
|
|
|
|
MOVW R0, R4 // store base for later
|
|
|
|
ADD R0, R1 // end
|
|
|
|
|
|
|
|
_sib_loop:
|
|
|
|
CMP R0, R1
|
|
|
|
B.EQ _sib_notfound
|
|
|
|
MOVBU.P 1(R0), R3
|
|
|
|
CMP R2, R3
|
|
|
|
B.NE _sib_loop
|
|
|
|
|
|
|
|
SUB $1, R0 // R0 will be one beyond the position we want
|
|
|
|
SUB R4, R0 // remove base
|
|
|
|
MOVW R0, ret+12(FP)
|
|
|
|
RET
|
|
|
|
|
|
|
|
_sib_notfound:
|
|
|
|
MOVW $-1, R0
|
|
|
|
MOVW R0, ret+12(FP)
|
|
|
|
RET
|
2014-05-02 10:32:42 -06:00
|
|
|
|
|
|
|
TEXT runtime·timenow(SB), NOSPLIT, $0-0
|
|
|
|
B time·now(SB)
|
2014-05-07 14:17:10 -06:00
|
|
|
|
|
|
|
// A Duff's device for zeroing memory.
|
|
|
|
// The compiler jumps to computed addresses within
|
|
|
|
// this routine to zero chunks of memory. Do not
|
|
|
|
// change this code without also changing the code
|
|
|
|
// in ../../cmd/5g/ggen.c:clearfat.
|
|
|
|
// R0: zero
|
|
|
|
// R1: ptr to memory to be zeroed
|
|
|
|
// R1 is updated as a side effect.
|
|
|
|
TEXT runtime·duffzero(SB), NOSPLIT, $0-0
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
MOVW.P R0, 4(R1)
|
|
|
|
RET
|
|
|
|
|
|
|
|
// A Duff's device for copying memory.
|
|
|
|
// The compiler jumps to computed addresses within
|
|
|
|
// this routine to copy chunks of memory. Source
|
|
|
|
// and destination must not overlap. Do not
|
|
|
|
// change this code without also changing the code
|
|
|
|
// in ../../cmd/5g/cgen.c:sgen.
|
|
|
|
// R0: scratch space
|
|
|
|
// R1: ptr to source memory
|
|
|
|
// R2: ptr to destination memory
|
|
|
|
// R1 and R2 are updated as a side effect
|
|
|
|
TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
MOVW.P 4(R1), R0
|
|
|
|
MOVW.P R0, 4(R2)
|
|
|
|
RET
|
2014-07-16 15:16:19 -06:00
|
|
|
|
|
|
|
TEXT runtime·fastrand2(SB), NOSPLIT, $-4-4
|
|
|
|
MOVW g_m(g), R1
|
|
|
|
MOVW m_fastrand(R1), R0
|
|
|
|
ADD.S R0, R0
|
|
|
|
EOR.MI $0x88888eef, R0
|
|
|
|
MOVW R0, m_fastrand(R1)
|
|
|
|
MOVW R0, ret+0(FP)
|
|
|
|
RET
|
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how
values were returned from functions. This made it difficult to call
Go from C or C from Go if return values were involved. It also made
assembly called from Go and assembly called from C different.
This CL changes the C compiler to use the Go conventions, passing
results on the stack, after the arguments.
[Exception: this does not apply to C ... functions, because you can't
know where on the stack the arguments end.]
By doing this, the CL makes it possible to rewrite C functions into Go
one at a time, without worrying about which languages call that
function or which languages it calls.
This CL also updates all the assembly files in package runtime to use
the new conventions. Argument references of the form 40(SP) have
been rewritten to the form name+10(FP) instead, and there are now
Go func prototypes for every assembly function called from C or Go.
This means that 'go vet runtime' checks effectively every assembly
function, and go vet's output was used to automate the bulk of the
conversion.
Some functions, like seek and nsec on Plan 9, needed to be rewritten.
Many assembly routines called from C were reading arguments
incorrectly, using MOVL instead of MOVQ or vice versa, especially on
the less used systems like openbsd.
These were found by go vet and have been corrected too.
If we're lucky, this may reduce flakiness on those systems.
Tested on:
darwin/386
darwin/amd64
linux/arm
linux/386
linux/amd64
If this breaks another system, the bug is almost certainly in the
sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested
by the combination of the above systems.
LGTM=dvyukov, iant
R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant
CC=golang-codereviews, josharian, r
https://golang.org/cl/135830043
2014-08-27 09:32:17 -06:00
|
|
|
|
|
|
|
TEXT runtime·gocputicks(SB), NOSPLIT, $0
|
|
|
|
B runtime·cputicks(SB)
|
|
|
|
|