1// Protocol Buffers - Google's data interchange format
2// Copyright 2012 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
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// The compilation of extension_set.cc fails when windows.h is included.
32// Therefore we move the code depending on windows.h to this separate cc file.
33
34// Don't compile this file for people not concerned about thread safety.
35#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
36
37#include <google/protobuf/stubs/atomicops.h>
38
39#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
40
41#include <windows.h>
42
43namespace google {
44namespace protobuf {
45namespace internal {
46
47inline void MemoryBarrier() {
48  // We use MemoryBarrier from WinNT.h
49  ::MemoryBarrier();
50}
51
52Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
53                                  Atomic32 old_value,
54                                  Atomic32 new_value) {
55  LONG result = InterlockedCompareExchange(
56      reinterpret_cast<volatile LONG*>(ptr),
57      static_cast<LONG>(new_value),
58      static_cast<LONG>(old_value));
59  return static_cast<Atomic32>(result);
60}
61
62Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
63                                  Atomic32 new_value) {
64  LONG result = InterlockedExchange(
65      reinterpret_cast<volatile LONG*>(ptr),
66      static_cast<LONG>(new_value));
67  return static_cast<Atomic32>(result);
68}
69
70Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
71                                 Atomic32 increment) {
72  return InterlockedExchangeAdd(
73      reinterpret_cast<volatile LONG*>(ptr),
74      static_cast<LONG>(increment)) + increment;
75}
76
77#if defined(_WIN64)
78
79// 64-bit low-level operations on 64-bit platform.
80
81Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
82                                  Atomic64 old_value,
83                                  Atomic64 new_value) {
84  PVOID result = InterlockedCompareExchangePointer(
85    reinterpret_cast<volatile PVOID*>(ptr),
86    reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
87  return reinterpret_cast<Atomic64>(result);
88}
89
90Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
91                                  Atomic64 new_value) {
92  PVOID result = InterlockedExchangePointer(
93    reinterpret_cast<volatile PVOID*>(ptr),
94    reinterpret_cast<PVOID>(new_value));
95  return reinterpret_cast<Atomic64>(result);
96}
97
98Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
99                                 Atomic64 increment) {
100  return InterlockedExchangeAdd64(
101      reinterpret_cast<volatile LONGLONG*>(ptr),
102      static_cast<LONGLONG>(increment)) + increment;
103}
104
105#endif  // defined(_WIN64)
106
107}  // namespace internal
108}  // namespace protobuf
109}  // namespace google
110
111#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
112#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
113