From ab4223e9cffbc21399c0468dd89a2e57122fbfee Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Tue, 14 Sep 2010 15:21:49 +0530 Subject: cpu: Add CPU information to pa_core This retains CPU information (processor type and supported features) in pa_core, so that this information can be used by modules at init time to figure out what optimisations may be used. --- src/Makefile.am | 1 + src/daemon/main.c | 13 ++++++---- src/pulsecore/core.h | 2 ++ src/pulsecore/cpu-arm.c | 39 ++++++++++++++++------------ src/pulsecore/cpu-arm.h | 3 ++- src/pulsecore/cpu-x86.c | 68 ++++++++++++++++++++++++++----------------------- src/pulsecore/cpu-x86.h | 3 ++- src/pulsecore/cpu.h | 45 ++++++++++++++++++++++++++++++++ 8 files changed, 119 insertions(+), 55 deletions(-) create mode 100644 src/pulsecore/cpu.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index ef6419bf..66757986 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -852,6 +852,7 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \ pulsecore/resampler.c pulsecore/resampler.h \ pulsecore/rtpoll.c pulsecore/rtpoll.h \ pulsecore/sample-util.c pulsecore/sample-util.h \ + pulsecore/cpu.h \ pulsecore/cpu-arm.c pulsecore/cpu-arm.h \ pulsecore/cpu-x86.c pulsecore/cpu-x86.h \ pulsecore/svolume_c.c pulsecore/svolume_arm.c \ diff --git a/src/daemon/main.c b/src/daemon/main.c index 9bea2aee..0e7b54a5 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -934,11 +934,6 @@ int main(int argc, char *argv[]) { pa_memtrap_install(); - if (!getenv("PULSE_NO_SIMD")) { - pa_cpu_init_x86(); - pa_cpu_init_arm(); - } - pa_assert_se(mainloop = pa_mainloop_new()); if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { @@ -964,6 +959,14 @@ int main(int argc, char *argv[]) { c->server_type = conf->local_server_type; #endif + c->cpu_info.cpu_type = PA_CPU_UNDEFINED; + if (!getenv("PULSE_NO_SIMD")) { + if (pa_cpu_init_x86(&(c->cpu_info.flags.x86))) + c->cpu_info.cpu_type = PA_CPU_X86; + if (pa_cpu_init_arm(&(c->cpu_info.flags.arm))) + c->cpu_info.cpu_type = PA_CPU_ARM; + } + pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index bfcea4f6..6088f915 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -24,6 +24,7 @@ #include #include +#include typedef struct pa_core pa_core; @@ -169,6 +170,7 @@ struct pa_core { int realtime_priority; pa_server_type_t server_type; + pa_cpu_info cpu_info; /* hooks */ pa_hook hooks[PA_CORE_HOOK_MAX]; diff --git a/src/pulsecore/cpu-arm.c b/src/pulsecore/cpu-arm.c index bf632f7a..1d0d7651 100644 --- a/src/pulsecore/cpu-arm.c +++ b/src/pulsecore/cpu-arm.c @@ -80,12 +80,11 @@ static char *get_cpuinfo(void) { } #endif /* defined (__arm__) && defined (__linux__) */ -void pa_cpu_init_arm (void) { +pa_bool_t pa_cpu_init_arm (pa_cpu_arm_flag_t *flags) { #if defined (__arm__) #if defined (__linux__) char *cpuinfo, *line; int arch; - pa_cpu_arm_flag_t flags = 0; /* We need to read the CPU flags from /proc/cpuinfo because there is no user * space support to get the CPU features. This only works on linux AFAIK. */ @@ -94,13 +93,15 @@ void pa_cpu_init_arm (void) { return; } + *flags = 0; + /* get the CPU architecture */ if ((line = get_cpuinfo_line (cpuinfo, "CPU architecture"))) { arch = strtoul (line, NULL, 0); if (arch >= 6) - flags |= PA_CPU_ARM_V6; + *flags |= PA_CPU_ARM_V6; if (arch >= 7) - flags |= PA_CPU_ARM_V7; + *flags |= PA_CPU_ARM_V7; pa_xfree(line); } @@ -111,13 +112,13 @@ void pa_cpu_init_arm (void) { while ((current = pa_split_spaces (line, &state))) { if (!strcmp (current, "vfp")) - flags |= PA_CPU_ARM_VFP; + *flags |= PA_CPU_ARM_VFP; else if (!strcmp (current, "edsp")) - flags |= PA_CPU_ARM_EDSP; + *flags |= PA_CPU_ARM_EDSP; else if (!strcmp (current, "neon")) - flags |= PA_CPU_ARM_NEON; + *flags |= PA_CPU_ARM_NEON; else if (!strcmp (current, "vfpv3")) - flags |= PA_CPU_ARM_VFPV3; + *flags |= PA_CPU_ARM_VFPV3; pa_xfree(current); } @@ -125,17 +126,23 @@ void pa_cpu_init_arm (void) { pa_xfree(cpuinfo); pa_log_info ("CPU flags: %s%s%s%s%s%s", - (flags & PA_CPU_ARM_V6) ? "V6 " : "", - (flags & PA_CPU_ARM_V7) ? "V7 " : "", - (flags & PA_CPU_ARM_VFP) ? "VFP " : "", - (flags & PA_CPU_ARM_EDSP) ? "EDSP " : "", - (flags & PA_CPU_ARM_NEON) ? "NEON " : "", - (flags & PA_CPU_ARM_VFPV3) ? "VFPV3 " : ""); + (*flags & PA_CPU_ARM_V6) ? "V6 " : "", + (*flags & PA_CPU_ARM_V7) ? "V7 " : "", + (*flags & PA_CPU_ARM_VFP) ? "VFP " : "", + (*flags & PA_CPU_ARM_EDSP) ? "EDSP " : "", + (*flags & PA_CPU_ARM_NEON) ? "NEON " : "", + (*flags & PA_CPU_ARM_VFPV3) ? "VFPV3 " : ""); + + if (*flags & PA_CPU_ARM_V6) + pa_volume_func_init_arm (*flags); + + return TRUE; + #else /* defined (__linux__) */ pa_log ("ARM cpu features not yet supported on this OS"); #endif /* defined (__linux__) */ - if (flags & PA_CPU_ARM_V6) - pa_volume_func_init_arm (flags); +#else /* defined (__arm__) */ + return FALSE; #endif /* defined (__arm__) */ } diff --git a/src/pulsecore/cpu-arm.h b/src/pulsecore/cpu-arm.h index a87cb63b..0e0c3e42 100644 --- a/src/pulsecore/cpu-arm.h +++ b/src/pulsecore/cpu-arm.h @@ -24,6 +24,7 @@ ***/ #include +#include typedef enum pa_cpu_arm_flag { PA_CPU_ARM_V6 = (1 << 0), @@ -34,7 +35,7 @@ typedef enum pa_cpu_arm_flag { PA_CPU_ARM_VFPV3 = (1 << 5) } pa_cpu_arm_flag_t; -void pa_cpu_init_arm (void); +pa_bool_t pa_cpu_init_arm (pa_cpu_arm_flag_t *flags); /* some optimized functions */ void pa_volume_func_init_arm(pa_cpu_arm_flag_t flags); diff --git a/src/pulsecore/cpu-x86.c b/src/pulsecore/cpu-x86.c index b1730722..062a4c1b 100644 --- a/src/pulsecore/cpu-x86.c +++ b/src/pulsecore/cpu-x86.c @@ -46,11 +46,12 @@ get_cpuid (uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) } #endif -void pa_cpu_init_x86 (void) { +pa_bool_t pa_cpu_init_x86 (pa_cpu_x86_flag_t *flags) { #if defined (__i386__) || defined (__amd64__) uint32_t eax, ebx, ecx, edx; uint32_t level; - pa_cpu_x86_flag_t flags = 0; + + *flags = 0; /* get standard level */ get_cpuid (0x00000000, &level, &ebx, &ecx, &edx); @@ -58,28 +59,28 @@ void pa_cpu_init_x86 (void) { get_cpuid (0x00000001, &eax, &ebx, &ecx, &edx); if (edx & (1<<15)) - flags |= PA_CPU_X86_CMOV; + *flags |= PA_CPU_X86_CMOV; if (edx & (1<<23)) - flags |= PA_CPU_X86_MMX; + *flags |= PA_CPU_X86_MMX; if (edx & (1<<25)) - flags |= PA_CPU_X86_SSE; + *flags |= PA_CPU_X86_SSE; if (edx & (1<<26)) - flags |= PA_CPU_X86_SSE2; + *flags |= PA_CPU_X86_SSE2; if (ecx & (1<<0)) - flags |= PA_CPU_X86_SSE3; + *flags |= PA_CPU_X86_SSE3; if (ecx & (1<<9)) - flags |= PA_CPU_X86_SSSE3; + *flags |= PA_CPU_X86_SSSE3; if (ecx & (1<<19)) - flags |= PA_CPU_X86_SSE4_1; + *flags |= PA_CPU_X86_SSE4_1; if (ecx & (1<<20)) - flags |= PA_CPU_X86_SSE4_2; + *flags |= PA_CPU_X86_SSE4_2; } /* get extended level */ @@ -88,42 +89,45 @@ void pa_cpu_init_x86 (void) { get_cpuid (0x80000001, &eax, &ebx, &ecx, &edx); if (edx & (1<<22)) - flags |= PA_CPU_X86_MMXEXT; + *flags |= PA_CPU_X86_MMXEXT; if (edx & (1<<23)) - flags |= PA_CPU_X86_MMX; + *flags |= PA_CPU_X86_MMX; if (edx & (1<<30)) - flags |= PA_CPU_X86_3DNOWEXT; + *flags |= PA_CPU_X86_3DNOWEXT; if (edx & (1<<31)) - flags |= PA_CPU_X86_3DNOW; + *flags |= PA_CPU_X86_3DNOW; } pa_log_info ("CPU flags: %s%s%s%s%s%s%s%s%s%s%s", - (flags & PA_CPU_X86_CMOV) ? "CMOV " : "", - (flags & PA_CPU_X86_MMX) ? "MMX " : "", - (flags & PA_CPU_X86_SSE) ? "SSE " : "", - (flags & PA_CPU_X86_SSE2) ? "SSE2 " : "", - (flags & PA_CPU_X86_SSE3) ? "SSE3 " : "", - (flags & PA_CPU_X86_SSSE3) ? "SSSE3 " : "", - (flags & PA_CPU_X86_SSE4_1) ? "SSE4_1 " : "", - (flags & PA_CPU_X86_SSE4_2) ? "SSE4_2 " : "", - (flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "", - (flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "", - (flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : ""); + (*flags & PA_CPU_X86_CMOV) ? "CMOV " : "", + (*flags & PA_CPU_X86_MMX) ? "MMX " : "", + (*flags & PA_CPU_X86_SSE) ? "SSE " : "", + (*flags & PA_CPU_X86_SSE2) ? "SSE2 " : "", + (*flags & PA_CPU_X86_SSE3) ? "SSE3 " : "", + (*flags & PA_CPU_X86_SSSE3) ? "SSSE3 " : "", + (*flags & PA_CPU_X86_SSE4_1) ? "SSE4_1 " : "", + (*flags & PA_CPU_X86_SSE4_2) ? "SSE4_2 " : "", + (*flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "", + (*flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "", + (*flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : ""); /* activate various optimisations */ - if (flags & PA_CPU_X86_MMX) { - pa_volume_func_init_mmx (flags); - pa_remap_func_init_mmx (flags); + if (*flags & PA_CPU_X86_MMX) { + pa_volume_func_init_mmx (*flags); + pa_remap_func_init_mmx (*flags); } - if (flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) { - pa_volume_func_init_sse (flags); - pa_remap_func_init_sse (flags); - pa_convert_func_init_sse (flags); + if (*flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) { + pa_volume_func_init_sse (*flags); + pa_remap_func_init_sse (*flags); + pa_convert_func_init_sse (*flags); } + return TRUE; +#else /* defined (__i386__) || defined (__amd64__) */ + return FALSE; #endif /* defined (__i386__) || defined (__amd64__) */ } diff --git a/src/pulsecore/cpu-x86.h b/src/pulsecore/cpu-x86.h index 285c2031..0045ef6d 100644 --- a/src/pulsecore/cpu-x86.h +++ b/src/pulsecore/cpu-x86.h @@ -24,6 +24,7 @@ ***/ #include +#include typedef enum pa_cpu_x86_flag { PA_CPU_X86_MMX = (1 << 0), @@ -39,7 +40,7 @@ typedef enum pa_cpu_x86_flag { PA_CPU_X86_CMOV = (1 << 10) } pa_cpu_x86_flag_t; -void pa_cpu_init_x86 (void); +pa_bool_t pa_cpu_init_x86 (pa_cpu_x86_flag_t *flags); #if defined (__i386__) typedef int32_t pa_reg_x86; diff --git a/src/pulsecore/cpu.h b/src/pulsecore/cpu.h new file mode 100644 index 00000000..7fe6f0b5 --- /dev/null +++ b/src/pulsecore/cpu.h @@ -0,0 +1,45 @@ +#ifndef foocpuhfoo +#define foocpuhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2010 Arun Raghavan + + PulseAudio 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. + + PulseAudio 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 + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +typedef enum { + PA_CPU_UNDEFINED = 0, + PA_CPU_X86, + PA_CPU_ARM, +} pa_cpu_type_t; + +typedef struct pa_cpu_info pa_cpu_info; + +struct pa_cpu_info { + pa_cpu_type_t cpu_type; + + union { + pa_cpu_x86_flag_t x86; + pa_cpu_arm_flag_t arm; + } flags; +}; + +#endif /* foocpuhfoo */ -- cgit