aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libc/x86/sys/__vdso_gettc.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2019-02-07 02:56:10 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2019-02-07 02:56:10 +0000
commit5925a983390f74a6b82d376750d24c6d42d6e638 (patch)
treedf02deea92cdd5b017c054647952c63fbbb87df3 /lib/libc/x86/sys/__vdso_gettc.c
parent9088a4751ca2d5eec4f72ac382c9b7d025ca840b (diff)
downloadsrc-5925a983390f74a6b82d376750d24c6d42d6e638.tar.gz
src-5925a983390f74a6b82d376750d24c6d42d6e638.zip
Use ifunc to select the barrier instruction for RDTSC.
This optimizes out runtime switch and removes yet another cpuid from libc. Note that this is the first use of ifunc in i386 libc, so ifunc-capable toolchain is required for building runnable userspace on i386, same as on amd64. Discussed with: emaste Sponsored by: The FreeBSD Foundation MFC after: 1 week
Notes
Notes: svn path=/head/; revision=343855
Diffstat (limited to 'lib/libc/x86/sys/__vdso_gettc.c')
-rw-r--r--lib/libc/x86/sys/__vdso_gettc.c77
1 files changed, 19 insertions, 58 deletions
diff --git a/lib/libc/x86/sys/__vdso_gettc.c b/lib/libc/x86/sys/__vdso_gettc.c
index ef2ca69edf7a..f8ca90bc5746 100644
--- a/lib/libc/x86/sys/__vdso_gettc.c
+++ b/lib/libc/x86/sys/__vdso_gettc.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
- * Copyright (c) 2016, 2017 The FreeBSD Foundation
+ * Copyright (c) 2016, 2017, 2019 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Konstantin Belousov
@@ -50,15 +50,9 @@ __FBSDID("$FreeBSD$");
#ifdef WANT_HYPERV
#include <dev/hyperv/hyperv.h>
#endif
+#include <x86/ifunc.h>
#include "libc_private.h"
-static enum LMB {
- LMB_UNKNOWN,
- LMB_NONE,
- LMB_MFENCE,
- LMB_LFENCE
-} lfence_works = LMB_UNKNOWN;
-
static void
cpuidp(u_int leaf, u_int p[4])
{
@@ -84,68 +78,35 @@ cpuidp(u_int leaf, u_int p[4])
: "0" (leaf));
}
-static enum LMB
-select_lmb(void)
+static void
+rdtsc_mb_lfence(void)
{
- u_int p[4];
- static const char intel_id[] = "GenuntelineI";
- cpuidp(0, p);
- return (memcmp(p + 1, intel_id, sizeof(intel_id) - 1) == 0 ?
- LMB_LFENCE : LMB_MFENCE);
+ lfence();
}
static void
-init_fence(void)
+rdtsc_mb_mfence(void)
{
-#if defined(__i386__)
- u_int cpuid_supported, p[4];
- lfence_works = LMB_NONE;
- __asm __volatile(
- " pushfl\n"
- " popl %%eax\n"
- " movl %%eax,%%ecx\n"
- " xorl $0x200000,%%eax\n"
- " pushl %%eax\n"
- " popfl\n"
- " pushfl\n"
- " popl %%eax\n"
- " xorl %%eax,%%ecx\n"
- " je 1f\n"
- " movl $1,%0\n"
- " jmp 2f\n"
- "1: movl $0,%0\n"
- "2:\n"
- : "=r" (cpuid_supported) : : "eax", "ecx", "cc");
- if (cpuid_supported) {
- cpuidp(0x1, p);
- if ((p[3] & CPUID_SSE2) != 0)
- lfence_works = select_lmb();
- }
-#elif defined(__amd64__)
- lfence_works = select_lmb();
-#else
-#error "Arch"
-#endif
+ mfence();
}
static void
-rdtsc_mb(void)
+rdtsc_mb_none(void)
{
+}
-again:
- if (__predict_true(lfence_works == LMB_LFENCE)) {
- lfence();
- return;
- } else if (lfence_works == LMB_MFENCE) {
- mfence();
- return;
- } else if (lfence_works == LMB_NONE) {
- return;
- }
- init_fence();
- goto again;
+DEFINE_UIFUNC(static, void, rdtsc_mb, (void), static)
+{
+ u_int p[4];
+ static const char intel_id[] = "GenuntelineI";
+
+ if ((cpu_feature & CPUID_SSE2) == 0)
+ return (rdtsc_mb_none);
+ cpuidp(0, p);
+ return (memcmp(p + 1, intel_id, sizeof(intel_id) - 1) == 0 ?
+ rdtsc_mb_lfence : rdtsc_mb_mfence);
}
static u_int