From: Russ Cox Date: Fri, 2 Aug 2013 00:07:01 +0000 (-0400) Subject: runtime: disable preemption during software fp routines X-Git-Tag: go1.2rc2~824 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e03dd0798163b267d8db6b4d2c95dc281be5a064;p=gostls13.git 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 --- diff --git a/src/pkg/runtime/vlop_arm.s b/src/pkg/runtime/vlop_arm.s index cd56898dc6..e58cee446a 100644 --- a/src/pkg/runtime/vlop_arm.s +++ b/src/pkg/runtime/vlop_arm.s @@ -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