gfpurge(pp)
traceProcFree(pp)
if raceenabled {
+ if pp.timerRaceCtx != 0 {
+ // The race detector code uses a callback to fetch
+ // the proc context, so arrange for that callback
+ // to see the right thing.
+ // This hack only works because we are the only
+ // thread running.
+ mp := getg().m
+ phold := mp.p.ptr()
+ mp.p.set(pp)
+
+ racectxend(pp.timerRaceCtx)
+ pp.timerRaceCtx = 0
+
+ mp.p.set(phold)
+ }
raceprocdestroy(pp.raceprocctx)
pp.raceprocctx = 0
}
racecall(&__tsan_go_end, getg().racectx, 0, 0, 0)
}
+//go:nosplit
+func racectxend(racectx uintptr) {
+ racecall(&__tsan_go_end, racectx, 0, 0, 0)
+}
+
//go:nosplit
func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
_g_ := getg()
racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0)
}
+//go:nosplit
+func raceacquirectx(racectx uintptr, addr unsafe.Pointer) {
+ if !isvalidaddr(addr) {
+ return
+ }
+ racecall(&__tsan_acquire, racectx, uintptr(addr), 0, 0)
+}
+
//go:nosplit
func racerelease(addr unsafe.Pointer) {
racereleaseg(getg(), addr)
func racewriterangepc(addr unsafe.Pointer, sz, callerpc, pc uintptr) { throw("race") }
func raceacquire(addr unsafe.Pointer) { throw("race") }
func raceacquireg(gp *g, addr unsafe.Pointer) { throw("race") }
+func raceacquirectx(racectx uintptr, addr unsafe.Pointer) { throw("race") }
func racerelease(addr unsafe.Pointer) { throw("race") }
func racereleaseg(gp *g, addr unsafe.Pointer) { throw("race") }
func racereleasemerge(addr unsafe.Pointer) { throw("race") }
func racefree(p unsafe.Pointer, sz uintptr) { throw("race") }
func racegostart(pc uintptr) uintptr { throw("race"); return 0 }
func racegoend() { throw("race") }
+func racectxend(racectx uintptr) { throw("race") }
// Set g = g0.
get_tls(R12)
MOVQ g(R12), R13
- MOVQ g_m(R13), R13
- MOVQ m_g0(R13), R14
- MOVQ R14, g(R12) // g = m->g0
+ MOVQ g_m(R13), R14
+ MOVQ m_g0(R14), R15
+ CMPQ R13, R15
+ JEQ noswitch // branch if already on g0
+ MOVQ R15, g(R12) // g = m->g0
PUSHQ RARG1 // func arg
PUSHQ RARG0 // func arg
CALL runtime·racecallback(SB)
MOVQ g_m(R13), R13
MOVQ m_curg(R13), R14
MOVQ R14, g(R12) // g = m->curg
+ret:
// Restore callee-saved registers.
POPQ R15
POPQ R14
POPQ BP
POPQ BX
RET
+
+noswitch:
+ // already on g0
+ PUSHQ RARG1 // func arg
+ PUSHQ RARG0 // func arg
+ CALL runtime·racecallback(SB)
+ POPQ R12
+ POPQ R12
+ JMP ret
// restore R0
MOVD R13, R0
MOVD g_m(g), R13
- MOVD m_g0(R13), g
+ MOVD m_g0(R13), R14
+ CMP R14, g
+ BEQ noswitch // branch if already on g0
+ MOVD R14, g
MOVD R0, 8(RSP) // func arg
MOVD R1, 16(RSP) // func arg
// All registers are smashed after Go code, reload.
MOVD g_m(g), R13
MOVD m_curg(R13), g // g = m->curg
+ret:
// Restore callee-saved registers.
MOVD 0(RSP), LR
LDP 24(RSP), (R19, R20)
ADD $112, RSP
JMP (LR)
+noswitch:
+ // already on g0
+ MOVD R0, 8(RSP) // func arg
+ MOVD R1, 16(RSP) // func arg
+ BL runtime·racecallback(SB)
+ JMP ret
+
// tls_g, g value for each thread in TLS
GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
FMOVD F30, 312(R1)
FMOVD F31, 320(R1)
+ MOVD R3, FIXED_FRAME+0(R1)
+ MOVD R4, FIXED_FRAME+8(R1)
+
MOVD runtime·tls_g(SB), R10
MOVD 0(R13)(R10*1), g
MOVD g_m(g), R7
- MOVD m_g0(R7), g // set g = m-> g0
- MOVD R3, FIXED_FRAME+0(R1)
- MOVD R4, FIXED_FRAME+8(R1)
+ MOVD m_g0(R7), R8
+ CMP g, R8
+ BEQ noswitch
+
+ MOVD R8, g // set g = m-> g0
+
BL runtime·racecallback(SB)
+
// All registers are clobbered after Go code, reload.
MOVD runtime·tls_g(SB), R10
MOVD 0(R13)(R10*1), g
MOVD g_m(g), R7
MOVD m_curg(R7), g // restore g = m->curg
+
+ret:
MOVD 328(R1), R14
MOVD 48(R1), R15
MOVD 56(R1), R16
MOVD R10, LR
RET
+noswitch:
+ BL runtime·racecallback(SB)
+ JMP ret
+
// tls_g, g value for each thread in TLS
GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
// such as timerModifying.
adjustTimers uint32
+ // Race context used while executing timer functions.
+ timerRaceCtx uintptr
+
pad cpu.CacheLinePad
}
import (
"internal/cpu"
"runtime/internal/atomic"
+ "runtime/internal/sys"
"unsafe"
)
// runOneTimer runs a single timer.
// The caller must have locked the timers for pp.
func runOneTimer(pp *p, t *timer, now int64) {
+ if raceenabled {
+ if pp.timerRaceCtx == 0 {
+ pp.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
+ }
+ raceacquirectx(pp.timerRaceCtx, unsafe.Pointer(t))
+ }
+
f := t.f
arg := t.arg
seq := t.seq
}
}
+ if raceenabled {
+ // Temporarily use the P's racectx for g0.
+ gp := getg()
+ if gp.racectx != 0 {
+ throw("runOneTimer: unexpected racectx")
+ }
+ gp.racectx = pp.timerRaceCtx
+ }
+
// Note that since timers are locked here, f may not call
// addtimer or resettimer.
f(arg, seq)
+
+ if raceenabled {
+ gp := getg()
+ gp.racectx = 0
+ }
}
func timejump() *p {