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 |