svn commit: r343855 - head/lib/libc/x86/sys
Konstantin Belousov
kib at FreeBSD.org
Thu Feb 7 02:56:11 UTC 2019
Author: kib
Date: Thu Feb 7 02:56:10 2019
New Revision: 343855
URL: https://svnweb.freebsd.org/changeset/base/343855
Log:
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
Modified:
head/lib/libc/x86/sys/__vdso_gettc.c
Modified: head/lib/libc/x86/sys/__vdso_gettc.c
==============================================================================
--- head/lib/libc/x86/sys/__vdso_gettc.c Thu Feb 7 02:36:59 2019 (r343854)
+++ head/lib/libc/x86/sys/__vdso_gettc.c Thu Feb 7 02:56:10 2019 (r343855)
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2012 Konstantin Belousov <kib at 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
More information about the svn-src-all
mailing list