LCOV - code coverage report
Current view: top level - toolkit/components/protobuf/src/google/protobuf/stubs - atomicops_internals_x86_gcc.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 18 23 78.3 %
Date: 2017-07-14 16:53:18 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2012 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       4             : //
       5             : // Redistribution and use in source and binary forms, with or without
       6             : // modification, are permitted provided that the following conditions are
       7             : // met:
       8             : //
       9             : //     * Redistributions of source code must retain the above copyright
      10             : // notice, this list of conditions and the following disclaimer.
      11             : //     * Redistributions in binary form must reproduce the above
      12             : // copyright notice, this list of conditions and the following disclaimer
      13             : // in the documentation and/or other materials provided with the
      14             : // distribution.
      15             : //     * Neither the name of Google Inc. nor the names of its
      16             : // contributors may be used to endorse or promote products derived from
      17             : // this software without specific prior written permission.
      18             : //
      19             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      20             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      21             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      22             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      23             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      24             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      25             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30             : 
      31             : // This module gets enough CPU information to optimize the
      32             : // atomicops module on x86.
      33             : 
      34             : #include <cstring>
      35             : 
      36             : #include <google/protobuf/stubs/atomicops.h>
      37             : 
      38             : // This file only makes sense with atomicops_internals_x86_gcc.h -- it
      39             : // depends on structs that are defined in that file.  If atomicops.h
      40             : // doesn't sub-include that file, then we aren't needed, and shouldn't
      41             : // try to do anything.
      42             : #ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
      43             : 
      44             : // Inline cpuid instruction.  In PIC compilations, %ebx contains the address
      45             : // of the global offset table.  To avoid breaking such executables, this code
      46             : // must preserve that register's value across cpuid instructions.
      47             : #if defined(__i386__)
      48             : #define cpuid(a, b, c, d, inp) \
      49             :   asm("mov %%ebx, %%edi\n"     \
      50             :       "cpuid\n"                \
      51             :       "xchg %%edi, %%ebx\n"    \
      52             :       : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
      53             : #elif defined(__x86_64__)
      54             : #define cpuid(a, b, c, d, inp) \
      55             :   asm("mov %%rbx, %%rdi\n"     \
      56             :       "cpuid\n"                \
      57             :       "xchg %%rdi, %%rbx\n"    \
      58             :       : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
      59             : #endif
      60             : 
      61             : #if defined(cpuid)        // initialize the struct only on x86
      62             : 
      63             : namespace google {
      64             : namespace protobuf {
      65             : namespace internal {
      66             : 
      67             : // Set the flags so that code will run correctly and conservatively, so even
      68             : // if we haven't been initialized yet, we're probably single threaded, and our
      69             : // default values should hopefully be pretty safe.
      70             : struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
      71             :   false,          // bug can't exist before process spawns multiple threads
      72             :   false,          // no SSE2
      73             : };
      74             : 
      75             : namespace {
      76             : 
      77             : // Initialize the AtomicOps_Internalx86CPUFeatures struct.
      78           3 : void AtomicOps_Internalx86CPUFeaturesInit() {
      79             :   uint32_t eax;
      80             :   uint32_t ebx;
      81             :   uint32_t ecx;
      82             :   uint32_t edx;
      83             : 
      84             :   // Get vendor string (issue CPUID with eax = 0)
      85           3 :   cpuid(eax, ebx, ecx, edx, 0);
      86             :   char vendor[13];
      87           3 :   memcpy(vendor, &ebx, 4);
      88           3 :   memcpy(vendor + 4, &edx, 4);
      89           3 :   memcpy(vendor + 8, &ecx, 4);
      90           3 :   vendor[12] = 0;
      91             : 
      92             :   // get feature flags in ecx/edx, and family/model in eax
      93           3 :   cpuid(eax, ebx, ecx, edx, 1);
      94             : 
      95           3 :   int family = (eax >> 8) & 0xf;        // family and model fields
      96           3 :   int model = (eax >> 4) & 0xf;
      97           3 :   if (family == 0xf) {                  // use extended family and model fields
      98           0 :     family += (eax >> 20) & 0xff;
      99           0 :     model += ((eax >> 16) & 0xf) << 4;
     100             :   }
     101             : 
     102             :   // Opteron Rev E has a bug in which on very rare occasions a locked
     103             :   // instruction doesn't act as a read-acquire barrier if followed by a
     104             :   // non-locked read-modify-write instruction.  Rev F has this bug in
     105             :   // pre-release versions, but not in versions released to customers,
     106             :   // so we test only for Rev E, which is family 15, model 32..63 inclusive.
     107           3 :   if (strcmp(vendor, "AuthenticAMD") == 0 &&       // AMD
     108           0 :       family == 15 &&
     109           0 :       32 <= model && model <= 63) {
     110           0 :     AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
     111             :   } else {
     112           3 :     AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
     113             :   }
     114             : 
     115             :   // edx bit 26 is SSE2 which we use to tell use whether we can use mfence
     116           3 :   AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
     117           3 : }
     118             : 
     119             : class AtomicOpsx86Initializer {
     120             :  public:
     121           3 :   AtomicOpsx86Initializer() {
     122           3 :     AtomicOps_Internalx86CPUFeaturesInit();
     123           3 :   }
     124             : };
     125             : 
     126             : // A global to get use initialized on startup via static initialization :/
     127           3 : AtomicOpsx86Initializer g_initer;
     128             : 
     129             : }  // namespace
     130             : 
     131             : }  // namespace internal
     132             : }  // namespace protobuf
     133             : }  // namespace google
     134             : 
     135             : #endif  // __i386__
     136             : 
     137             : #endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_

Generated by: LCOV version 1.13