OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 2014 Samsung Electronics. All rights reserved. |
| 3 * |
| 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions |
| 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. |
| 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ |
| 25 |
| 26 #include "config.h" |
| 27 |
| 28 #include "CPU.h" |
| 29 |
| 30 #if CPU(ARM_NEON_OPTIONAL) |
| 31 #include "wtf/Assertions.h" |
| 32 #include <pthread.h> |
| 33 |
| 34 #if OS(LINUX) |
| 35 #include <errno.h> |
| 36 #include <fcntl.h> |
| 37 #include <string.h> |
| 38 #include <unistd.h> |
| 39 #endif |
| 40 |
| 41 #if OS(ANDROID) |
| 42 #include <cpu-features.h> |
| 43 #endif |
| 44 |
| 45 static pthread_once_t sOnce; |
| 46 static bool sHasArmNeon; |
| 47 |
| 48 // A function used to determine at runtime if the target CPU supports |
| 49 // the ARM NEON instruction set. This implementation is Linux and Android specif
ic. |
| 50 static bool checkNEON(void) |
| 51 { |
| 52 // If we fail any of the following, assume we don't have NEON instructions |
| 53 // This allows us to return immediately in case of error. |
| 54 bool result = false; |
| 55 |
| 56 #if OS(ANDROID) |
| 57 // Use the Android NDK's cpu-features helper library to detect NEON at runti
me. |
| 58 // See http://crbug.com/164154 for skia to see why this is needed in Chromiu
m for Android. |
| 59 result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; |
| 60 #elif OS(LINUX) |
| 61 // There is no user-accessible CPUID instruction on ARM that we can use. |
| 62 // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature. |
| 63 // For example, here's a typical output (Nexus S running ICS 4.0.3): |
| 64 /* |
| 65 Processor : ARMv7 Processor rev 2 (v7l) |
| 66 BogoMIPS : 994.65 |
| 67 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 |
| 68 CPU implementer : 0x41 |
| 69 CPU architecture: 7 |
| 70 CPU variant : 0x2 |
| 71 CPU part : 0xc08 |
| 72 CPU revision : 2 |
| 73 |
| 74 Hardware : herring |
| 75 Revision : 000b |
| 76 Serial : 3833c77d6dc000ec |
| 77 */ |
| 78 char buffer[4096]; |
| 79 |
| 80 do { |
| 81 // open /proc/cpuinfo |
| 82 int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY)); |
| 83 if (fd < 0) { |
| 84 WTF_LOG_ERROR("Could not open /proc/cpuinfo: %s", strerror(errno)); |
| 85 break; |
| 86 } |
| 87 |
| 88 // Read the file. To simplify our search, we're going to place two |
| 89 // sentinel '\n' characters: one at the start of the buffer, and one at |
| 90 // the end. This means we reserve the first and last buffer bytes. |
| 91 buffer[0] = '\n'; |
| 92 int size = TEMP_FAILURE_RETRY(read(fd, buffer+1, sizeof(buffer)-2)); |
| 93 close(fd); |
| 94 |
| 95 if (size < 0) { |
| 96 WTF_LOG_ERROR("Could not read /proc/cpuinfo: %s", strerror(errno)); |
| 97 break; |
| 98 } |
| 99 |
| 100 WTF_LOG(CPU, "START /proc/cpuinfo:\n%.*s\nEND /proc/cpuinfo", size, buff
er+1); |
| 101 |
| 102 // Compute buffer limit, and place final sentinel |
| 103 char* bufferEnd = buffer + 1 + size; |
| 104 bufferEnd[0] = '\n'; |
| 105 |
| 106 // Now, find a line that starts with "Features", i.e. look for |
| 107 // '\nFeatures ' in our buffer. |
| 108 const char features[] = "\nFeatures\t"; |
| 109 const size_t featuresLength = sizeof(features)-1; |
| 110 |
| 111 char* line = (char*) memmem(buffer, bufferEnd - buffer, features, featur
esLength); |
| 112 if (!line) { |
| 113 WTF_LOG(CPU, "Could not find a line starting with 'Features' in /pro
c/cpuinfo ?"); |
| 114 break; |
| 115 } |
| 116 |
| 117 // Skip the "\nFeatures\t" prefix |
| 118 line += featuresLength; |
| 119 |
| 120 // Find the end of the current line |
| 121 char* lineEnd = (char*) memchr(line, '\n', bufferEnd - line); |
| 122 if (!lineEnd) |
| 123 lineEnd = bufferEnd; |
| 124 |
| 125 // Now find an instance of 'neon' in the flags list. We want to |
| 126 // ensure it's only 'neon' and not something fancy like 'noneon' |
| 127 // so check that it follows a space. |
| 128 const char neon[] = " neon"; |
| 129 const size_t neonLength = sizeof(neon)-1; |
| 130 const char* flag = (const char*) memmem(line, lineEnd - line, neon, neon
Length); |
| 131 if (!flag) |
| 132 break; |
| 133 |
| 134 // Ensure it is followed by a space or a newline. |
| 135 if (flag[neonLength] != ' ' && flag[neonLength] != '\n') |
| 136 break; |
| 137 |
| 138 // Fine, we support Arm NEON ! |
| 139 result = true; |
| 140 |
| 141 } while (0); |
| 142 #endif // OS(ANDROID) |
| 143 |
| 144 if (result) |
| 145 WTF_LOG(CPU, "Device supports ARM NEON instructions!\n"); |
| 146 else |
| 147 WTF_LOG(CPU, "Device does NOT support ARM NEON instructions!\n"); |
| 148 return result; |
| 149 } |
| 150 |
| 151 // called through pthread_once() |
| 152 void probeNEONFeature(void) |
| 153 { |
| 154 sHasArmNeon = checkNEON(); |
| 155 } |
| 156 |
| 157 bool isSupportedNEON(void) |
| 158 { |
| 159 pthread_once(&sOnce, probeNEONFeature); |
| 160 return sHasArmNeon; |
| 161 } |
| 162 #endif |
OLD | NEW |