]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: disable preemption during software fp routines
authorRuss Cox <rsc@golang.org>
Fri, 2 Aug 2013 00:07:01 +0000 (20:07 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 2 Aug 2013 00:07:01 +0000 (20:07 -0400)
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

src/pkg/runtime/vlop_arm.s

index cd56898dc6da0cd95344376b829f72263aef4d41..e58cee446a9b8af83cf968b25463938a37ecbf07 100644 (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