MongoDB C++ Driver  legacy-1.1.2
atomic_intrinsics_gcc_intel.h
1 /* Copyright 2012 10gen Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
21 #pragma once
22 
23 #include <boost/utility.hpp>
24 
25 namespace mongo {
26 
33 template <typename T, typename IsTLarge = void>
34 class AtomicIntrinsics {
35 public:
36  static T compareAndSwap(volatile T* dest, T expected, T newValue) {
37  T result;
38  asm volatile("lock cmpxchg %[src], %[dest]"
39  : [dest] "+m"(*dest), "=a"(result)
40  : [src] "r"(newValue), "a"(expected)
41  : "memory", "cc");
42  return result;
43  }
44 
45  static T swap(volatile T* dest, T newValue) {
46  T result = newValue;
47  // No need for "lock" prefix on "xchg".
48  asm volatile("xchg %[r], %[dest]" : [dest] "+m"(*dest), [r] "+r"(result) : : "memory");
49  return result;
50  }
51 
52  static T load(volatile const T* value) {
53  asm volatile("mfence" ::: "memory");
54  T result = *value;
55  asm volatile("mfence" ::: "memory");
56  return result;
57  }
58 
59  static T loadRelaxed(volatile const T* value) {
60  return *value;
61  }
62 
63  static void store(volatile T* dest, T newValue) {
64  asm volatile("mfence" ::: "memory");
65  *dest = newValue;
66  asm volatile("mfence" ::: "memory");
67  }
68 
69  static T fetchAndAdd(volatile T* dest, T increment) {
70  T result = increment;
71  asm volatile("lock xadd %[src], %[dest]"
72  : [dest] "+m"(*dest), [src] "+r"(result)
73  :
74  : "memory", "cc");
75  return result;
76  }
77 
78 private:
79  AtomicIntrinsics();
80  ~AtomicIntrinsics();
81 };
82 
92 template <typename T>
93 class AtomicIntrinsics<T, typename boost::disable_if_c<sizeof(T) <= sizeof(void*)>::type> {
94 public:
95  static T compareAndSwap(volatile T* dest, T expected, T newValue) {
96  T result = expected;
97  asm volatile(
98  "push %%eax\n"
99  "push %%ebx\n"
100  "push %%ecx\n"
101  "push %%edx\n"
102  "mov (%%edx), %%ebx\n"
103  "mov 4(%%edx), %%ecx\n"
104  "mov (%%edi), %%eax\n"
105  "mov 4(%%edi), %%edx\n"
106  "lock cmpxchg8b (%%esi)\n"
107  "mov %%eax, (%%edi)\n"
108  "mov %%edx, 4(%%edi)\n"
109  "pop %%edx\n"
110  "pop %%ecx\n"
111  "pop %%ebx\n"
112  "pop %%eax\n"
113  :
114  : "S"(dest), "D"(&result), "d"(&newValue)
115  : "memory", "cc");
116  return result;
117  }
118 
119  static T swap(volatile T* dest, T newValue) {
120  T expected;
121  T actual;
122  do {
123  expected = *dest;
124  actual = compareAndSwap(dest, expected, newValue);
125  } while (actual != expected);
126  return actual;
127  }
128 
129  static T load(volatile const T* value) {
130  return compareAndSwap(const_cast<volatile T*>(value), T(0), T(0));
131  }
132 
133  static void store(volatile T* dest, T newValue) {
134  swap(dest, newValue);
135  }
136 
137  static T fetchAndAdd(volatile T* dest, T increment) {
138  T expected;
139  T actual;
140  do {
141  expected = load(dest);
142  actual = compareAndSwap(dest, expected, expected + increment);
143  } while (actual != expected);
144  return actual;
145  }
146 
147 private:
148  AtomicIntrinsics();
149  ~AtomicIntrinsics();
150 };
151 
152 } // namespace mongo
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20