106 lines
2.7 KiB
ArmAsm
106 lines
2.7 KiB
ArmAsm
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Adapted from code in the Go runtime package at Go 1.16.6:
|
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build go1.16
|
|
// +build !go1.17
|
|
|
|
#include "go_asm.h"
|
|
#include "textflag.h"
|
|
|
|
#define get_tls(r) MOVQ TLS, r
|
|
#define g(r) 0(r)(TLS*1)
|
|
|
|
#define SYS_clock_gettime 228
|
|
|
|
// Hard-coded offsets into runtime structs.
|
|
// Generated by adding the following code
|
|
// to package runtime and then executing
|
|
// and empty func main:
|
|
//
|
|
// func init() {
|
|
// println("#define g_m", unsafe.Offsetof(g{}.m))
|
|
// println("#define g_sched", unsafe.Offsetof(g{}.sched))
|
|
// println("#define gobuf_sp", unsafe.Offsetof(g{}.sched.sp))
|
|
// println("#define m_g0", unsafe.Offsetof(m{}.g0))
|
|
// println("#define m_curg", unsafe.Offsetof(m{}.curg))
|
|
// println("#define m_vdsoSP", unsafe.Offsetof(m{}.vdsoSP))
|
|
// println("#define m_vdsoPC", unsafe.Offsetof(m{}.vdsoPC))
|
|
// }
|
|
|
|
#define g_m 48
|
|
#define g_sched 56
|
|
#define gobuf_sp 0
|
|
#define m_g0 0
|
|
#define m_curg 192
|
|
#define m_vdsoSP 832
|
|
#define m_vdsoPC 840
|
|
|
|
#define CLOCK_MONOTONIC_COARSE 6
|
|
|
|
// func MonotonicCoarse() int64
|
|
TEXT ·MonotonicCoarse(SB),NOSPLIT,$16-8
|
|
// Switch to g0 stack.
|
|
|
|
MOVQ SP, R12 // Save old SP; R12 unchanged by C code.
|
|
|
|
get_tls(CX)
|
|
MOVQ g(CX), AX
|
|
MOVQ g_m(AX), BX // BX unchanged by C code.
|
|
|
|
// Set vdsoPC and vdsoSP for SIGPROF traceback.
|
|
// Save the old values on stack and restore them on exit,
|
|
// so this function is reentrant.
|
|
MOVQ m_vdsoPC(BX), CX
|
|
MOVQ m_vdsoSP(BX), DX
|
|
MOVQ CX, 0(SP)
|
|
MOVQ DX, 8(SP)
|
|
|
|
LEAQ ret+0(FP), DX
|
|
MOVQ -8(DX), CX
|
|
MOVQ CX, m_vdsoPC(BX)
|
|
MOVQ DX, m_vdsoSP(BX)
|
|
|
|
CMPQ AX, m_curg(BX) // Only switch if on curg.
|
|
JNE noswitch
|
|
|
|
MOVQ m_g0(BX), DX
|
|
MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
|
|
|
|
noswitch:
|
|
SUBQ $16, SP // Space for results
|
|
ANDQ $~15, SP // Align for C code
|
|
|
|
MOVL $CLOCK_MONOTONIC_COARSE, DI
|
|
LEAQ 0(SP), SI
|
|
MOVQ runtime·vdsoClockgettimeSym(SB), AX
|
|
CMPQ AX, $0
|
|
JEQ fallback
|
|
CALL AX
|
|
ret:
|
|
MOVQ 0(SP), AX // sec
|
|
MOVQ 8(SP), DX // nsec
|
|
MOVQ R12, SP // Restore real SP
|
|
// Restore vdsoPC, vdsoSP
|
|
// We don't worry about being signaled between the two stores.
|
|
// If we are not in a signal handler, we'll restore vdsoSP to 0,
|
|
// and no one will care about vdsoPC. If we are in a signal handler,
|
|
// we cannot receive another signal.
|
|
MOVQ 8(SP), CX
|
|
MOVQ CX, m_vdsoSP(BX)
|
|
MOVQ 0(SP), CX
|
|
MOVQ CX, m_vdsoPC(BX)
|
|
// sec is in AX; return it
|
|
MOVQ AX, ret+0(FP)
|
|
RET
|
|
fallback:
|
|
MOVQ $SYS_clock_gettime, AX
|
|
SYSCALL
|
|
JMP ret
|