Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: base/atomicops_internals_arm_gcc.h

Issue 18984012: Refine atomic operations for Linux/ARM. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove empty line Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 file is an internal atomic implementation, use base/atomicops.h instead. 5 // This file is an internal atomic implementation, use base/atomicops.h instead.
6 // 6 //
7 // LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. 7 // LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
8 8
9 #ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ 9 #ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
10 #define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ 10 #define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 int reloop; 63 int reloop;
64 do { 64 do {
65 // The following is equivalent to: 65 // The following is equivalent to:
66 // 66 //
67 // prev_value = LDREX(ptr) 67 // prev_value = LDREX(ptr)
68 // reloop = 0 68 // reloop = 0
69 // if (prev_value != old_value) 69 // if (prev_value != old_value)
70 // reloop = STREX(ptr, new_value) 70 // reloop = STREX(ptr, new_value)
71 __asm__ __volatile__(" ldrex %0, [%3]\n" 71 __asm__ __volatile__(" ldrex %0, [%3]\n"
72 " mov %1, #0\n" 72 " mov %1, #0\n"
73 " teq %0, %4\n" 73 " cmp %0, %4\n"
74 #ifdef __thumb2__ 74 #ifdef __thumb2__
75 " it eq\n" 75 " it eq\n"
76 #endif 76 #endif
77 " strexeq %1, %5, [%3]\n" 77 " strexeq %1, %5, [%3]\n"
78 : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr) 78 : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr)
79 : "r"(ptr), "r"(old_value), "r"(new_value) 79 : "r"(ptr), "r"(old_value), "r"(new_value)
80 : "cc", "memory"); 80 : "cc", "memory");
81 } while (reloop != 0); 81 } while (reloop != 0);
82 return prev_value; 82 return prev_value;
83 } 83 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 MemoryBarrier(); 128 MemoryBarrier();
129 return result; 129 return result;
130 } 130 }
131 131
132 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 132 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
133 Atomic32 new_value) { 133 Atomic32 new_value) {
134 Atomic32 old_value; 134 Atomic32 old_value;
135 int reloop; 135 int reloop;
136 do { 136 do {
137 // old_value = LDREX(ptr) 137 // old_value = LDREX(ptr)
138 // fail = STREX(ptr, new_value) 138 // reloop = STREX(ptr, new_value)
139 __asm__ __volatile__(" ldrex %0, [%3]\n" 139 __asm__ __volatile__(" ldrex %0, [%3]\n"
140 " strex %1, %4, [%3]\n" 140 " strex %1, %4, [%3]\n"
141 : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr) 141 : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr)
142 : "r"(ptr), "r"(new_value) 142 : "r"(ptr), "r"(new_value)
143 : "cc", "memory"); 143 : "cc", "memory");
144 } while (reloop != 0); 144 } while (reloop != 0);
145 return old_value; 145 return old_value;
146 } 146 }
147 147
148 // This tests against any known ARMv5 variant. 148 // This tests against any known ARMv5 variant.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 return prev_value; 225 return prev_value;
226 } 226 }
227 if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) 227 if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
228 return old_value; 228 return old_value;
229 } 229 }
230 } 230 }
231 231
232 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 232 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
233 Atomic32 old_value, 233 Atomic32 old_value,
234 Atomic32 new_value) { 234 Atomic32 new_value) {
235 // Use NoBarrier_CompareAndSwap(), because its implementation 235 // This could be implemented as:
236 // ensures that all stores happen through the kernel helper 236 // MemoryBarrier();
237 // which always implement a full barrier. 237 // return NoBarrier_CompareAndSwap();
238 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 238 //
239 // But would use 3 barriers per succesful CAS. To save performance,
240 // use Acquire_CompareAndSwap(). Its implementation guarantees that:
241 // - A succesful swap uses only 2 barriers (in the kernel helper).
242 // - An early return due to (prev_value != old_value) performs
243 // a memory barrier with no store, which is equivalent to the
244 // generic implementation above.
245 return Acquire_CompareAndSwap(ptr, old_value, new_value);
Dmitry Vyukov 2013/07/15 14:42:32 A failing Release_CompareAndSwap() does not need a
239 } 246 }
240 247
241 #else 248 #else
242 # error "Your CPU's ARM architecture is not supported yet" 249 # error "Your CPU's ARM architecture is not supported yet"
243 #endif 250 #endif
244 251
245 // NOTE: Atomicity of the following load and store operations is only 252 // NOTE: Atomicity of the following load and store operations is only
246 // guaranteed in case of 32-bit alignement of |ptr| values. 253 // guaranteed in case of 32-bit alignement of |ptr| values.
247 254
248 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 255 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
(...skipping 20 matching lines...) Expand all
269 276
270 inline Atomic32 Release_Load(volatile const Atomic32* ptr) { 277 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
271 MemoryBarrier(); 278 MemoryBarrier();
272 return *ptr; 279 return *ptr;
273 } 280 }
274 281
275 } // namespace base::subtle 282 } // namespace base::subtle
276 } // namespace base 283 } // namespace base
277 284
278 #endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ 285 #endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698