MongoDB C++ Driver legacy-1.1.1
Loading...
Searching...
No Matches
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
25namespace mongo {
26
33template <typename T, typename IsTLarge = void>
34class AtomicIntrinsics {
35public:
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
78private:
79 AtomicIntrinsics();
80 ~AtomicIntrinsics();
81};
82
92template <typename T>
93class AtomicIntrinsics<T, typename boost::disable_if_c<sizeof(T) <= sizeof(void*)>::type> {
94public:
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
147private:
148 AtomicIntrinsics();
149 ~AtomicIntrinsics();
150};
151
152} // namespace mongo
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:32