gfx/skia/trunk/src/core/SkUtilsArm.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2012 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #include "SkUtilsArm.h"
    11 #if SK_ARM_NEON_IS_DYNAMIC
    13 #include <unistd.h>
    14 #include <fcntl.h>
    15 #include <errno.h>
    16 #include <string.h>
    17 #include <pthread.h>
    19 // Set USE_ANDROID_NDK_CPU_FEATURES to use the Android NDK's
    20 // cpu-features helper library to detect NEON at runtime. See
    21 // http://crbug.com/164154 to see why this is needed in Chromium
    22 // for Android.
    23 #if !defined(USE_ANDROID_NDK_CPU_FEATURES)
    24 #  if defined(SK_BUILD_FOR_ANDROID)
    25 #    define USE_ANDROID_NDK_CPU_FEATURES 1
    26 #  else
    27 #    define USE_ANDROID_NDK_CPU_FEATURES 0
    28 #  endif
    29 #endif
    31 #if USE_ANDROID_NDK_CPU_FEATURES
    32 #  include <cpu-features.h>
    33 #endif
    35 // Set NEON_DEBUG to 1 to allow debugging of the CPU features probing.
    36 // For now, we always set it for SK_DEBUG builds.
    37 #ifdef SK_DEBUG
    38 #  define NEON_DEBUG  1
    39 #else
    40 #  define NEON_DEBUG 0
    41 #endif
    43 #if NEON_DEBUG
    44 #  ifdef SK_BUILD_FOR_ANDROID
    45      // used to declare PROP_VALUE_MAX and __system_property_get()
    46 #    include <sys/system_properties.h>
    47 #  endif
    48 #endif
    50 // A function used to determine at runtime if the target CPU supports
    51 // the ARM NEON instruction set. This implementation is Linux-specific.
    52 static bool sk_cpu_arm_check_neon(void) {
    53     bool result = false;
    55 #if NEON_DEBUG
    56     // Allow forcing the mode through the environment during debugging.
    57 #  ifdef SK_BUILD_FOR_ANDROID
    58     // On Android, we use a system property
    59 #   define PROP_NAME  "debug.skia.arm_neon_mode"
    60     char prop[PROP_VALUE_MAX];
    61     if (__system_property_get(PROP_NAME, prop) > 0) {
    62 #  else
    63 #   define PROP_NAME   "SKIA_ARM_NEON_MODE"
    64     // On ARM Linux, we use an environment variable
    65     const char* prop = getenv(PROP_NAME);
    66     if (prop != NULL) {
    67 #  endif
    68         SkDebugf("%s: %s", PROP_NAME, prop);
    69         if (!strcmp(prop, "1")) {
    70             SkDebugf("Forcing ARM Neon mode to full!\n");
    71             return true;
    72         }
    73         if (!strcmp(prop, "0")) {
    74             SkDebugf("Disabling ARM NEON mode\n");
    75             return false;
    76         }
    77     }
    78     SkDebugf("Running dynamic CPU feature detection\n");
    79 #endif
    81 #if USE_ANDROID_NDK_CPU_FEATURES
    83   result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
    85 #else  // USE_ANDROID_NDK_CPU_FEATURES
    87     // There is no user-accessible CPUID instruction on ARM that we can use.
    88     // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature.
    89     // For example, here's a typical output (Nexus S running ICS 4.0.3):
    90     /*
    91     Processor       : ARMv7 Processor rev 2 (v7l)
    92     BogoMIPS        : 994.65
    93     Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3
    94     CPU implementer : 0x41
    95     CPU architecture: 7
    96     CPU variant     : 0x2
    97     CPU part        : 0xc08
    98     CPU revision    : 2
   100     Hardware        : herring
   101     Revision        : 000b
   102     Serial          : 3833c77d6dc000ec
   103     */
   104     char   buffer[4096];
   106     // If we fail any of the following, assume we don't have NEON instructions
   107     // This allows us to return immediately in case of error.
   108     result = false;
   110     do {
   111         // open /proc/cpuinfo
   112         int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY));
   113         if (fd < 0) {
   114             SkDebugf("Could not open /proc/cpuinfo: %s\n", strerror(errno));
   115             break;
   116         }
   118         // Read the file. To simplify our search, we're going to place two
   119         // sentinel '\n' characters: one at the start of the buffer, and one at
   120         // the end. This means we reserve the first and last buffer bytes.
   121         buffer[0] = '\n';
   122         int size = TEMP_FAILURE_RETRY(read(fd, buffer+1, sizeof(buffer)-2));
   123         close(fd);
   125         if (size < 0) {  // should not happen
   126             SkDebugf("Could not read /proc/cpuinfo: %s\n", strerror(errno));
   127             break;
   128         }
   130         SkDebugf("START /proc/cpuinfo:\n%.*s\nEND /proc/cpuinfo\n",
   131                  size, buffer+1);
   133         // Compute buffer limit, and place final sentinel
   134         char* buffer_end = buffer + 1 + size;
   135         buffer_end[0] = '\n';
   137         // Now, find a line that starts with "Features", i.e. look for
   138         // '\nFeatures ' in our buffer.
   139         const char features[] = "\nFeatures\t";
   140         const size_t features_len = sizeof(features)-1;
   142         char*  line = (char*) memmem(buffer, buffer_end - buffer,
   143                                      features, features_len);
   144         if (line == NULL) {  // Weird, no Features line, bad kernel?
   145             SkDebugf("Could not find a line starting with 'Features'"
   146               "in /proc/cpuinfo ?\n");
   147             break;
   148         }
   150         line += features_len;  // Skip the "\nFeatures\t" prefix
   152         // Find the end of the current line
   153         char* line_end = (char*) memchr(line, '\n', buffer_end - line);
   154         if (line_end == NULL)
   155             line_end = buffer_end;
   157         // Now find an instance of 'neon' in the flags list. We want to
   158         // ensure it's only 'neon' and not something fancy like 'noneon'
   159         // so check that it follows a space.
   160         const char neon[] = " neon";
   161         const size_t neon_len = sizeof(neon)-1;
   162         const char* flag = (const char*) memmem(line, line_end - line,
   163                                                 neon, neon_len);
   164         if (flag == NULL)
   165             break;
   167         // Ensure it is followed by a space or a newline.
   168         if (flag[neon_len] != ' ' && flag[neon_len] != '\n')
   169             break;
   171         // Fine, we support Arm NEON !
   172         result = true;
   174     } while (0);
   176 #endif  // USE_ANDROID_NDK_CPU_FEATURES
   178     if (result) {
   179         SkDebugf("Device supports ARM NEON instructions!\n");
   180     } else {
   181         SkDebugf("Device does NOT support ARM NEON instructions!\n");
   182     }
   183     return result;
   184 }
   186 static pthread_once_t  sOnce;
   187 static bool            sHasArmNeon;
   189 // called through pthread_once()
   190 void sk_cpu_arm_probe_features(void) {
   191     sHasArmNeon = sk_cpu_arm_check_neon();
   192 }
   194 bool sk_cpu_arm_has_neon(void) {
   195     pthread_once(&sOnce, sk_cpu_arm_probe_features);
   196     return sHasArmNeon;
   197 }
   199 #endif // SK_ARM_NEON_IS_DYNAMIC

mercurial