~james-page/ubuntu/precise/ceph/cloud-archive

« back to all changes in this revision

Viewing changes to src/leveldb/port/atomic_pointer.h

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-07-19 08:28:18 UTC
  • Revision ID: package-import@ubuntu.com-20120719082818-rdnt9r2hc0ced8n5
Tags: 0.48-1ubuntu2
* Drop use of in-tree dependencies, re-align with Debian:
  - d/patches/{intree_leveldb|add-powerpc-support}.patch: Dropped.
  - d/patches/series: Use patches to support lib{leveldb|s3}-dev usage.
  - d/control: BD on libsnappy-dev, liblevedb-dev, libs3-dev.
  - d/rules: Use system provided leveldb and libs3.
  - d/rules: Enable hardening.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
 
// Use of this source code is governed by a BSD-style license that can be
3
 
// found in the LICENSE file. See the AUTHORS file for names of contributors.
4
 
 
5
 
// AtomicPointer provides storage for a lock-free pointer.
6
 
// Platform-dependent implementation of AtomicPointer:
7
 
// - If the platform provides a cheap barrier, we use it with raw pointers
8
 
// - If cstdatomic is present (on newer versions of gcc, it is), we use
9
 
//   a cstdatomic-based AtomicPointer.  However we prefer the memory
10
 
//   barrier based version, because at least on a gcc 4.4 32-bit build
11
 
//   on linux, we have encountered a buggy <cstdatomic>
12
 
//   implementation.  Also, some <cstdatomic> implementations are much
13
 
//   slower than a memory-barrier based implementation (~16ns for
14
 
//   <cstdatomic> based acquire-load vs. ~1ns for a barrier based
15
 
//   acquire-load).
16
 
// This code is based on atomicops-internals-* in Google's perftools:
17
 
// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase
18
 
 
19
 
#ifndef PORT_ATOMIC_POINTER_H_
20
 
#define PORT_ATOMIC_POINTER_H_
21
 
 
22
 
#include <stdint.h>
23
 
#ifdef LEVELDB_CSTDATOMIC_PRESENT
24
 
#include <cstdatomic>
25
 
#endif
26
 
#ifdef OS_WIN
27
 
#include <windows.h>
28
 
#endif
29
 
#ifdef OS_MACOSX
30
 
#include <libkern/OSAtomic.h>
31
 
#endif
32
 
 
33
 
#if defined(_M_X64) || defined(__x86_64__)
34
 
#define ARCH_CPU_X86_FAMILY 1
35
 
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
36
 
#define ARCH_CPU_X86_FAMILY 1
37
 
#elif defined(__ARMEL__)
38
 
#define ARCH_CPU_ARM_FAMILY 1
39
 
#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__)
40
 
#define ARCH_CPU_PPC_FAMILY 1
41
 
#endif
42
 
 
43
 
namespace leveldb {
44
 
namespace port {
45
 
 
46
 
// Define MemoryBarrier() if available
47
 
// Windows on x86
48
 
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
49
 
// windows.h already provides a MemoryBarrier(void) macro
50
 
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
51
 
#define LEVELDB_HAVE_MEMORY_BARRIER
52
 
 
53
 
// Gcc on x86
54
 
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
55
 
inline void MemoryBarrier() {
56
 
  // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
57
 
  // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
58
 
  __asm__ __volatile__("" : : : "memory");
59
 
}
60
 
#define LEVELDB_HAVE_MEMORY_BARRIER
61
 
 
62
 
// Sun Studio
63
 
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC)
64
 
inline void MemoryBarrier() {
65
 
  // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
66
 
  // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
67
 
  asm volatile("" : : : "memory");
68
 
}
69
 
#define LEVELDB_HAVE_MEMORY_BARRIER
70
 
 
71
 
// Mac OS
72
 
#elif defined(OS_MACOSX)
73
 
inline void MemoryBarrier() {
74
 
  OSMemoryBarrier();
75
 
}
76
 
#define LEVELDB_HAVE_MEMORY_BARRIER
77
 
 
78
 
// ARM
79
 
#elif defined(ARCH_CPU_ARM_FAMILY)
80
 
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
81
 
LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
82
 
    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
83
 
inline void MemoryBarrier() {
84
 
  pLinuxKernelMemoryBarrier();
85
 
}
86
 
#define LEVELDB_HAVE_MEMORY_BARRIER
87
 
 
88
 
// PPC
89
 
#elif defined(ARCH_CPU_PPC_FAMILY)
90
 
inline void MemoryBarrier() {
91
 
  __asm__ __volatile__ ("sync" : : : "memory");
92
 
}
93
 
#define LEVELDB_HAVE_MEMORY_BARRIER
94
 
 
95
 
#endif
96
 
 
97
 
// AtomicPointer built using platform-specific MemoryBarrier()
98
 
#if defined(LEVELDB_HAVE_MEMORY_BARRIER)
99
 
class AtomicPointer {
100
 
 private:
101
 
  void* rep_;
102
 
 public:
103
 
  AtomicPointer() { }
104
 
  explicit AtomicPointer(void* p) : rep_(p) {}
105
 
  inline void* NoBarrier_Load() const { return rep_; }
106
 
  inline void NoBarrier_Store(void* v) { rep_ = v; }
107
 
  inline void* Acquire_Load() const {
108
 
    void* result = rep_;
109
 
    MemoryBarrier();
110
 
    return result;
111
 
  }
112
 
  inline void Release_Store(void* v) {
113
 
    MemoryBarrier();
114
 
    rep_ = v;
115
 
  }
116
 
};
117
 
 
118
 
// AtomicPointer based on <cstdatomic>
119
 
#elif defined(LEVELDB_CSTDATOMIC_PRESENT)
120
 
class AtomicPointer {
121
 
 private:
122
 
  std::atomic<void*> rep_;
123
 
 public:
124
 
  AtomicPointer() { }
125
 
  explicit AtomicPointer(void* v) : rep_(v) { }
126
 
  inline void* Acquire_Load() const {
127
 
    return rep_.load(std::memory_order_acquire);
128
 
  }
129
 
  inline void Release_Store(void* v) {
130
 
    rep_.store(v, std::memory_order_release);
131
 
  }
132
 
  inline void* NoBarrier_Load() const {
133
 
    return rep_.load(std::memory_order_relaxed);
134
 
  }
135
 
  inline void NoBarrier_Store(void* v) {
136
 
    rep_.store(v, std::memory_order_relaxed);
137
 
  }
138
 
};
139
 
 
140
 
// We have neither MemoryBarrier(), nor <cstdatomic>
141
 
#else
142
 
#error Please implement AtomicPointer for this platform.
143
 
 
144
 
#endif
145
 
 
146
 
#undef LEVELDB_HAVE_MEMORY_BARRIER
147
 
#undef ARCH_CPU_X86_FAMILY
148
 
#undef ARCH_CPU_ARM_FAMILY
149
 
#undef ARCH_CPU_PPC_FAMILY
150
 
 
151
 
}  // namespace port
152
 
}  // namespace leveldb
153
 
 
154
 
#endif  // PORT_ATOMIC_POINTER_H_