LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - atomicops_internals_x86_gcc.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 19 24 79.2 %
Date: 2017-07-14 16:53:18 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : // This module gets enough CPU information to optimize the
       8             : // atomicops module on x86.
       9             : 
      10             : #include <string.h>
      11             : 
      12             : #include "base/atomicops.h"
      13             : #include "base/basictypes.h"
      14             : 
      15             : // This file only makes sense with atomicops_internals_x86_gcc.h -- it
      16             : // depends on structs that are defined in that file.  If atomicops.h
      17             : // doesn't sub-include that file, then we aren't needed, and shouldn't
      18             : // try to do anything.
      19             : #ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
      20             : 
      21             : // Inline cpuid instruction.  In PIC compilations, %ebx contains the address
      22             : // of the global offset table.  To avoid breaking such executables, this code
      23             : // must preserve that register's value across cpuid instructions.
      24             : #if defined(__i386__)
      25             : #define cpuid(a, b, c, d, inp) \
      26             :   asm ("mov %%ebx, %%edi\n"    \
      27             :        "cpuid\n"               \
      28             :        "xchg %%edi, %%ebx\n"   \
      29             :        : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
      30             : #elif defined (__x86_64__)
      31             : #define cpuid(a, b, c, d, inp) \
      32             :   asm ("mov %%rbx, %%rdi\n"    \
      33             :        "cpuid\n"               \
      34             :        "xchg %%rdi, %%rbx\n"   \
      35             :        : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
      36             : #endif
      37             : 
      38             : #if defined(cpuid)        // initialize the struct only on x86
      39             : 
      40             : // Set the flags so that code will run correctly and conservatively, so even
      41             : // if we haven't been initialized yet, we're probably single threaded, and our
      42             : // default values should hopefully be pretty safe.
      43             : struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
      44             :   false,          // bug can't exist before process spawns multiple threads
      45             :   false,          // no SSE2
      46             : };
      47             : 
      48             : // Initialize the AtomicOps_Internalx86CPUFeatures struct.
      49           3 : static void AtomicOps_Internalx86CPUFeaturesInit() {
      50             :   uint32_t eax;
      51             :   uint32_t ebx;
      52             :   uint32_t ecx;
      53             :   uint32_t edx;
      54             : 
      55             :   // Get vendor string (issue CPUID with eax = 0)
      56           3 :   cpuid(eax, ebx, ecx, edx, 0);
      57             :   char vendor[13];
      58           3 :   memcpy(vendor, &ebx, 4);
      59           3 :   memcpy(vendor + 4, &edx, 4);
      60           3 :   memcpy(vendor + 8, &ecx, 4);
      61           3 :   vendor[12] = 0;
      62             : 
      63             :   // get feature flags in ecx/edx, and family/model in eax
      64           3 :   cpuid(eax, ebx, ecx, edx, 1);
      65             : 
      66           3 :   int family = (eax >> 8) & 0xf;        // family and model fields
      67           3 :   int model = (eax >> 4) & 0xf;
      68           3 :   if (family == 0xf) {                  // use extended family and model fields
      69           0 :     family += (eax >> 20) & 0xff;
      70           0 :     model += ((eax >> 16) & 0xf) << 4;
      71             :   }
      72             : 
      73             :   // Opteron Rev E has a bug in which on very rare occasions a locked
      74             :   // instruction doesn't act as a read-acquire barrier if followed by a
      75             :   // non-locked read-modify-write instruction.  Rev F has this bug in
      76             :   // pre-release versions, but not in versions released to customers,
      77             :   // so we test only for Rev E, which is family 15, model 32..63 inclusive.
      78           3 :   if (strcmp(vendor, "AuthenticAMD") == 0 &&       // AMD
      79           0 :       family == 15 &&
      80           0 :       32 <= model && model <= 63) {
      81           0 :     AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
      82             :   } else {
      83           3 :     AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
      84             :   }
      85             : 
      86             :   // edx bit 26 is SSE2 which we use to tell use whether we can use mfence
      87           3 :   AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
      88           3 : }
      89             : 
      90             : namespace {
      91             : 
      92             : class AtomicOpsx86Initializer {
      93             :  public:
      94           3 :   AtomicOpsx86Initializer() {
      95           3 :     AtomicOps_Internalx86CPUFeaturesInit();
      96           3 :   }
      97             : };
      98             : 
      99             : // A global to get use initialized on startup via static initialization :/
     100           3 : AtomicOpsx86Initializer g_initer;
     101             : 
     102           9 : }  // namespace
     103             : 
     104             : #endif  // if x86
     105             : 
     106             : #endif  // ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_

Generated by: LCOV version 1.13