]> git.sesse.net Git - x264/blob - common/cpu.c
1668a6fae57fbf4e3e2ff2b36f98026a0f870b8e
[x264] / common / cpu.c
1 /*****************************************************************************
2  * cpu.c: h264 encoder library
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: cpu.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #if defined(HAVE_PTHREAD) && defined(SYS_LINUX)
25 #define _GNU_SOURCE
26 #include <sched.h>
27 #endif
28 #ifdef SYS_BEOS
29 #include <kernel/OS.h>
30 #endif
31 #ifdef SYS_MACOSX
32 #include <sys/types.h>
33 #include <sys/sysctl.h>
34 #endif
35
36 #include <string.h>
37
38 #include "common.h"
39
40 #ifdef HAVE_MMX
41 extern int  x264_cpu_cpuid_test( void );
42 extern uint32_t  x264_cpu_cpuid( uint32_t op, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx );
43 extern void x264_emms( void );
44
45 uint32_t x264_cpu_detect( void )
46 {
47     uint32_t cpu = 0;
48
49     uint32_t eax, ebx, ecx, edx;
50     int      b_amd;
51
52     if( !x264_cpu_cpuid_test() )
53     {
54         /* No cpuid */
55         return 0;
56     }
57
58     x264_cpu_cpuid( 0, &eax, &ebx, &ecx, &edx);
59     if( eax == 0 )
60     {
61         return 0;
62     }
63     b_amd   = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
64
65     x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
66     if( (edx&0x00800000) == 0 )
67     {
68         /* No MMX */
69         return 0;
70     }
71     cpu = X264_CPU_MMX;
72     if( (edx&0x02000000) )
73     {
74         /* SSE - identical to AMD MMX extensions */
75         cpu |= X264_CPU_MMXEXT|X264_CPU_SSE;
76     }
77     if( (edx&0x04000000) )
78     {
79         /* Is it OK ? */
80         cpu |= X264_CPU_SSE2;
81     }
82 #ifdef HAVE_SSE3
83     if( (ecx&0x00000001) )
84     {
85         cpu |= X264_CPU_SSE3;
86     }
87     if( (ecx&0x00000200) )
88     {
89         cpu |= X264_CPU_SSSE3;
90     }
91 #endif
92
93     x264_cpu_cpuid( 0x80000000, &eax, &ebx, &ecx, &edx );
94     if( eax < 0x80000001 )
95     {
96         /* no extended capabilities */
97         return cpu;
98     }
99
100     x264_cpu_cpuid( 0x80000001, &eax, &ebx, &ecx, &edx );
101     if( edx&0x80000000 )
102     {
103         cpu |= X264_CPU_3DNOW;
104     }
105     if( b_amd && (edx&0x00400000) )
106     {
107         /* AMD MMX extensions */
108         cpu |= X264_CPU_MMXEXT;
109     }
110
111     return cpu;
112 }
113
114 void     x264_cpu_restore( uint32_t cpu )
115 {
116     if( cpu&(X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_3DNOW|X264_CPU_3DNOWEXT) )
117     {
118         x264_emms();
119     }
120 }
121
122 #elif defined( ARCH_PPC )
123
124 #ifdef SYS_MACOSX
125 #include <sys/sysctl.h>
126 uint32_t x264_cpu_detect( void )
127 {
128     /* Thank you VLC */
129     uint32_t cpu = 0;
130     int      selectors[2] = { CTL_HW, HW_VECTORUNIT };
131     int      has_altivec = 0;
132     size_t   length = sizeof( has_altivec );
133     int      error = sysctl( selectors, 2, &has_altivec, &length, NULL, 0 );
134
135     if( error == 0 && has_altivec != 0 )
136     {
137         cpu |= X264_CPU_ALTIVEC;
138     }
139
140     return cpu;
141 }
142
143 #elif defined( SYS_LINUX )
144 #include <signal.h>
145 #include <setjmp.h>
146 static sigjmp_buf jmpbuf;
147 static volatile sig_atomic_t canjump = 0;
148
149 static void sigill_handler( int sig )
150 {
151     if( !canjump )
152     {
153         signal( sig, SIG_DFL );
154         raise( sig );
155     }
156
157     canjump = 0;
158     siglongjmp( jmpbuf, 1 );
159 }
160
161 uint32_t x264_cpu_detect( void )
162 {
163     static void (* oldsig)( int );
164
165     oldsig = signal( SIGILL, sigill_handler );
166     if( sigsetjmp( jmpbuf, 1 ) )
167     {
168         signal( SIGILL, oldsig );
169         return 0;
170     }
171
172     canjump = 1;
173     asm volatile( "mtspr 256, %0\n\t"
174                   "vand 0, 0, 0\n\t"
175                   :
176                   : "r"(-1) );
177     canjump = 0;
178
179     signal( SIGILL, oldsig );
180
181     return X264_CPU_ALTIVEC;
182 }
183 #endif
184
185 void     x264_cpu_restore( uint32_t cpu )
186 {
187 }
188
189 #else
190
191 uint32_t x264_cpu_detect( void )
192 {
193     return 0;
194 }
195
196 void     x264_cpu_restore( uint32_t cpu )
197 {
198 }
199
200 #endif
201
202
203 int x264_cpu_num_processors( void )
204 {
205 #if !defined(HAVE_PTHREAD)
206     return 1;
207
208 #elif defined(WIN32)
209     return pthread_num_processors_np();
210
211 #elif defined(SYS_LINUX)
212     unsigned int bit;
213     int np;
214     cpu_set_t p_aff;
215     memset( &p_aff, 0, sizeof(p_aff) );
216     sched_getaffinity( 0, sizeof(p_aff), &p_aff );
217     for( np = 0, bit = 0; bit < sizeof(p_aff); bit++ )
218         np += (((uint8_t *)&p_aff)[bit / 8] >> (bit % 8)) & 1;
219     return np;
220
221 #elif defined(SYS_BEOS)
222     system_info info;
223     get_system_info( &info );
224     return info.cpu_count;
225
226 #elif defined(SYS_MACOSX)
227     int numberOfCPUs;
228     size_t length = sizeof( numberOfCPUs );
229     if( sysctlbyname("hw.ncpu", &numberOfCPUs, &length, NULL, 0) )
230     {
231         numberOfCPUs = 1;
232     }
233     return numberOfCPUs;
234
235 #else
236     return 1;
237 #endif
238 }