From ece954d8b8e13a76de891c8078c27c5e7f884f9f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Jan 2021 11:06:04 -0500 Subject: [PATCH] runtime: find g in Windows profiler using SP The architecture-specific interpretation of m->tls[0] is unnecessary and fragile. Delete it. This CL is part of a stack adding windows/arm64 support (#36439), intended to land in the Go 1.17 cycle. This CL is, however, not windows/arm64-specific. It is cleanup meant to make the port (and future ports) easier. Change-Id: I927345e52fa2f1741d4914478a29d1fb8acb0dc3 Reviewed-on: https://go-review.googlesource.com/c/go/+/288806 Trust: Russ Cox Trust: Jason A. Donenfeld Reviewed-by: Jason A. Donenfeld Reviewed-by: Cherry Zhang --- src/runtime/os_windows.go | 22 +++++++++++----------- src/runtime/sys_windows_arm.s | 34 ---------------------------------- 2 files changed, 11 insertions(+), 45 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index a2a124cd9d..a8406460e2 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -1132,21 +1132,21 @@ func profilem(mp *m, thread uintptr) { c.contextflags = _CONTEXT_CONTROL stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(c))) - gp := gFromTLS(mp) + gp := gFromSP(mp, c.sp()) sigprof(c.ip(), c.sp(), c.lr(), gp, mp) } -func gFromTLS(mp *m) *g { - switch GOARCH { - case "arm": - tls := &mp.tls[0] - return **((***g)(unsafe.Pointer(tls))) - case "386", "amd64": - tls := &mp.tls[0] - return *((**g)(unsafe.Pointer(tls))) +func gFromSP(mp *m, sp uintptr) *g { + if gp := mp.g0; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { + return gp + } + if gp := mp.gsignal; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { + return gp + } + if gp := mp.curg; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { + return gp } - throw("unsupported architecture") return nil } @@ -1295,7 +1295,7 @@ func preemptM(mp *m) { unlock(&suspendLock) // Does it want a preemption and is it safe to preempt? - gp := gFromTLS(mp) + gp := gFromSP(mp, c.sp()) if wantAsyncPreempt(gp) { if ok, newpc := isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()); ok { // Inject call to asyncPreempt diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s index a55f474d39..a30d63513a 100644 --- a/src/runtime/sys_windows_arm.s +++ b/src/runtime/sys_windows_arm.s @@ -350,9 +350,6 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0 MOVW R0, g_m(g) BL runtime·save_g(SB) - // do per-thread TLS initialization - BL init_thread_tls<>(SB) - // Layout new m scheduler stack on os stack. MOVW R13, R0 MOVW R0, g_stack+stack_hi(g) @@ -581,39 +578,8 @@ TEXT runtime·_initcgo(SB),NOSPLIT|NOFRAME,$0 MOVW $runtime·tls_g(SB), R1 MOVW R0, (R1) - BL init_thread_tls<>(SB) - MOVW R4, R13 MOVM.IA.W (R13), [R4, R15] // pop {r4, pc} -// void init_thread_tls() -// -// Does per-thread TLS initialization. Saves a pointer to the TLS slot -// holding G, in the current m. -// -// g->m->tls[0] = &_TEB->TlsSlots[tls_g] -// -// The purpose of this is to enable the profiling handler to get the -// current g associated with the thread. We cannot use m->curg because curg -// only holds the current user g. If the thread is executing system code or -// external code, m->curg will be NULL. The thread's TLS slot always holds -// the current g, so save a reference to this location so the profiling -// handler can get the real g from the thread's m. -// -// Clobbers R0-R3 -TEXT init_thread_tls<>(SB),NOSPLIT|NOFRAME,$0 - // compute &_TEB->TlsSlots[tls_g] - MRC 15, 0, R0, C13, C0, 2 - ADD $0xe10, R0 - MOVW $runtime·tls_g(SB), R1 - MOVW (R1), R1 - MOVW R1<<2, R1 - ADD R1, R0 - - // save in g->m->tls[0] - MOVW g_m(g), R1 - MOVW R0, m_tls(R1) - RET - // Holds the TLS Slot, which was allocated by TlsAlloc() GLOBL runtime·tls_g+0(SB), NOPTR, $4 -- 2.48.1