1// Copyright 2014 Google Inc. All rights reserved.
2// https://developers.google.com/protocol-buffers/
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// This file is an internal atomic implementation, use atomicops.h instead.
31
32#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
33#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
34
35#include <atomic.h>
36
37namespace google {
38namespace protobuf {
39namespace internal {
40
41inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
42                                         Atomic32 old_value,
43                                         Atomic32 new_value) {
44  return (Atomic32)atomic_cas_32((volatile uint32_t*)ptr, (uint32_t)old_value, (uint32_t)new_value);
45}
46
47inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
48                                         Atomic32 new_value) {
49  return (Atomic32)atomic_swap_32((volatile uint32_t*)ptr, (uint32_t)new_value);
50}
51
52inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
53                                          Atomic32 increment) {
54  return (Atomic32)atomic_add_32_nv((volatile uint32_t*)ptr, (uint32_t)increment);
55}
56
57inline void MemoryBarrier(void) {
58	membar_producer();
59	membar_consumer();
60}
61
62inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
63                                        Atomic32 increment) {
64  MemoryBarrier();
65  Atomic32 ret = NoBarrier_AtomicIncrement(ptr, increment);
66  MemoryBarrier();
67
68  return ret;
69}
70
71inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
72                                       Atomic32 old_value,
73                                       Atomic32 new_value) {
74  Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
75  MemoryBarrier();
76
77  return ret;
78}
79
80inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
81                                       Atomic32 old_value,
82                                       Atomic32 new_value) {
83  MemoryBarrier();
84  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
85}
86
87inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
88  *ptr = value;
89}
90
91inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
92  *ptr = value;
93  membar_producer();
94}
95
96inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
97  membar_consumer();
98  *ptr = value;
99}
100
101inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
102  return *ptr;
103}
104
105inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
106  Atomic32 val = *ptr;
107  membar_consumer();
108  return val;
109}
110
111inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
112  membar_producer();
113  return *ptr;
114}
115
116#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
117inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
118                                         Atomic64 old_value,
119                                         Atomic64 new_value) {
120  return atomic_cas_64((volatile uint64_t*)ptr, (uint64_t)old_value, (uint64_t)new_value);
121}
122
123inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value) {
124  return atomic_swap_64((volatile uint64_t*)ptr, (uint64_t)new_value);
125}
126
127inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) {
128  return atomic_add_64_nv((volatile uint64_t*)ptr, increment);
129}
130
131inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) {
132  MemoryBarrier();
133  Atomic64 ret = atomic_add_64_nv((volatile uint64_t*)ptr, increment);
134  MemoryBarrier();
135  return ret;
136}
137
138inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
139                                       Atomic64 old_value,
140                                       Atomic64 new_value) {
141  Atomic64 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
142  MemoryBarrier();
143  return ret;
144}
145
146inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
147                                       Atomic64 old_value,
148                                       Atomic64 new_value) {
149  MemoryBarrier();
150  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
151}
152
153inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
154  *ptr = value;
155}
156
157inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
158  *ptr = value;
159  membar_producer();
160}
161
162inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
163  membar_consumer();
164  *ptr = value;
165}
166
167inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
168  return *ptr;
169}
170
171inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
172  Atomic64 ret = *ptr;
173  membar_consumer();
174  return ret;
175}
176
177inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
178  membar_producer();
179  return *ptr;
180}
181#endif
182
183}  // namespace internal
184}  // namespace protobuf
185}  // namespace google
186
187#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
188
189