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 | |
63 namespace google { | 61 namespace google { |
64 namespace protobuf { | 62 namespace protobuf { |
65 namespace internal { | 63 namespace internal { |
66 | 64 |
67 // Set the flags so that code will run correctly and conservatively, so even | 65 #if defined(cpuid) // initialize the struct only on x86 |
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 | 66 |
75 namespace { | 67 // Initialize the cr_AtomicOps_Internalx86CPUFeatures struct. |
76 | |
77 // Initialize the AtomicOps_Internalx86CPUFeatures struct. | |
78 void AtomicOps_Internalx86CPUFeaturesInit() { | 68 void AtomicOps_Internalx86CPUFeaturesInit() { |
79 uint32_t eax; | 69 uint32_t eax; |
80 uint32_t ebx; | 70 uint32_t ebx; |
81 uint32_t ecx; | 71 uint32_t ecx; |
82 uint32_t edx; | 72 uint32_t edx; |
83 | 73 |
84 // Get vendor string (issue CPUID with eax = 0) | 74 // Get vendor string (issue CPUID with eax = 0) |
85 cpuid(eax, ebx, ecx, edx, 0); | 75 cpuid(eax, ebx, ecx, edx, 0); |
86 char vendor[13]; | 76 char vendor[13]; |
87 memcpy(vendor, &ebx, 4); | 77 memcpy(vendor, &ebx, 4); |
(...skipping 12 matching lines...) Expand all Loading... |
100 } | 90 } |
101 | 91 |
102 // Opteron Rev E has a bug in which on very rare occasions a locked | 92 // 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 | 93 // 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 | 94 // non-locked read-modify-write instruction. Rev F has this bug in |
105 // pre-release versions, but not in versions released to customers, | 95 // 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. | 96 // so we test only for Rev E, which is family 15, model 32..63 inclusive. |
107 if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD | 97 if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD |
108 family == 15 && | 98 family == 15 && |
109 32 <= model && model <= 63) { | 99 32 <= model && model <= 63) { |
110 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; | 100 cr_AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; |
111 } else { | 101 } else { |
112 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; | 102 cr_AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; |
113 } | 103 } |
114 | 104 |
115 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence | 105 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence |
116 AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); | 106 cr_AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); |
117 } | 107 } |
118 | 108 #else |
119 class AtomicOpsx86Initializer { | 109 void AtomicOps_Internalx86CPUFeaturesInit() {} |
120 public: | 110 #endif // __i386__ |
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 | |
130 | 111 |
131 } // namespace internal | 112 } // namespace internal |
132 } // namespace protobuf | 113 } // namespace protobuf |
133 } // namespace google | 114 } // namespace google |
134 | 115 |
135 #endif // __i386__ | |
136 | |
137 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ | 116 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ |
OLD | NEW |