]> git.sesse.net Git - vlc/blob - src/posix/linux_cpu.c
Fix Metacube header handling with multiple header blocks.
[vlc] / src / posix / linux_cpu.c
1 /*****************************************************************************
2  * linux_cpu.c: CPU detection code for Linux
3  *****************************************************************************
4  * Copyright (C) 2012 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <vlc_common.h>
28 #include <vlc_cpu.h>
29
30 #undef CPU_FLAGS
31 #if defined (__arm__)
32 # define CPU_FLAGS "Features\t:"
33
34 #elif defined (__i386__) || defined (__x86_64__)
35 # define CPU_FLAGS "flags\t\t:"
36
37 #elif defined (__powerpc__) || defined (__powerpc64__)
38 # define CPU_FLAGS "cpu\t\t:"
39
40 #endif
41
42 #ifdef CPU_FLAGS
43 static uint32_t cpu_flags = 0;
44
45 static void vlc_CPU_init (void)
46 {
47     FILE *info = fopen ("/proc/cpuinfo", "rte");
48     if (info == NULL)
49         return;
50
51     char *line = NULL;
52     size_t linelen = 0;
53     uint_fast32_t all_caps = 0xFFFFFFFF;
54
55     while (getline (&line, &linelen, info) != -1)
56     {
57         char *p = line, *cap;
58         uint_fast32_t core_caps = 0;
59
60 #if defined (__arm__)
61         unsigned ver;
62         if (sscanf (line, "Processor\t: ARMv%u", &ver) >= 1 && ver >= 6)
63             core_caps |= VLC_CPU_ARMv6;
64 #endif
65         if (strncmp (line, CPU_FLAGS, strlen (CPU_FLAGS)))
66             continue;
67
68         while ((cap = strsep (&p, " ")) != NULL)
69         {
70 #if defined (__arm__)
71             if (!strcmp (cap, "neon"))
72                 core_caps |= VLC_CPU_ARM_NEON;
73
74 #elif defined (__i386__) || defined (__x86_64__)
75             if (!strcmp (cap, "mmx"))
76                 core_caps |= VLC_CPU_MMX;
77             if (!strcmp (cap, "sse"))
78                 core_caps |= VLC_CPU_SSE | VLC_CPU_MMXEXT;
79             if (!strcmp (cap, "mmxext"))
80                 core_caps |= VLC_CPU_MMXEXT;
81             if (!strcmp (cap, "sse2"))
82                 core_caps |= VLC_CPU_SSE2;
83             if (!strcmp (cap, "pni"))
84                 core_caps |= VLC_CPU_SSE3;
85             if (!strcmp (cap, "ssse3"))
86                 core_caps |= VLC_CPU_SSSE3;
87             if (!strcmp (cap, "sse4_1"))
88                 core_caps |= VLC_CPU_SSE4_1;
89             if (!strcmp (cap, "sse4_2"))
90                 core_caps |= VLC_CPU_SSE4_2;
91             if (!strcmp (cap, "sse4a"))
92                 core_caps |= VLC_CPU_SSE4A;
93             if (!strcmp (cap, "avx"))
94                 core_caps |= VLC_CPU_AVX;
95             if (!strcmp (cap, "avx2"))
96                 core_caps |= VLC_CPU_AVX2;
97             if (!strcmp (cap, "3dnow"))
98                 core_caps |= VLC_CPU_3dNOW;
99             if (!strcmp (cap, "xop"))
100                 core_caps |= VLC_CPU_XOP;
101             if (!strcmp (cap, "fma4"))
102                 core_caps |= VLC_CPU_FMA4;
103
104 #elif defined (__powerpc__) || defined (__powerpc64__)
105             if (!strcmp (cap, "altivec supported"))
106                 core_caps |= VLC_CPU_ALTIVEC;
107 #endif
108         }
109
110         /* Take the intersection of capabilities of each processor */
111         all_caps &= core_caps;
112     }
113     fclose (info);
114     free (line);
115
116     if (all_caps == 0xFFFFFFFF) /* Error parsing of cpuinfo? */
117         all_caps = 0; /* Do not assume any capability! */
118
119     cpu_flags = all_caps;
120 }
121
122 unsigned vlc_CPU (void)
123 {
124     static pthread_once_t once = PTHREAD_ONCE_INIT;
125
126     pthread_once (&once, vlc_CPU_init);
127     return cpu_flags;
128 }
129 #else /* CPU_FLAGS */
130 unsigned vlc_CPU (void)
131 {
132     return 0;
133 }
134 #endif