From 953b1c185fcb4d9a1da063ca70a79f14b88c47a3 Mon Sep 17 00:00:00 2001 From: "simon.hosie" Date: Wed, 6 Apr 2016 14:02:26 -0700 Subject: [PATCH] Implement CPU feature detection for ARM Linux. BUG=webrtc:5057 NOTRY=True Review URL: https://codereview.webrtc.org/1820133002 Cr-Commit-Position: refs/heads/master@{#12270} --- webrtc/system_wrappers/BUILD.gn | 15 ++++ .../system_wrappers/cpu_features_webrtc.gyp | 15 ++++ .../source/cpu_features_linux.c | 83 +++++++++++++++++++ webrtc/system_wrappers/system_wrappers.gyp | 7 ++ 4 files changed, 120 insertions(+) create mode 100644 webrtc/system_wrappers/source/cpu_features_linux.c diff --git a/webrtc/system_wrappers/BUILD.gn b/webrtc/system_wrappers/BUILD.gn index bbad2d9534..aff29de502 100644 --- a/webrtc/system_wrappers/BUILD.gn +++ b/webrtc/system_wrappers/BUILD.gn @@ -107,6 +107,10 @@ static_library("system_wrappers") { if (is_linux) { defines += [ "WEBRTC_THREAD_RR" ] + if (!build_with_chromium) { + deps += [ ":cpu_features_linux" ] + } + libs += [ "rt" ] } @@ -177,3 +181,14 @@ if (is_android) { ] } } + +if (is_linux) { + source_set("cpu_features_linux") { + sources = [ + "source/cpu_features_linux.c", + ] + + configs += [ "..:common_config" ] + public_configs = [ "..:common_inherited_config" ] + } +} diff --git a/webrtc/system_wrappers/cpu_features_webrtc.gyp b/webrtc/system_wrappers/cpu_features_webrtc.gyp index 064b3cf049..310e3b2448 100644 --- a/webrtc/system_wrappers/cpu_features_webrtc.gyp +++ b/webrtc/system_wrappers/cpu_features_webrtc.gyp @@ -7,6 +7,7 @@ # be found in the AUTHORS file in the root of the source tree. { + 'includes': [ '../build/common.gypi', ], 'conditions': [ ['OS=="android"', { 'targets': [ @@ -22,5 +23,19 @@ }, ], }], + ['OS=="linux"', { + 'targets': [ + { + 'target_name': 'cpu_features_linux', + 'type': 'static_library', + 'sources': [ + 'source/cpu_features_linux.c', + ], + 'dependencies': [ + '<(webrtc_root)/common.gyp:webrtc_common', + ], + }, + ], + }], ], # conditions } diff --git a/webrtc/system_wrappers/source/cpu_features_linux.c b/webrtc/system_wrappers/source/cpu_features_linux.c new file mode 100644 index 0000000000..f23d827b71 --- /dev/null +++ b/webrtc/system_wrappers/source/cpu_features_linux.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include +#include +#if __GLIBC_PREREQ(2, 16) +#include +#else +#include +#include +#include +#include +#endif +#include "webrtc/system_wrappers/include/cpu_features_wrapper.h" + +#if defined(WEBRTC_ARCH_ARM_FAMILY) +#include + +uint64_t WebRtc_GetCPUFeaturesARM(void) { + uint64_t result = 0; + int architecture = 0; + unsigned long hwcap = 0; + const char* platform = NULL; +#if __GLIBC_PREREQ(2, 16) + hwcap = getauxval(AT_HWCAP); + platform = (const char*)getauxval(AT_PLATFORM); +#else + ElfW(auxv_t) auxv; + int fd = open("/proc/self/auxv", O_RDONLY); + if (fd >= 0) { + while (hwcap == 0 || platform == NULL) { + if (read(fd, &auxv, sizeof(auxv)) < (ssize_t)sizeof(auxv)) { + if (errno == EINTR) + continue; + break; + } + switch (auxv.a_type) { + case AT_HWCAP: + hwcap = auxv.a_un.a_val; + break; + case AT_PLATFORM: + platform = (const char*)auxv.a_un.a_val; + break; + } + } + close(fd); + } +#endif // __GLIBC_PREREQ(2,16) +#if defined(__aarch64__) + architecture = 8; + if ((hwcap & HWCAP_FP) != 0) + result |= kCPUFeatureVFPv3; + if ((hwcap & HWCAP_ASIMD) != 0) + result |= kCPUFeatureNEON; +#else + if (platform != NULL) { + /* expect a string in the form "v6l" or "v7l", etc. + */ + if (platform[0] == 'v' && '0' <= platform[1] && platform[1] <= '9' && + (platform[2] == 'l' || platform[2] == 'b')) { + architecture = platform[1] - '0'; + } + } + if ((hwcap & HWCAP_VFPv3) != 0) + result |= kCPUFeatureVFPv3; + if ((hwcap & HWCAP_NEON) != 0) + result |= kCPUFeatureNEON; +#endif + if (architecture >= 7) + result |= kCPUFeatureARMv7; + if (architecture >= 6) + result |= kCPUFeatureLDREXSTREX; + return result; +} +#endif // WEBRTC_ARCH_ARM_FAMILY diff --git a/webrtc/system_wrappers/system_wrappers.gyp b/webrtc/system_wrappers/system_wrappers.gyp index a8dc0c8bd5..cd6d3ea671 100644 --- a/webrtc/system_wrappers/system_wrappers.gyp +++ b/webrtc/system_wrappers/system_wrappers.gyp @@ -122,6 +122,13 @@ 'defines': [ 'WEBRTC_THREAD_RR', ], + 'conditions': [ + ['build_with_chromium==0', { + 'dependencies': [ + 'cpu_features_webrtc.gyp:cpu_features_linux', + ], + }], + ], 'link_settings': { 'libraries': [ '-lrt', ], },