Commit 5c35f9d1 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Linux: parse /proc/cpuinfo instead of playing fork tricks

parent 2e1a59d0
...@@ -254,6 +254,7 @@ SOURCES_libvlc_linux = \ ...@@ -254,6 +254,7 @@ SOURCES_libvlc_linux = \
posix/filesystem.c \ posix/filesystem.c \
posix/plugin.c \ posix/plugin.c \
posix/thread.c \ posix/thread.c \
posix/linux_cpu.c \
posix/linux_specific.c \ posix/linux_specific.c \
posix/rand.c \ posix/rand.c \
$(NULL) $(NULL)
......
...@@ -32,7 +32,11 @@ ...@@ -32,7 +32,11 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_cpu.h> #include <vlc_cpu.h>
#include "libvlc.h"
#include <assert.h>
#ifndef __linux__
#include <sys/types.h> #include <sys/types.h>
#ifndef WIN32 #ifndef WIN32
#include <unistd.h> #include <unistd.h>
...@@ -41,14 +45,11 @@ ...@@ -41,14 +45,11 @@
#else #else
#include <errno.h> #include <errno.h>
#endif #endif
#include <assert.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
#include "libvlc.h"
static uint32_t cpu_flags; static uint32_t cpu_flags;
#if defined (__i386__) || defined (__x86_64__) || defined (__powerpc__) \ #if defined (__i386__) || defined (__x86_64__) || defined (__powerpc__) \
...@@ -284,45 +285,6 @@ void vlc_CPU_init (void) ...@@ -284,45 +285,6 @@ void vlc_CPU_init (void)
} }
out: 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__ ) \ #elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __powerpc64__ ) \
|| defined( __ppc64__ ) || defined( __ppc64__ )
...@@ -363,6 +325,7 @@ unsigned vlc_CPU (void) ...@@ -363,6 +325,7 @@ unsigned vlc_CPU (void)
#endif #endif
return cpu_flags; return cpu_flags;
} }
#endif
void vlc_CPU_dump (vlc_object_t *obj) void vlc_CPU_dump (vlc_object_t *obj)
{ {
......
/*****************************************************************************
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment