| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2012 Google Inc. All rights reserved. | 2 // Copyright 2012 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 "xchg %%edi, %%ebx\n" \ | 51 "xchg %%edi, %%ebx\n" \ |
| 52 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) | 52 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) |
| 53 #elif defined(__x86_64__) | 53 #elif defined(__x86_64__) |
| 54 #define cpuid(a, b, c, d, inp) \ | 54 #define cpuid(a, b, c, d, inp) \ |
| 55 asm("mov %%rbx, %%rdi\n" \ | 55 asm("mov %%rbx, %%rdi\n" \ |
| 56 "cpuid\n" \ | 56 "cpuid\n" \ |
| 57 "xchg %%rdi, %%rbx\n" \ | 57 "xchg %%rdi, %%rbx\n" \ |
| 58 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) | 58 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) |
| 59 #endif | 59 #endif |
| 60 | 60 |
| 61 #if defined(cpuid) // initialize the struct only on x86 |
| 62 |
| 61 namespace google { | 63 namespace google { |
| 62 namespace protobuf { | 64 namespace protobuf { |
| 63 namespace internal { | 65 namespace internal { |
| 64 | 66 |
| 65 #if defined(cpuid) // initialize the struct only on x86 | 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 }; |
| 66 | 74 |
| 67 // Initialize the cr_AtomicOps_Internalx86CPUFeatures struct. | 75 namespace { |
| 76 |
| 77 // Initialize the AtomicOps_Internalx86CPUFeatures struct. |
| 68 void AtomicOps_Internalx86CPUFeaturesInit() { | 78 void AtomicOps_Internalx86CPUFeaturesInit() { |
| 69 uint32_t eax; | 79 uint32_t eax; |
| 70 uint32_t ebx; | 80 uint32_t ebx; |
| 71 uint32_t ecx; | 81 uint32_t ecx; |
| 72 uint32_t edx; | 82 uint32_t edx; |
| 73 | 83 |
| 74 // Get vendor string (issue CPUID with eax = 0) | 84 // Get vendor string (issue CPUID with eax = 0) |
| 75 cpuid(eax, ebx, ecx, edx, 0); | 85 cpuid(eax, ebx, ecx, edx, 0); |
| 76 char vendor[13]; | 86 char vendor[13]; |
| 77 memcpy(vendor, &ebx, 4); | 87 memcpy(vendor, &ebx, 4); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 90 } | 100 } |
| 91 | 101 |
| 92 // Opteron Rev E has a bug in which on very rare occasions a locked | 102 // Opteron Rev E has a bug in which on very rare occasions a locked |
| 93 // instruction doesn't act as a read-acquire barrier if followed by a | 103 // instruction doesn't act as a read-acquire barrier if followed by a |
| 94 // non-locked read-modify-write instruction. Rev F has this bug in | 104 // non-locked read-modify-write instruction. Rev F has this bug in |
| 95 // pre-release versions, but not in versions released to customers, | 105 // pre-release versions, but not in versions released to customers, |
| 96 // so we test only for Rev E, which is family 15, model 32..63 inclusive. | 106 // so we test only for Rev E, which is family 15, model 32..63 inclusive. |
| 97 if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD | 107 if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD |
| 98 family == 15 && | 108 family == 15 && |
| 99 32 <= model && model <= 63) { | 109 32 <= model && model <= 63) { |
| 100 cr_AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; | 110 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; |
| 101 } else { | 111 } else { |
| 102 cr_AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; | 112 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; |
| 103 } | 113 } |
| 104 | 114 |
| 105 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence | 115 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence |
| 106 cr_AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); | 116 AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); |
| 107 } | 117 } |
| 108 #else | 118 |
| 109 void AtomicOps_Internalx86CPUFeaturesInit() {} | 119 class AtomicOpsx86Initializer { |
| 110 #endif // __i386__ | 120 public: |
| 121 AtomicOpsx86Initializer() { |
| 122 AtomicOps_Internalx86CPUFeaturesInit(); |
| 123 } |
| 124 }; |
| 125 |
| 126 // A global to get use initialized on startup via static initialization :/ |
| 127 AtomicOpsx86Initializer g_initer; |
| 128 |
| 129 } // namespace |
| 111 | 130 |
| 112 } // namespace internal | 131 } // namespace internal |
| 113 } // namespace protobuf | 132 } // namespace protobuf |
| 114 } // namespace google | 133 } // namespace google |
| 115 | 134 |
| 135 #endif // __i386__ |
| 136 |
| 116 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ | 137 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ |
| OLD | NEW |