1
0
mirror of https://github.com/golang/go synced 2024-11-25 14:07:56 -07:00

runtime: disable preemption during software fp routines

It's okay to preempt at ordinary function calls because
compilers arrange that there are no live registers to save
on entry to the function call.

The software floating point routines are function calls
masquerading as individual machine instructions. They are
expected to keep all the registers intact. In particular,
they are expected not to clobber all the floating point
registers.

The floating point registers are kept per-M, because they
are not live at non-preemptive goroutine scheduling events,
and so keeping them per-M reduces the number of 132-byte
register blocks we are keeping in memory.

Because they are per-M, allowing the goroutine to be
rescheduled during software floating point simulation
would mean some other goroutine could overwrite the registers
or perhaps the goroutine would continue running on a different
M entirely.

Disallow preemption during the software floating point
routines to make sure that a function full of floating point
instructions has the same floating point registers throughout
its execution.

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/12298043
This commit is contained in:
Russ Cox 2013-08-01 20:07:01 -04:00
parent e2a1bd68b3
commit e03dd07981

View File

@ -23,6 +23,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "zasm_GOOS_GOARCH.h"
arg=0
/* replaced use of R10 by R11 because the former can be the data segment base register */
@ -54,7 +56,28 @@ TEXT _sfloat(SB), 7, $64-0 // 4 arg + 14*4 saved regs + cpsr
MOVW R1, 60(R13)
WORD $0xe10f1000 // mrs r1, cpsr
MOVW R1, 64(R13)
// Disable preemption of this goroutine during _sfloat2 by
// m->locks++ and m->locks-- around the call.
// Rescheduling this goroutine may cause the loss of the
// contents of the software floating point registers in
// m->freghi, m->freglo, m->fflag, if the goroutine is moved
// to a different m or another goroutine runs on this m.
// Rescheduling at ordinary function calls is okay because
// all registers are caller save, but _sfloat2 and the things
// that it runs are simulating the execution of individual
// program instructions, and those instructions do not expect
// the floating point registers to be lost.
// An alternative would be to move the software floating point
// registers into G, but they do not need to be kept at the
// usual places a goroutine reschedules (at function calls),
// so it would be a waste of 132 bytes per G.
MOVW m_locks(m), R1
ADD $1, R1
MOVW R1, m_locks(m)
BL runtime·_sfloat2(SB)
MOVW m_locks(m), R1
SUB $1, R1
MOVW R1, m_locks(m)
MOVW R0, 0(R13)
MOVW 64(R13), R1
WORD $0xe128f001 // msr cpsr_f, r1