mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 17:10:48 +01:00
SERVER-6018 Use gcc __sync primitives if they are available and useable
This commit is contained in:
parent
9df8f46db0
commit
1134c0d1fc
45
SConstruct
45
SConstruct
@ -1441,17 +1441,52 @@ def doConfigure(myenv):
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
context.Message('Checking for gcc atomic builtins... ')
|
||||
context.Message('Checking for gcc __atomic builtins... ')
|
||||
ret = context.TryLink(textwrap.dedent(test_body), '.cpp')
|
||||
context.Result(ret)
|
||||
return ret
|
||||
|
||||
def CheckGCCSyncBuiltins(context):
|
||||
test_body = """
|
||||
int main(int argc, char **argv) {
|
||||
int a = 0;
|
||||
return __sync_fetch_and_add(&a, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Figure out if we are using gcc older than 4.2 to target 32-bit x86. If so, error out
|
||||
// even if we were able to compile the __sync statement, due to
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40693
|
||||
//
|
||||
#if defined(__i386__)
|
||||
#if !defined(__clang__)
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 2)
|
||||
#error "Refusing to use __sync in 32-bit mode with gcc older than 4.2"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
"""
|
||||
|
||||
context.Message('Checking for useable __sync builtins... ')
|
||||
ret = context.TryLink(textwrap.dedent(test_body), '.cpp')
|
||||
context.Result(ret)
|
||||
return ret
|
||||
|
||||
conf = Configure(myenv, help=False, custom_tests = {
|
||||
'CheckGCCAtomicBuiltins': CheckGCCAtomicBuiltins,
|
||||
'CheckGCCSyncBuiltins': CheckGCCSyncBuiltins,
|
||||
})
|
||||
haveGCCAtomicBuiltins = conf.CheckGCCAtomicBuiltins()
|
||||
conf.Finish()
|
||||
if haveGCCAtomicBuiltins:
|
||||
conf.env.Append(CPPDEFINES=["HAVE_GCC_ATOMIC_BUILTINS"])
|
||||
|
||||
# Prefer the __atomic builtins. If we don't have those, try for __sync. Otherwise
|
||||
# atomic_intrinsics.h will try to fall back to the hand-rolled assembly implementations
|
||||
# in atomic_intrinsics_gcc_intel for x86 platforms.
|
||||
if conf.CheckGCCAtomicBuiltins():
|
||||
conf.env.Append(CPPDEFINES=["MONGO_HAVE_GCC_ATOMIC_BUILTINS"])
|
||||
else:
|
||||
if conf.CheckGCCSyncBuiltins():
|
||||
conf.env.Append(CPPDEFINES=["MONGO_HAVE_GCC_SYNC_BUILTINS"])
|
||||
|
||||
myenv = conf.Finish()
|
||||
|
||||
conf = Configure(myenv)
|
||||
libdeps.setup_conftests(conf)
|
||||
|
@ -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
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
110
src/mongo/platform/atomic_intrinsics_gcc_sync.h
Normal file
110
src/mongo/platform/atomic_intrinsics_gcc_sync.h
Normal file
@ -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
|
@ -30,6 +30,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include "mongo/bson/util/misc.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user