1// Protocol Buffers - Google's data interchange format
2// Copyright 2012 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// This file is an internal atomic implementation, use atomicops.h instead.
32
33#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
34#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
35
36namespace google {
37namespace protobuf {
38namespace internal {
39
40inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
41                                          Atomic32 increment) {
42  return Barrier_AtomicIncrement(ptr, increment);
43}
44
45#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
46#error "We require at least vs2005 for MemoryBarrier"
47#endif
48
49inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
50                                       Atomic32 old_value,
51                                       Atomic32 new_value) {
52  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
53}
54
55inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
56                                       Atomic32 old_value,
57                                       Atomic32 new_value) {
58  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
59}
60
61inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
62  *ptr = value;
63}
64
65inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
66  NoBarrier_AtomicExchange(ptr, value);
67              // acts as a barrier in this implementation
68}
69
70inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
71  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
72  // See comments in Atomic64 version of Release_Store() below.
73}
74
75inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
76  return *ptr;
77}
78
79inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
80  Atomic32 value = *ptr;
81  return value;
82}
83
84inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
85  MemoryBarrier();
86  return *ptr;
87}
88
89#if defined(_WIN64)
90
91// 64-bit low-level operations on 64-bit platform.
92
93inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
94                                          Atomic64 increment) {
95  return Barrier_AtomicIncrement(ptr, increment);
96}
97
98inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
99  *ptr = value;
100}
101
102inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
103  NoBarrier_AtomicExchange(ptr, value);
104              // acts as a barrier in this implementation
105}
106
107inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
108  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
109
110  // When new chips come out, check:
111  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
112  //  System Programming Guide, Chatper 7: Multiple-processor management,
113  //  Section 7.2, Memory Ordering.
114  // Last seen at:
115  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
116}
117
118inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
119  return *ptr;
120}
121
122inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
123  Atomic64 value = *ptr;
124  return value;
125}
126
127inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
128  MemoryBarrier();
129  return *ptr;
130}
131
132inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
133                                       Atomic64 old_value,
134                                       Atomic64 new_value) {
135  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
136}
137
138inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
139                                       Atomic64 old_value,
140                                       Atomic64 new_value) {
141  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
142}
143
144#endif  // defined(_WIN64)
145
146}  // namespace internal
147}  // namespace protobuf
148}  // namespace google
149
150#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
151