[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