OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This module gets enough CPU information to optimize the | 5 // This module gets enough CPU information to optimize the |
6 // atomicops module on x86. | 6 // atomicops module on x86. |
7 | 7 |
| 8 #include <stdint.h> |
8 #include <string.h> | 9 #include <string.h> |
9 | 10 |
10 #include "base/atomicops.h" | 11 #include "base/atomicops.h" |
11 #include "base/basictypes.h" | |
12 | 12 |
13 // This file only makes sense with atomicops_internals_x86_gcc.h -- it | 13 // This file only makes sense with atomicops_internals_x86_gcc.h -- it |
14 // depends on structs that are defined in that file. If atomicops.h | 14 // depends on structs that are defined in that file. If atomicops.h |
15 // doesn't sub-include that file, then we aren't needed, and shouldn't | 15 // doesn't sub-include that file, then we aren't needed, and shouldn't |
16 // try to do anything. | 16 // try to do anything. |
17 #ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ | 17 #ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ |
18 | 18 |
19 // Inline cpuid instruction. In PIC compilations, %ebx contains the address | 19 // Inline cpuid instruction. In PIC compilations, %ebx contains the address |
20 // of the global offset table. To avoid breaking such executables, this code | 20 // of the global offset table. To avoid breaking such executables, this code |
21 // must preserve that register's value across cpuid instructions. | 21 // must preserve that register's value across cpuid instructions. |
22 #if defined(__i386__) | 22 #if defined(__i386__) |
23 #define cpuid(a, b, c, d, inp) \ | 23 #define cpuid(a, b, c, d, inp) \ |
24 asm ("mov %%ebx, %%edi\n" \ | 24 asm("mov %%ebx, %%edi\n" \ |
25 "cpuid\n" \ | 25 "cpuid\n" \ |
26 "xchg %%edi, %%ebx\n" \ | 26 "xchg %%edi, %%ebx\n" \ |
27 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) | 27 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) |
28 #elif defined (__x86_64__) | 28 #elif defined(__x86_64__) |
29 #define cpuid(a, b, c, d, inp) \ | 29 #define cpuid(a, b, c, d, inp) \ |
30 asm ("mov %%rbx, %%rdi\n" \ | 30 asm("mov %%rbx, %%rdi\n" \ |
31 "cpuid\n" \ | 31 "cpuid\n" \ |
32 "xchg %%rdi, %%rbx\n" \ | 32 "xchg %%rdi, %%rbx\n" \ |
33 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) | 33 : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) |
34 #endif | 34 #endif |
35 | 35 |
36 #if defined(cpuid) // initialize the struct only on x86 | 36 #if defined(cpuid) // initialize the struct only on x86 |
37 | 37 |
38 // Set the flags so that code will run correctly and conservatively, so even | 38 // Set the flags so that code will run correctly and conservatively, so even |
39 // if we haven't been initialized yet, we're probably single threaded, and our | 39 // if we haven't been initialized yet, we're probably single threaded, and our |
40 // default values should hopefully be pretty safe. | 40 // default values should hopefully be pretty safe. |
41 struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { | 41 struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { |
42 false, // bug can't exist before process spawns multiple threads | 42 false, // bug can't exist before process spawns multiple threads |
43 false, // no SSE2 | 43 false, // no SSE2 |
44 }; | 44 }; |
45 | 45 |
| 46 namespace { |
| 47 |
46 // Initialize the AtomicOps_Internalx86CPUFeatures struct. | 48 // Initialize the AtomicOps_Internalx86CPUFeatures struct. |
47 static void AtomicOps_Internalx86CPUFeaturesInit() { | 49 void AtomicOps_Internalx86CPUFeaturesInit() { |
48 uint32 eax; | 50 uint32_t eax; |
49 uint32 ebx; | 51 uint32_t ebx; |
50 uint32 ecx; | 52 uint32_t ecx; |
51 uint32 edx; | 53 uint32_t edx; |
52 | 54 |
53 // Get vendor string (issue CPUID with eax = 0) | 55 // Get vendor string (issue CPUID with eax = 0) |
54 cpuid(eax, ebx, ecx, edx, 0); | 56 cpuid(eax, ebx, ecx, edx, 0); |
55 char vendor[13]; | 57 char vendor[13]; |
56 memcpy(vendor, &ebx, 4); | 58 memcpy(vendor, &ebx, 4); |
57 memcpy(vendor + 4, &edx, 4); | 59 memcpy(vendor + 4, &edx, 4); |
58 memcpy(vendor + 8, &ecx, 4); | 60 memcpy(vendor + 8, &ecx, 4); |
59 vendor[12] = 0; | 61 vendor[12] = 0; |
60 | 62 |
61 // get feature flags in ecx/edx, and family/model in eax | 63 // get feature flags in ecx/edx, and family/model in eax |
(...skipping 16 matching lines...) Expand all Loading... |
78 32 <= model && model <= 63) { | 80 32 <= model && model <= 63) { |
79 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; | 81 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; |
80 } else { | 82 } else { |
81 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; | 83 AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; |
82 } | 84 } |
83 | 85 |
84 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence | 86 // edx bit 26 is SSE2 which we use to tell use whether we can use mfence |
85 AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); | 87 AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); |
86 } | 88 } |
87 | 89 |
88 namespace { | |
89 | |
90 class AtomicOpsx86Initializer { | 90 class AtomicOpsx86Initializer { |
91 public: | 91 public: |
92 AtomicOpsx86Initializer() { | 92 AtomicOpsx86Initializer() { |
93 AtomicOps_Internalx86CPUFeaturesInit(); | 93 AtomicOps_Internalx86CPUFeaturesInit(); |
94 } | 94 } |
95 }; | 95 }; |
96 | 96 |
97 // A global to get use initialized on startup via static initialization :/ | 97 // A global to get use initialized on startup via static initialization :/ |
98 AtomicOpsx86Initializer g_initer; | 98 AtomicOpsx86Initializer g_initer; |
99 | 99 |
100 } // namespace | 100 } // namespace |
101 | 101 |
102 #endif // if x86 | 102 #endif // if x86 |
103 | 103 |
104 #endif // ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ | 104 #endif // ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ |
OLD | NEW |