blob: fe7a862a29fdbc0d863508be22cd1c943d298a83 [file] [log] [blame]
[email protected]b2e7f952012-08-22 18:22:031// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file is an internal atomic implementation, include base/atomicops.h
6// instead. This file is for platforms that use GCC intrinsics rather than
7// platform-specific assembly code for atomic operations.
8
9#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_
10#define BASE_ATOMICOPS_INTERNALS_GCC_H_
11
12namespace base {
13namespace subtle {
14
15inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
16 Atomic32 old_value,
17 Atomic32 new_value) {
18 Atomic32 prev_value;
19 do {
20 prev_value = __sync_val_compare_and_swap(ptr, old_value, new_value);
21 } while (prev_value != old_value);
22 return old_value;
23}
24
25inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
26 Atomic32 new_value) {
27 Atomic32 old_value;
28 do {
29 old_value = *ptr;
30 } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
31 return old_value;
32}
33
34inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
35 Atomic32 increment) {
36 return Barrier_AtomicIncrement(ptr, increment);
37}
38
39inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
40 Atomic32 increment) {
41 for (;;) {
42 // Atomic exchange the old value with an incremented one.
43 Atomic32 old_value = *ptr;
44 Atomic32 new_value = old_value + increment;
45 if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
46 // The exchange took place as expected.
47 return new_value;
48 }
49 // Otherwise, *ptr changed mid-loop and we need to retry.
50 }
51}
52
53inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
54 Atomic32 old_value,
55 Atomic32 new_value) {
56 // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which
57 // is a full memory barrier, none is needed here or below in Release.
58 return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
59}
60
61inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
62 Atomic32 old_value,
63 Atomic32 new_value) {
64 return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
65}
66
67inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
68 *ptr = value;
69}
70
71inline void MemoryBarrier() {
72 __sync_synchronize();
73}
74
75inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
76 *ptr = value;
77 MemoryBarrier();
78}
79
80inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
81 MemoryBarrier();
82 *ptr = value;
83}
84
85inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
86 return *ptr;
87}
88
89inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
90 Atomic32 value = *ptr;
91 MemoryBarrier();
92 return value;
93}
94
95inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
96 MemoryBarrier();
97 return *ptr;
98}
99
100} // namespace base::subtle
101} // namespace base
102
103#endif // BASE_ATOMICOPS_INTERNALS_GCC_H_
104