X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fcpu.c;h=fc6e437ed6dda7c176e54dff259a9a2cc3f5ba0d;hb=69d7fdea2da6f773fd7993f78c2bea494eb2d819;hp=3dfdb0537193633763a490fa670a3d6666952cdb;hpb=66dbe2921ed6f9740f7dc11a2a7a7998fd5c5ba0;p=vlc diff --git a/src/misc/cpu.c b/src/misc/cpu.c index 3dfdb05371..fc6e437ed6 100644 --- a/src/misc/cpu.c +++ b/src/misc/cpu.c @@ -37,6 +37,9 @@ #ifndef WIN32 #include #include +#include +#else +#include #endif #include "libvlc.h" @@ -47,9 +50,9 @@ #if defined( __i386__ ) || defined( __x86_64__ ) || defined( __powerpc__ ) \ || defined( __ppc__ ) || defined( __ppc64__ ) || defined( __powerpc64__ ) +# ifndef WIN32 static bool check_OS_capability( const char *psz_capability, pid_t pid ) { -#ifndef WIN32 int status; if( pid == -1 ) @@ -65,14 +68,25 @@ static bool check_OS_capability( const char *psz_capability, pid_t pid ) fprintf( stderr, " some optimizations will be disabled unless " "you upgrade your OS\n" ); return false; -#else -# warning FIXME! -# define fork() (errno = ENOSYS, -1) - (void)pid; - (void)psz_capability; - return true; -#endif } + +# define check_capability(name, flag, code) \ + do { \ + pid_t pid = fork(); \ + if( pid == 0 ) \ + { \ + signal(SIGILL, SIG_DFL); \ + __asm__ __volatile__ ( code : : ); \ + _exit(0); \ + } \ + if( check_OS_capability((name), pid )) \ + i_capabilities |= (flag); \ + } while(0) + +# else /* WIN32 */ +# define check_capability(name, flag, code) \ + i_capabilities |= (flag); +# endif #endif /***************************************************************************** @@ -113,18 +127,6 @@ uint32_t CPUCapabilities( void ) : "cc" ); # endif /* Check if the OS really supports the requested instructions */ -# define check_capability(name, flag, code) \ - do { \ - pid_t pid = fork(); \ - if( pid == 0 ) \ - { \ - __asm__ __volatile__ ( code : : ); \ - exit(0); \ - } \ - if( check_OS_capability((name), pid )) \ - i_capabilities |= (flag); \ - } while(0) - # if defined (__i386__) && !defined (__i486__) && !defined (__i586__) \ && !defined (__i686__) && !defined (__pentium4__) \ && !defined (__k6__) && !defined (__athlon__) && !defined (__k8__) @@ -201,6 +203,30 @@ uint32_t CPUCapabilities( void ) "movsldup %%xmm1, %%xmm0\n" ); # endif +# if defined (__SSSE3__) + i_capabilities |= CPU_CAPABILITY_SSSE3; +# elif defined (CAN_COMPILE_SSSE3) + if( i_ecx & 0x00000200 ) + check_capability( "SSSE3", CPU_CAPABILITY_SSSE3, + "pabsw %%xmm1, %%xmm0\n" ); +# endif + +# if defined (__SSE4_1__) + i_capabilities |= CPU_CAPABILITY_SSE4_1; +# elif defined (CAN_COMPILE_SSE4_1) + if( i_ecx & 0x00080000 ) + check_capability( "SSE4.1", CPU_CAPABILITY_SSE4_1, + "pmaxsb %%xmm1, %%xmm0\n" ); +# endif + +# if defined (__SSE4_2__) + i_capabilities |= CPU_CAPABILITY_SSE4_2; +# elif defined (CAN_COMPILE_SSE4_2) + if( i_ecx & 0x00100000 ) + check_capability( "SSE4.2", CPU_CAPABILITY_SSE4_2, + "pcmpgtq %%xmm1, %%xmm0\n" ); +# endif + /* test for additional capabilities */ cpuid( 0x80000000 ); @@ -245,11 +271,12 @@ out: pid_t pid = fork(); if( pid == 0 ) { + signal(SIGILL, SIG_DFL); asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0" : : "r" (-1)); - exit(0); + _exit(0); } if( check_OS_capability( "Altivec", pid ) ) @@ -272,6 +299,86 @@ unsigned vlc_CPU (void) return cpu_flags; } +const struct +{ + uint32_t value; + char name[12]; +} cap_dirs[] = { +#if defined ( __i386__ ) || defined ( __x86_64__ ) + { CPU_CAPABILITY_MMX, "mmx" }, + { CPU_CAPABILITY_MMXEXT, "mmxext" }, + { CPU_CAPABILITY_3DNOW, "3dnow" }, + { CPU_CAPABILITY_SSE, "sse" }, +#endif +#if defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__) + { CPU_CAPABILITY_ALTIVEC, "altivec" }, +#endif +#if defined (__arm__) + { CPU_CAPABILITY_NEON, "arm_neon" }, +#endif +}; + +/** + * Return the number of available logical CPU. + */ +unsigned vlc_GetCPUCount(void) +{ +#if defined(WIN32) && !defined(UNDER_CE) + DWORD process_mask; + DWORD system_mask; + if (!GetProcessAffinityMask(GetCurrentProcess(), &process_mask, &system_mask)) + return 1; + + unsigned count = 0; + while (system_mask) { + count++; + system_mask >>= 1; + } + return count; +#elif defined(HAVE_SCHED_GETAFFINITY) + cpu_set_t cpu; + CPU_ZERO(&cpu); + if (sched_getaffinity(0, sizeof(cpu), &cpu) < 0) + return 1; + unsigned count = 0; + for (unsigned i = 0; i < CPU_SETSIZE; i++) + count += CPU_ISSET(i, &cpu) != 0; + return count; +#elif defined(__APPLE__) + int count; + size_t size = sizeof(count) ; + if (sysctlbyname("hw.ncpu", &count, &size, NULL, 0)) + return 1; /* Failure */ + return count; +#else +# warning "vlc_GetCPUCount is not implemented for your platform" + return 1; +#endif +} + +/** + * Check if a directory name contains usable plugins w.r.t. the hardware + * capabilities. Loading a plugin when the hardware has insufficient + * capabilities may lead to illegal instructions (SIGILL) and must be avoided. + * + * @param name the name of the directory (not the path) + * + * @return true if the hardware has sufficient capabilities or the directory + * does not require any special capability; false if the running hardware has + * insufficient capabilities. + */ +bool vlc_CPU_CheckPluginDir (const char *name) +{ + const unsigned flags = vlc_CPU (); + for (size_t i = 0; i < sizeof (cap_dirs) / sizeof (cap_dirs[0]); i++) + { + if (strcmp (name, cap_dirs[i].name)) + continue; + return (flags & cap_dirs[i].value) != 0; + } + return true; +} + static vlc_memcpy_t pf_vlc_memcpy = memcpy; static vlc_memset_t pf_vlc_memset = memset;