Support OS X and BeOS in x264_cpu_num_processors
[x264/x264-sandbox.git] / 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
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "common.h"
36
37 #if defined(ARCH_X86) || defined(ARCH_X86_64)
38 extern int  x264_cpu_cpuid_test( void );
39 extern uint32_t  x264_cpu_cpuid( uint32_t op, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx );
40 extern void x264_emms( void );
41
42 uint32_t x264_cpu_detect( void )
43 {
44     uint32_t cpu = 0;
45
46     uint32_t eax, ebx, ecx, edx;
47     int      b_amd;
48
49
50     if( !x264_cpu_cpuid_test() )
51     {
52         /* No cpuid */
53         return 0;
54     }
55
56     x264_cpu_cpuid( 0, &eax, &ebx, &ecx, &edx);
57     if( eax == 0 )
58     {
59         return 0;
60     }
61     b_amd   = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
62
63     x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
64     if( (edx&0x00800000) == 0 )
65     {
66         /* No MMX */
67         return 0;
68     }
69     cpu = X264_CPU_MMX;
70     if( (edx&0x02000000) )
71     {
72         /* SSE - identical to AMD MMX extensions */
73         cpu |= X264_CPU_MMXEXT|X264_CPU_SSE;
74     }
75     if( (edx&0x04000000) )
76     {
77         /* Is it OK ? */
78         cpu |= X264_CPU_SSE2;
79     }
80
81     x264_cpu_cpuid( 0x80000000, &eax, &ebx, &ecx, &edx );
82     if( eax < 0x80000001 )
83     {
84         /* no extended capabilities */
85         return cpu;
86     }
87
88     x264_cpu_cpuid( 0x80000001, &eax, &ebx, &ecx, &edx );
89     if( edx&0x80000000 )
90     {
91         cpu |= X264_CPU_3DNOW;
92     }
93     if( b_amd && (edx&0x00400000) )
94     {
95         /* AMD MMX extensions */
96         cpu |= X264_CPU_MMXEXT;
97     }
98
99     return cpu;
100 }
101
102 void     x264_cpu_restore( uint32_t cpu )
103 {
104     if( cpu&(X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_3DNOW|X264_CPU_3DNOWEXT) )
105     {
106         x264_emms();
107     }
108 }
109
110 #elif defined( ARCH_PPC )
111
112 #ifdef SYS_MACOSX
113 #include <sys/sysctl.h>
114 uint32_t x264_cpu_detect( void )
115 {
116     /* Thank you VLC */
117     uint32_t cpu = 0;
118     int      selectors[2] = { CTL_HW, HW_VECTORUNIT };
119     int      has_altivec = 0;
120     size_t   length = sizeof( has_altivec );
121     int      error = sysctl( selectors, 2, &has_altivec, &length, NULL, 0 );
122
123     if( error == 0 && has_altivec != 0 )
124     {
125         cpu |= X264_CPU_ALTIVEC;
126     }
127
128     return cpu;
129 }
130
131 #elif defined( SYS_LINUX )
132 uint32_t x264_cpu_detect( void )
133 {
134     /* FIXME (Linux PPC) */
135     return X264_CPU_ALTIVEC;
136 }
137 #endif
138
139 void     x264_cpu_restore( uint32_t cpu )
140 {
141 }
142
143 #else
144
145 uint32_t x264_cpu_detect( void )
146 {
147     return 0;
148 }
149
150 void     x264_cpu_restore( uint32_t cpu )
151 {
152 }
153
154 #endif
155
156
157 int x264_cpu_num_processors( void )
158 {
159 #if !defined(HAVE_PTHREAD)
160     return 1;
161
162 #elif defined(SYS_LINUX) || defined(WIN32)
163     int np;
164 #if defined(WIN32)
165     uint32_t p_aff, s_aff;
166     GetProcessAffinityMask( GetCurrentProcess(), &p_aff, &s_aff );
167 #else
168     uint64_t p_aff;
169     sched_getaffinity( 0, sizeof(p_aff), (cpu_set_t*)&p_aff );
170 #endif
171     for( np = 0; p_aff != 0; p_aff >>= 1 )
172         np += p_aff&1;
173     return np;
174
175 #elif defined(SYS_BEOS)
176     system_info info;
177     get_system_info( &info );
178     return info.cpu_count;
179
180 #elif defined(SYS_MACOSX)
181     FILE * pipe;
182     char   buffer[16];
183     int    num = 1;
184     if( ( pipe = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
185     {   
186         memset( buffer, 0, 16 );
187         if( fgets( buffer, 16, pipe ) )
188         {   
189             if( sscanf( buffer, "hw.ncpu: %d", &num ) != 1 )
190             {   
191                 num = 1;
192             }
193         }
194         fclose( pipe );
195     }
196     return num;
197
198 #else
199     return 1;
200 #endif
201 }