Summary: RocksDB already depends on C++11, so we might as well all the goodness that C++11 provides. This means that we don't need AtomicPointer anymore. The less things in port/, the easier it will be to port to other platforms. Test Plan: make check + careful visual review verifying that NoBarried got memory_order_relaxed, while Acquire/Release methods got memory_order_acquire and memory_order_release Reviewers: rven, yhchiang, ljin, sdong Reviewed By: ljin Subscribers: leveldb Differential Revision: https://reviews.facebook.net/D27543main
parent
f37048ad1d
commit
48842ab316
@ -1,157 +0,0 @@ |
||||
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
// AtomicPointer provides storage for a lock-free pointer.
|
||||
// Platform-dependent implementation of AtomicPointer:
|
||||
// - If the platform provides a cheap barrier, we use it with raw pointers
|
||||
// - If cstdatomic is present (on newer versions of gcc, it is), we use
|
||||
// a cstdatomic-based AtomicPointer. However we prefer the memory
|
||||
// barrier based version, because at least on a gcc 4.4 32-bit build
|
||||
// on linux, we have encountered a buggy <cstdatomic>
|
||||
// implementation. Also, some <cstdatomic> implementations are much
|
||||
// slower than a memory-barrier based implementation (~16ns for
|
||||
// <cstdatomic> based acquire-load vs. ~1ns for a barrier based
|
||||
// acquire-load).
|
||||
// This code is based on atomicops-internals-* in Google's perftools:
|
||||
// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase
|
||||
|
||||
#ifndef PORT_ATOMIC_POINTER_H_ |
||||
#define PORT_ATOMIC_POINTER_H_ |
||||
|
||||
#include <stdint.h> |
||||
#ifdef ROCKSDB_ATOMIC_PRESENT |
||||
#include <atomic> |
||||
#endif |
||||
#ifdef OS_WIN |
||||
#include <windows.h> |
||||
#endif |
||||
#ifdef OS_MACOSX |
||||
#include <libkern/OSAtomic.h> |
||||
#endif |
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__) |
||||
#define ARCH_CPU_X86_FAMILY 1 |
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) |
||||
#define ARCH_CPU_X86_FAMILY 1 |
||||
#elif defined(__ARMEL__) |
||||
#define ARCH_CPU_ARM_FAMILY 1 |
||||
#endif |
||||
|
||||
namespace rocksdb { |
||||
namespace port { |
||||
|
||||
// Define MemoryBarrier() if available
|
||||
// Windows on x86
|
||||
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) |
||||
// windows.h already provides a MemoryBarrier(void) macro
|
||||
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
|
||||
#define ROCKSDB_HAVE_MEMORY_BARRIER |
||||
|
||||
// Gcc on x86
|
||||
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__) |
||||
inline void MemoryBarrier() { |
||||
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
||||
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
||||
__asm__ __volatile__("" : : : "memory"); |
||||
} |
||||
#define ROCKSDB_HAVE_MEMORY_BARRIER |
||||
|
||||
// Sun Studio
|
||||
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC) |
||||
inline void MemoryBarrier() { |
||||
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
||||
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
||||
asm volatile("" : : : "memory"); |
||||
} |
||||
#define ROCKSDB_HAVE_MEMORY_BARRIER |
||||
|
||||
// Mac OS
|
||||
#elif defined(OS_MACOSX) |
||||
inline void MemoryBarrier() { |
||||
OSMemoryBarrier(); |
||||
} |
||||
#define ROCKSDB_HAVE_MEMORY_BARRIER |
||||
|
||||
// ARM Linux
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) |
||||
typedef void (*LinuxKernelMemoryBarrierFunc)(void); |
||||
// The Linux ARM kernel provides a highly optimized device-specific memory
|
||||
// barrier function at a fixed memory address that is mapped in every
|
||||
// user-level process.
|
||||
//
|
||||
// This beats using CPU-specific instructions which are, on single-core
|
||||
// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more
|
||||
// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking
|
||||
// shows that the extra function call cost is completely negligible on
|
||||
// multi-core devices.
|
||||
//
|
||||
inline void MemoryBarrier() { |
||||
(*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); |
||||
} |
||||
#define ROCKSDB_HAVE_MEMORY_BARRIER |
||||
|
||||
#endif |
||||
|
||||
// AtomicPointer built using platform-specific MemoryBarrier()
|
||||
#if defined(ROCKSDB_HAVE_MEMORY_BARRIER) |
||||
class AtomicPointer { |
||||
private: |
||||
void* rep_; |
||||
public: |
||||
AtomicPointer() { } |
||||
explicit AtomicPointer(void* p) : rep_(p) {} |
||||
inline void* NoBarrier_Load() const { return rep_; } |
||||
inline void NoBarrier_Store(void* v) { rep_ = v; } |
||||
inline void* Acquire_Load() const { |
||||
void* result = rep_; |
||||
MemoryBarrier(); |
||||
return result; |
||||
} |
||||
inline void Release_Store(void* v) { |
||||
MemoryBarrier(); |
||||
rep_ = v; |
||||
} |
||||
}; |
||||
|
||||
// AtomicPointer based on <atomic>
|
||||
#elif defined(ROCKSDB_ATOMIC_PRESENT) |
||||
class AtomicPointer { |
||||
private: |
||||
std::atomic<void*> rep_; |
||||
public: |
||||
AtomicPointer() { } |
||||
explicit AtomicPointer(void* v) : rep_(v) { } |
||||
inline void* Acquire_Load() const { |
||||
return rep_.load(std::memory_order_acquire); |
||||
} |
||||
inline void Release_Store(void* v) { |
||||
rep_.store(v, std::memory_order_release); |
||||
} |
||||
inline void* NoBarrier_Load() const { |
||||
return rep_.load(std::memory_order_relaxed); |
||||
} |
||||
inline void NoBarrier_Store(void* v) { |
||||
rep_.store(v, std::memory_order_relaxed); |
||||
} |
||||
}; |
||||
|
||||
// We have neither MemoryBarrier(), nor <cstdatomic>
|
||||
#else |
||||
#error Please implement AtomicPointer for this platform. |
||||
|
||||
#endif |
||||
|
||||
#undef ROCKSDB_HAVE_MEMORY_BARRIER |
||||
#undef ARCH_CPU_X86_FAMILY |
||||
#undef ARCH_CPU_ARM_FAMILY |
||||
|
||||
} // namespace port
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // PORT_ATOMIC_POINTER_H_
|
Loading…
Reference in new issue