summaryrefslogtreecommitdiff
path: root/src/mongo/platform
diff options
context:
space:
mode:
authorAndrew Morrow <acm@mongodb.com>2014-05-14 10:41:00 -0400
committerAndrew Morrow <acm@mongodb.com>2014-05-17 15:46:27 -0400
commit1134c0d1fc3dcbde6a457ecd55de1697d7a13f97 (patch)
tree0fa755f11b9ac1cf7ea42678ba1c1b8cdca34dca /src/mongo/platform
parent9df8f46db0152921264a6bd235cfd0fd655bf1bc (diff)
downloadmongo-1134c0d1fc3dcbde6a457ecd55de1697d7a13f97.tar.gz
SERVER-6018 Use gcc __sync primitives if they are available and useable
Diffstat (limited to 'src/mongo/platform')
-rw-r--r--src/mongo/platform/atomic_intrinsics.h10
-rw-r--r--src/mongo/platform/atomic_intrinsics_gcc_atomic.h (renamed from src/mongo/platform/atomic_intrinsics_gcc_generic.h)2
-rw-r--r--src/mongo/platform/atomic_intrinsics_gcc_sync.h110
3 files changed, 114 insertions, 8 deletions
diff --git a/src/mongo/platform/atomic_intrinsics.h b/src/mongo/platform/atomic_intrinsics.h
index c67fa3495fb..d8a60ada361 100644
--- a/src/mongo/platform/atomic_intrinsics.h
+++ b/src/mongo/platform/atomic_intrinsics.h
@@ -54,14 +54,12 @@
#if defined(_WIN32)
#include "mongo/platform/atomic_intrinsics_win32.h"
-#elif defined(__GNUC__)
-#if defined(HAVE_GCC_ATOMIC_BUILTINS)
-#include "mongo/platform/atomic_intrinsics_gcc_generic.h"
+#elif defined(MONGO_HAVE_GCC_ATOMIC_BUILTINS)
+#include "mongo/platform/atomic_intrinsics_gcc_atomic.h"
+#elif defined(MONGO_HAVE_GCC_SYNC_BUILTINS)
+#include "mongo/platform/atomic_intrinsics_gcc_sync.h"
#elif defined(__i386__) || defined(__x86_64__)
#include "mongo/platform/atomic_intrinsics_gcc_intel.h"
#else
-#error "Unsupported platform: no gcc atomic builtins or port available"
-#endif
-#else
#error "Unsupported os/compiler family"
#endif
diff --git a/src/mongo/platform/atomic_intrinsics_gcc_generic.h b/src/mongo/platform/atomic_intrinsics_gcc_atomic.h
index 0848585d312..5e2e7d24a14 100644
--- a/src/mongo/platform/atomic_intrinsics_gcc_generic.h
+++ b/src/mongo/platform/atomic_intrinsics_gcc_atomic.h
@@ -32,8 +32,6 @@
#pragma once
-#include <boost/utility.hpp>
-
namespace mongo {
/**
diff --git a/src/mongo/platform/atomic_intrinsics_gcc_sync.h b/src/mongo/platform/atomic_intrinsics_gcc_sync.h
new file mode 100644
index 00000000000..2ff7b33f4be
--- /dev/null
+++ b/src/mongo/platform/atomic_intrinsics_gcc_sync.h
@@ -0,0 +1,110 @@
+/* Copyright 2014 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of the AtomicIntrinsics<T>::* operations for systems on any
+ * architecture using a GCC 4.1+ compatible compiler toolchain.
+ */
+
+#pragma once
+
+#include <boost/utility.hpp>
+
+namespace mongo {
+
+ /**
+ * Instantiation of AtomicIntrinsics<> for all word types T.
+ */
+ template <typename T, typename IsTLarge=void>
+ class AtomicIntrinsics {
+ public:
+
+ static T compareAndSwap(volatile T* dest, T expected, T newValue) {
+ return __sync_val_compare_and_swap(dest, expected, newValue);
+ }
+
+ static T swap(volatile T* dest, T newValue) {
+ T currentValue = *dest;
+ while (true) {
+ const T result = compareAndSwap(dest, currentValue, newValue);
+ if (result == currentValue)
+ return result;
+ currentValue = result;
+ }
+ }
+
+ static T load(volatile const T* value) {
+ __sync_synchronize();
+ T result = *value;
+ __sync_synchronize();
+ return result;
+ }
+
+ static T loadRelaxed(volatile const T* value) {
+ asm volatile("" ::: "memory");
+ return *value;
+ }
+
+ static void store(volatile T* dest, T newValue) {
+ __sync_synchronize();
+ *dest = newValue;
+ __sync_synchronize();
+ }
+
+ static T fetchAndAdd(volatile T* dest, T increment) {
+ return __sync_fetch_and_add(dest, increment);
+ }
+
+ private:
+ AtomicIntrinsics();
+ ~AtomicIntrinsics();
+ };
+
+ template <typename T>
+ class AtomicIntrinsics<T, typename boost::disable_if_c<sizeof(T) <= sizeof(void*)>::type> {
+ public:
+
+ static T compareAndSwap(volatile T* dest, T expected, T newValue) {
+ return __sync_val_compare_and_swap(dest, expected, newValue);
+ }
+
+ static T swap(volatile T* dest, T newValue) {
+ T currentValue = *dest;
+ while (true) {
+ const T result = compareAndSwap(dest, currentValue, newValue);
+ if (result == currentValue)
+ return result;
+ currentValue = result;
+ }
+ }
+
+ static T load(volatile const T* value) {
+ return compareAndSwap(const_cast<volatile T*>(value), T(0), T(0));
+ }
+
+ static void store(volatile T* dest, T newValue) {
+ swap(dest, newValue);
+ }
+
+ static T fetchAndAdd(volatile T* dest, T increment) {
+ return __sync_fetch_and_add(dest, increment);
+ }
+
+ private:
+ AtomicIntrinsics();
+ ~AtomicIntrinsics();
+ };
+
+} // namespace mongo