[vlc-commits] Linux: parse /proc/cpuinfo instead of playing fork tricks
Rémi Denis-Courmont
git at videolan.org
Fri Feb 3 17:44:38 CET 2012
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Fri Feb 3 18:36:04 2012 +0200| [5c35f9d1ff19be0ccd1229d2195e36bfa667454e] | committer: Rémi Denis-Courmont
Linux: parse /proc/cpuinfo instead of playing fork tricks
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5c35f9d1ff19be0ccd1229d2195e36bfa667454e
---
src/Makefile.am | 1 +
src/misc/cpu.c | 47 ++------------
src/posix/linux_cpu.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 176 insertions(+), 42 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 6dc3384..492dcde 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -254,6 +254,7 @@ SOURCES_libvlc_linux = \
posix/filesystem.c \
posix/plugin.c \
posix/thread.c \
+ posix/linux_cpu.c \
posix/linux_specific.c \
posix/rand.c \
$(NULL)
diff --git a/src/misc/cpu.c b/src/misc/cpu.c
index 7c28b25..d4e762c 100644
--- a/src/misc/cpu.c
+++ b/src/misc/cpu.c
@@ -32,7 +32,11 @@
#include <vlc_common.h>
#include <vlc_cpu.h>
+#include "libvlc.h"
+
+#include <assert.h>
+#ifndef __linux__
#include <sys/types.h>
#ifndef WIN32
#include <unistd.h>
@@ -41,14 +45,11 @@
#else
#include <errno.h>
#endif
-#include <assert.h>
#ifdef __APPLE__
#include <sys/sysctl.h>
#endif
-#include "libvlc.h"
-
static uint32_t cpu_flags;
#if defined (__i386__) || defined (__x86_64__) || defined (__powerpc__) \
@@ -284,45 +285,6 @@ void vlc_CPU_init (void)
}
out:
-#elif defined (__arm__)
-
-# if defined (__ARM_NEON__)
- i_capabilities |= CPU_CAPABILITY_NEON;
-# elif defined (CAN_COMPILE_NEON)
-# define NEED_RUNTIME_CPU_CHECK 1
-# endif
-
-# ifdef NEED_RUNTIME_CPU_CHECK
-# if defined (__linux__)
- FILE *info = fopen ("/proc/cpuinfo", "rt");
- if (info != NULL)
- {
- char *line = NULL;
- size_t linelen = 0;
-
- while (getline (&line, &linelen, info) != -1)
- {
- const char *cap;
-
- if (strncmp (line, "Features\t:", 10))
- continue;
-
- /* TODO: detect other CPU features when we use them */
-# if defined (CAN_COMPILE_NEON) && !defined (__ARM_NEON__)
- cap = strstr (line + 10, " neon");
- if (cap != NULL && (cap[5] == '\0' || cap[5] == ' '))
- i_capabilities |= CPU_CAPABILITY_NEON;
-# endif
- break;
- }
- fclose (info);
- free (line);
- }
-# else
-# warning Run-time CPU detection missing: optimizations disabled!
-# endif
-# endif
-
#elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __powerpc64__ ) \
|| defined( __ppc64__ )
@@ -363,6 +325,7 @@ unsigned vlc_CPU (void)
#endif
return cpu_flags;
}
+#endif
void vlc_CPU_dump (vlc_object_t *obj)
{
diff --git a/src/posix/linux_cpu.c b/src/posix/linux_cpu.c
new file mode 100644
index 0000000..63f184e
--- /dev/null
+++ b/src/posix/linux_cpu.c
@@ -0,0 +1,170 @@
+/*****************************************************************************
+ * linux_cpu.c: CPU detection code for Linux
+ *****************************************************************************
+ * Copyright (C) 2012 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 <stdio.h>
+#include <string.h>
+#include <vlc_common.h>
+#include <vlc_cpu.h>
+
+#undef CPU_FLAGS
+#if defined (__arm__)
+# define CPU_FLAGS "Features\t:"
+
+#elif defined (__i386__) || defined (__x86_64__)
+# define CPU_FLAGS "flags\t\t:"
+
+#elif defined (__powerpc__) || defined (__powerpc64__)
+# define CPU_FLAGS "cpu\t\t:"
+
+#endif
+
+#ifdef CPU_FLAGS
+static uint32_t cpu_flags = 0;
+
+static void vlc_CPU_init (void)
+{
+ FILE *info = fopen ("/proc/cpuinfo", "rt");
+ if (info == NULL)
+ return;
+
+ char *line = NULL;
+ size_t linelen = 0;
+ uint_fast32_t all_caps = 0xFFFFFFFF;
+
+ while (getline (&line, &linelen, info) != -1)
+ {
+ if (strncmp (line, CPU_FLAGS, strlen (CPU_FLAGS)))
+ continue;
+
+ char *p = line, *cap;
+ uint_fast32_t core_caps = 0;
+
+ while ((cap = strsep (&p, " ")) != NULL)
+ {
+#if defined (__arm__)
+# ifndef __ARM_NEON__
+ if (!strcmp (cap, "neon"))
+ core_caps |= CPU_CAPABILITY_NEON;
+# endif
+
+#elif defined (__i386__) || defined (__x86_64__)
+# ifndef __MMX__
+ if (!strcmp (cap, "mmx"))
+ core_caps |= CPU_CAPABILITY_MMX;
+# endif
+# ifndef __SSE__
+ if (!strcmp (cap, "sse"))
+ core_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
+ if (!strcmp (cap, "mmxext"))
+ core_caps |= CPU_CAPABILITY_MMXEXT;
+# endif
+# ifndef __SSE2__
+ if (!strcmp (cap, "sse2"))
+ core_caps |= CPU_CAPABILITY_SSE2;
+# endif
+# ifndef __SSE3__
+ if (!strcmp (cap, "pni"))
+ core_caps |= CPU_CAPABILITY_SSE3;
+# endif
+# ifndef __SSSE3__
+ if (!strcmp (cap, "ssse3"))
+ core_caps |= CPU_CAPABILITY_SSSE3;
+# endif
+# ifndef __SSE4_1__
+ if (!strcmp (cap, "sse4_1"))
+ core_caps |= CPU_CAPABILITY_SSE4_1;
+# endif
+# ifndef __SSE4_2__
+ if (!strcmp (cap, "sse4_2"))
+ core_caps |= CPU_CAPABILITY_SSE4_1;
+# endif
+# ifndef __3dNOW__
+ if (!strcmp (cap, "3dnow"))
+ core_caps |= CPU_CAPABILITY_3DNOW;
+# endif
+
+#elif defined (__powerpc__) || defined (__powerpc64__)
+ if (!strcmp (cap, "altivec supported"))
+ core_caps |= CPU_CAPABILITY_ALTIVEC;
+#endif
+ }
+
+ /* Take the intersection of capabilities of each processor */
+ all_caps &= core_caps;
+ }
+ fclose (info);
+ free (line);
+
+ if (all_caps == 0xFFFFFFFF) /* Error parsing of cpuinfo? */
+ all_caps = 0; /* Do not assume any capability! */
+
+ /* Always enable capabilities that were forced during compilation */
+#if defined (__arm__)
+# ifdef __ARM_NEON__
+ all_caps |= CPU_CAPABILITY_NEON;
+# endif
+
+#elif defined (__i386__) || defined (__x86_64__)
+# ifdef __MMX__
+ all_caps |= CPU_CAPABILITY_MMX;
+# endif
+# ifdef __SSE__
+ all_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
+# endif
+# ifdef __SSE2__
+ all_caps |= CPU_CAPABILITY_SSE2;
+# endif
+# ifdef __SSE3__
+ all_caps |= CPU_CAPABILITY_SSE3;
+# endif
+# ifdef __SSSE3__
+ all_caps |= CPU_CAPABILITY_SSSE3;
+# endif
+# ifdef __SSE4_1__
+ all_caps |= CPU_CAPABILITY_SSE4_1;
+# endif
+# ifdef __SSE4_2__
+ all_caps |= CPU_CAPABILITY_SSE4_2;
+# endif
+# ifdef __3dNOW__
+ all_caps |= CPU_CAPABILITY_3DNOW;
+# endif
+
+#endif
+ cpu_flags = all_caps;
+}
+
+unsigned vlc_CPU (void)
+{
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+ pthread_once (&once, vlc_CPU_init);
+ return cpu_flags;
+}
+#else /* CPU_FLAGS */
+unsigned vlc_CPU (void)
+{
+ return 0;
+}
+#endif
More information about the vlc-commits
mailing list