[vlc-commits] [Git][videolan/vlc][master] 7 commits: linux: detect <sys/auxv.h>
Rémi Denis-Courmont (@Courmisch)
gitlab at videolan.org
Thu Feb 24 01:35:14 UTC 2022
Rémi Denis-Courmont pushed to branch master at VideoLAN / VLC
Commits:
b2a48016 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: detect <sys/auxv.h>
This is necessary for Linux-specific getauxval() and associated flags.
In this case, VLC needs AT_HWCAP (and probably AT_HWCAP2 going forward)
to detect CPU features on most architectures.
- - - - -
ea93bcb8 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
compat: Linux getauxval() replacement
This was added over a decade ago, but 🤷...
- - - - -
f383f00f by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: use getauxval() for AArch64 CPU detection
- - - - -
4aea7124 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: use getauxval() for AArch32 CPU detection
- - - - -
e75a33e4 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: use getauxval() for POWER CPU detection
- - - - -
d7b1f8e2 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: use getauxval() for RISC-V CPU detection
- - - - -
13ab2516 by Rémi Denis-Courmont at 2022-02-23T21:10:16+00:00
linux: simplify CPU detection macros
Only x86 still uses the flaky procfs parsing.
- - - - -
4 changed files:
- + compat/getauxval.c
- configure.ac
- include/vlc_fixups.h
- src/linux/cpu.c
Changes:
=====================================
compat/getauxval.c
=====================================
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * getauxval.c: Linux getauxval() replacement
+ *****************************************************************************
+ * Copyright © 2022 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+extern char **environ;
+
+unsigned long getauxval(unsigned long type)
+{
+ const unsigned long *auxv;
+ size_t i = 0;
+
+ while (environ[i++] != NULL);
+
+ auxv = (const void *)&environ[i];
+
+ for (i = 0; auxv[i]; i += 2)
+ if (auxv[i] == type)
+ return auxv[i + 1];
+
+ return 0;
+}
=====================================
configure.ac
=====================================
@@ -734,6 +734,7 @@ dnl Check for non-standard system calls
case "$SYS" in
"linux")
AC_CHECK_FUNCS([eventfd vmsplice sched_getaffinity recvmmsg memfd_create])
+ AC_REPLACE_FUNCS([getauxval])
;;
"mingw32")
AC_CHECK_FUNCS([_lock_file])
@@ -965,7 +966,7 @@ dnl BSD
AC_CHECK_HEADERS([netinet/tcp.h netinet/udplite.h sys/param.h sys/mount.h])
dnl GNU/Linux
-AC_CHECK_HEADERS([features.h getopt.h linux/dccp.h linux/magic.h sys/eventfd.h])
+AC_CHECK_HEADERS([features.h getopt.h linux/dccp.h linux/magic.h sys/auxv.h sys/eventfd.h])
dnl MacOS
AC_CHECK_HEADERS([xlocale.h])
=====================================
include/vlc_fixups.h
=====================================
@@ -503,6 +503,11 @@ void *lfind( const void *key, const void *base, size_t *nmemb,
void tdestroy( void *root, void (*free_node)(void *nodep) );
#endif
+/* sys/auxv.h */
+#ifndef HAVE_GETAUXVAL
+unsigned long getauxval(unsigned long);
+#endif
+
/* Random numbers */
#ifndef HAVE_NRAND48
double erand48 (unsigned short subi[3]);
=====================================
src/linux/cpu.c
=====================================
@@ -24,82 +24,79 @@
#include <stdio.h>
#include <string.h>
+#ifdef HAVE_SYS_AUXV_H
+# include <sys/auxv.h>
+#endif
+#ifndef AT_HWCAP /* ancient libc, fallback to kernel header */
+# include <linux/auxvec.h>
+#endif
#include <vlc_common.h>
#include <vlc_cpu.h>
-#undef CPU_FLAGS
-#if defined (__arm__) || defined (__aarch64__)
-# define CPU_FLAGS "Features"
-
-#elif defined (__i386__) || defined (__x86_64__)
-# define CPU_FLAGS "flags"
-
-#elif defined (__powerpc__) || defined (__powerpc64__)
-# define CPU_FLAGS "cpu"
-
-#elif defined (__riscv)
-# include <vlc_strings.h>
-# define CPU_FLAGS "isa"
-
-static unsigned vlc_CPU_RV_isa_parse(const char *isa)
+#if defined (__aarch64__)
+unsigned vlc_CPU_raw(void)
{
- unsigned caps = 0;
- int c;
-
- if (vlc_ascii_tolower((unsigned char)isa[0]) != 'r'
- || vlc_ascii_tolower((unsigned char)isa[1]) != 'v')
- return 0;
-
- isa += 2;
-
- if (strncmp(isa, "32", 2) == 0 || strncmp(isa, "64", 2) == 0)
- isa += 2;
- else if (strncmp(isa, "128", 3) == 0)
- isa += 3;
- else
- return 0;
-
- while ((c = vlc_ascii_tolower((unsigned char)*isa)) != '\0') {
- size_t extlen = 1;
+ unsigned int flags = 0;
+ const unsigned long hwcap = getauxval(AT_HWCAP);
+ //const unsigned long hwcap2 = getauxval(AT_HWCAP2); // TODO: SVE2
+
+ /* HWCAP_FP (HAVE_FPU) is statically assumed. */
+# ifdef HWCAP_ASIMD
+ if (hwcap & HWCAP_ASIMD)
+ flags |= VLC_CPU_ARM_NEON;
+# endif
+# ifdef HWCAP_SVE
+ if (hwcap & HWCAP_SVE)
+ flags |= VLC_CPU_ARM_SVE;
+# endif
+ return flags;
+}
- switch (c) {
- case '_':
- break;
+#elif defined (__arm__)
+/* On AArch32, glibc's <bits/hwcap.h> uses different HWCAP names than the
+ * kernel and other libc's. Include the kernel header manually. */
+# include <asm/hwcap.h>
- case 'z':
- case 's':
- case 'h':
- case 'x':
- extlen = 1 + strcspn(isa + 1, "_");
- break;
+unsigned vlc_CPU_raw(void)
+{
+ unsigned int flags = 0;
+ const unsigned long hwcap = getauxval(AT_HWCAP);
+
+ /* TLS implies ARMv6, Thumb-EE and VFP imply ARMv7 */
+ if (hwcap & (HWCAP_TLS|HWCAP_THUMBEE|HWCAP_VFP))
+ flags |= VLC_CPU_ARMv6; /* SIMD */
+ if (hwcap & HWCAP_NEON)
+ flags |= VLC_CPU_ARM_NEON; /* Advanced SIMD */
+ return flags;
+}
- default:
- if (((unsigned)(c - 'a')) > 'y')
- return 0;
+#elif defined (__powerpc__) /* both 32- and 64-bit */
+unsigned vlc_CPU_raw(void)
+{
+ const unsigned long hwcap = getauxval(AT_HWCAP);
+ unsigned int flags = 0;
- while (isa[extlen] && ((unsigned)(isa[extlen] - '0')) < 10)
- extlen++;
+ if (hwcap & PPC_FEATURE_HAS_ALTIVEC)
+ flags |= VLC_CPU_ALTIVEC;
- if (vlc_ascii_tolower(isa[extlen]) == 'p') {
- extlen++;
+ return flags;
+}
- while (isa[extlen] && ((unsigned)(isa[extlen] - '0')) < 10)
- extlen++;
- }
- }
+#elif defined (__riscv)
+# define HWCAP_RV(letter) (1LU << ((letter) - 'A'))
- /* TODO: Zve extensions */
- if (c == 'v')
- caps |= VLC_CPU_RV_V;
+unsigned vlc_CPU_raw(void)
+{
+ const unsigned long hwcap = getauxval(AT_HWCAP);
+ unsigned int flags = 0;
- isa += extlen;
- }
+ if (hwcap & HWCAP_RV('V'))
+ flags |= VLC_CPU_RV_V;
- return caps;
+ return flags;
}
-#endif
-#ifdef CPU_FLAGS
+#elif defined (__i386__) || defined (__x86_64__)
unsigned vlc_CPU_raw(void)
{
FILE *info = fopen ("/proc/cpuinfo", "rte");
@@ -115,34 +112,16 @@ unsigned vlc_CPU_raw(void)
char *p, *cap;
uint_fast32_t core_caps = 0;
-#if defined (__arm__)
- unsigned ver;
- if (sscanf (line, "Processor\t: ARMv%u", &ver) >= 1 && ver >= 6)
- core_caps |= VLC_CPU_ARMv6;
-#endif
- if (strncmp (line, CPU_FLAGS, strlen (CPU_FLAGS)))
+ if (strncmp(line, "flags", 5))
continue;
- p = line + strlen(CPU_FLAGS);
+ p = line + 5;
p += strspn(p, "\t");
if (*p != ':')
continue;
-#if defined (__riscv)
- p += strspn(p, "\t ");
- core_caps = vlc_CPU_RV_isa_parse(p);
-#else
while ((cap = strsep (&p, " ")) != NULL)
{
-#if defined (__arm__) || defined (__aarch64__)
- if (!strcmp (cap, "neon"))
- core_caps |= VLC_CPU_ARM_NEON;
-# if defined (__aarch64__)
- if (!strcmp (cap, "sve"))
- core_caps |= VLC_CPU_ARM_SVE;
-# endif
-
-#elif defined (__i386__) || defined (__x86_64__)
if (!strcmp (cap, "mmx"))
core_caps |= VLC_CPU_MMX;
if (!strcmp (cap, "sse"))
@@ -169,13 +148,7 @@ unsigned vlc_CPU_raw(void)
core_caps |= VLC_CPU_XOP;
if (!strcmp (cap, "fma4"))
core_caps |= VLC_CPU_FMA4;
-
-#elif defined (__powerpc__) || defined (__powerpc64__)
- if (!strcmp (cap, "altivec supported"))
- core_caps |= VLC_CPU_ALTIVEC;
-#endif
}
-#endif
/* Take the intersection of capabilities of each processor */
all_caps &= core_caps;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1cd55cbad268ea90db8028c759fa046c4ffe0800...13ab251675dfa32269ffa47adb809315a76388e5
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1cd55cbad268ea90db8028c759fa046c4ffe0800...13ab251675dfa32269ffa47adb809315a76388e5
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list