xref: /aosp_15_r20/external/webrtc/system_wrappers/source/cpu_features_linux.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <features.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #ifdef __GLIBC_PREREQ
16 #define WEBRTC_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
17 #else
18 #define WEBRTC_GLIBC_PREREQ(a, b) 0
19 #endif
20 
21 #if WEBRTC_GLIBC_PREREQ(2, 16)
22 #include <sys/auxv.h>
23 #else
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <link.h>
27 #include <unistd.h>
28 #endif
29 
30 #include "rtc_base/system/arch.h"
31 #include "system_wrappers/include/cpu_features_wrapper.h"
32 
33 #if defined(WEBRTC_ARCH_ARM_FAMILY)
34 #include <asm/hwcap.h>
35 
36 namespace webrtc {
37 
GetCPUFeaturesARM(void)38 uint64_t GetCPUFeaturesARM(void) {
39   uint64_t result = 0;
40   int architecture = 0;
41   uint64_t hwcap = 0;
42   const char* platform = NULL;
43 #if WEBRTC_GLIBC_PREREQ(2, 16)
44   hwcap = getauxval(AT_HWCAP);
45   platform = (const char*)getauxval(AT_PLATFORM);
46 #else
47   ElfW(auxv_t) auxv;
48   int fd = open("/proc/self/auxv", O_RDONLY);
49   if (fd >= 0) {
50     while (hwcap == 0 || platform == NULL) {
51       if (read(fd, &auxv, sizeof(auxv)) < (ssize_t)sizeof(auxv)) {
52         if (errno == EINTR)
53           continue;
54         break;
55       }
56       switch (auxv.a_type) {
57         case AT_HWCAP:
58           hwcap = auxv.a_un.a_val;
59           break;
60         case AT_PLATFORM:
61           platform = (const char*)auxv.a_un.a_val;
62           break;
63       }
64     }
65     close(fd);
66   }
67 #endif  // WEBRTC_GLIBC_PREREQ(2, 16)
68 #if defined(__aarch64__)
69   (void)platform;
70   architecture = 8;
71   if ((hwcap & HWCAP_FP) != 0)
72     result |= kCPUFeatureVFPv3;
73   if ((hwcap & HWCAP_ASIMD) != 0)
74     result |= kCPUFeatureNEON;
75 #else
76   if (platform != NULL) {
77     /* expect a string in the form "v6l" or "v7l", etc.
78      */
79     if (platform[0] == 'v' && '0' <= platform[1] && platform[1] <= '9' &&
80         (platform[2] == 'l' || platform[2] == 'b')) {
81       architecture = platform[1] - '0';
82     }
83   }
84   if ((hwcap & HWCAP_VFPv3) != 0)
85     result |= kCPUFeatureVFPv3;
86   if ((hwcap & HWCAP_NEON) != 0)
87     result |= kCPUFeatureNEON;
88 #endif
89   if (architecture >= 7)
90     result |= kCPUFeatureARMv7;
91   if (architecture >= 6)
92     result |= kCPUFeatureLDREXSTREX;
93   return result;
94 }
95 
96 }  // namespace webrtc
97 #endif  // WEBRTC_ARCH_ARM_FAMILY
98