diff options
author | Andrew Morrow <acm@mongodb.com> | 2014-05-14 10:41:00 -0400 |
---|---|---|
committer | Andrew Morrow <acm@mongodb.com> | 2014-05-17 15:46:27 -0400 |
commit | 1134c0d1fc3dcbde6a457ecd55de1697d7a13f97 (patch) | |
tree | 0fa755f11b9ac1cf7ea42678ba1c1b8cdca34dca /src/mongo/platform | |
parent | 9df8f46db0152921264a6bd235cfd0fd655bf1bc (diff) | |
download | mongo-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.h | 10 | ||||
-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.h | 110 |
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 |