port_posix.h 6.4 KB
Newer Older
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
S
Siying Dong 已提交
2 3 4
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
5
//
J
jorlow@chromium.org 已提交
6 7 8 9 10 11
// 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.
//
// See port_example.h for documentation for the following types/functions.

12
#pragma once
J
jorlow@chromium.org 已提交
13

D
Dmitri Smirnov 已提交
14
#include <thread>
15

16
#include "rocksdb/options.h"
17 18
#include "rocksdb/rocksdb_namespace.h"

S
sdong 已提交
19 20
// size_t printf formatting named in the manner of C99 standard formatting
// strings such as PRIu64
D
Dmitri Smirnov 已提交
21 22 23
// in fact, we could use that one
#define ROCKSDB_PRIszt "zu"

D
Dmitri Smirnov 已提交
24 25
#define __declspec(S)

H
heyongqiang 已提交
26
#undef PLATFORM_IS_LITTLE_ENDIAN
27
#if defined(OS_MACOSX)
S
sdong 已提交
28 29 30 31 32
#include <machine/endian.h>
#if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER)
#define PLATFORM_IS_LITTLE_ENDIAN \
  (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN)
#endif
33
#elif defined(OS_SOLARIS)
S
sdong 已提交
34 35 36 37 38 39 40
#include <sys/isa_defs.h>
#ifdef _LITTLE_ENDIAN
#define PLATFORM_IS_LITTLE_ENDIAN true
#else
#define PLATFORM_IS_LITTLE_ENDIAN false
#endif
#include <alloca.h>
T
Tomas Kolda 已提交
41
#elif defined(OS_AIX)
S
sdong 已提交
42 43 44 45
#include <arpa/nameser_compat.h>
#include <sys/types.h>
#define PLATFORM_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
#include <alloca.h>
I
Islam AbdelRahman 已提交
46 47
#elif defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || \
    defined(OS_DRAGONFLYBSD) || defined(OS_ANDROID)
S
sdong 已提交
48 49 50
#include <sys/endian.h>
#include <sys/types.h>
#define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
51
#else
S
sdong 已提交
52
#include <endian.h>
53
#endif
J
jorlow@chromium.org 已提交
54 55
#include <pthread.h>
#include <stdint.h>
H
heyongqiang 已提交
56
#include <string.h>
S
sdong 已提交
57

58 59
#include <limits>
#include <string>
60

H
heyongqiang 已提交
61 62
#ifndef PLATFORM_IS_LITTLE_ENDIAN
#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
63 64
#endif

S
sdong 已提交
65 66
#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||      \
    defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) || \
T
Tomas Kolda 已提交
67
    defined(OS_ANDROID) || defined(CYGWIN) || defined(OS_AIX)
68
// Use fread/fwrite/fflush on platforms without _unlocked variants
69 70 71 72 73
#define fread_unlocked fread
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif

S
sdong 已提交
74 75
#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || \
    defined(OS_DRAGONFLYBSD)
76
// Use fsync() on platforms without fdatasync()
77 78
#define fdatasync fsync
#endif
J
jorlow@chromium.org 已提交
79

H
heyongqiang 已提交
80 81
#if defined(OS_ANDROID) && __ANDROID_API__ < 9
// fdatasync() was only introduced in API level 9 on Android. Use fsync()
C
charsyam 已提交
82
// when targeting older platforms.
H
heyongqiang 已提交
83 84 85
#define fdatasync fsync
#endif

86
namespace ROCKSDB_NAMESPACE {
87 88 89

extern const bool kDefaultToAdaptiveMutex;

J
jorlow@chromium.org 已提交
90
namespace port {
91
constexpr bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
H
heyongqiang 已提交
92
#undef PLATFORM_IS_LITTLE_ENDIAN
J
jorlow@chromium.org 已提交
93 94 95 96 97

class CondVar;

class Mutex {
 public:
98 99
  static const char* kName() { return "pthread_mutex_t"; }

100
  explicit Mutex(bool adaptive = kDefaultToAdaptiveMutex);
101 102 103 104
  // No copying
  Mutex(const Mutex&) = delete;
  void operator=(const Mutex&) = delete;

J
jorlow@chromium.org 已提交
105 106 107 108
  ~Mutex();

  void Lock();
  void Unlock();
109 110 111

  bool TryLock();

112 113
  // this will assert if the mutex is not locked
  // it does NOT verify that mutex is held by a calling thread
I
Igor Canadi 已提交
114
  void AssertHeld();
J
jorlow@chromium.org 已提交
115

116 117 118 119 120
  // Also implement std Lockable
  inline void lock() { Lock(); }
  inline void unlock() { Unlock(); }
  inline bool try_lock() { return TryLock(); }

J
jorlow@chromium.org 已提交
121 122 123
 private:
  friend class CondVar;
  pthread_mutex_t mu_;
I
Igor Canadi 已提交
124
#ifndef NDEBUG
125
  bool locked_ = false;
I
Igor Canadi 已提交
126
#endif
J
jorlow@chromium.org 已提交
127 128
};

129 130 131
class RWMutex {
 public:
  RWMutex();
132 133 134 135
  // No copying allowed
  RWMutex(const RWMutex&) = delete;
  void operator=(const RWMutex&) = delete;

136 137 138 139
  ~RWMutex();

  void ReadLock();
  void WriteLock();
140 141
  void ReadUnlock();
  void WriteUnlock();
S
sdong 已提交
142
  void AssertHeld() {}
143 144

 private:
S
sdong 已提交
145
  pthread_rwlock_t mu_;  // the underlying platform mutex
146 147
};

J
jorlow@chromium.org 已提交
148 149 150 151 152
class CondVar {
 public:
  explicit CondVar(Mutex* mu);
  ~CondVar();
  void Wait();
153 154
  // Timed condition wait.  Returns true if timeout occurred.
  bool TimedWait(uint64_t abs_time_us);
J
jorlow@chromium.org 已提交
155 156
  void Signal();
  void SignalAll();
S
sdong 已提交
157

J
jorlow@chromium.org 已提交
158 159 160 161 162
 private:
  pthread_cond_t cv_;
  Mutex* mu_;
};

D
Dmitri Smirnov 已提交
163 164
using Thread = std::thread;

165 166 167 168
static inline void AsmVolatilePause() {
#if defined(__i386__) || defined(__x86_64__)
  asm volatile("pause");
#elif defined(__aarch64__)
169
  asm volatile("isb");
170 171
#elif defined(__powerpc64__)
  asm volatile("or 27,27,27");
172 173
#elif defined(__loongarch64)
  asm volatile("dbar 0");
174 175 176 177 178 179 180
#endif
  // it's okay for other platforms to be no-ops
}

// Returns -1 if not available on this platform
extern int PhysicalCoreID();

181
using OnceType = pthread_once_t;
H
heyongqiang 已提交
182 183 184
#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
extern void InitOnce(OnceType* once, void (*initializer)());

185
#ifndef CACHE_LINE_SIZE
186 187 188 189 190 191 192 193
// To test behavior with non-native cache line size, e.g. for
// Bloom filters, set TEST_CACHE_LINE_SIZE to the desired test size.
// This disables ALIGN_AS to keep it from failing compilation.
#ifdef TEST_CACHE_LINE_SIZE
#define CACHE_LINE_SIZE TEST_CACHE_LINE_SIZE
#define ALIGN_AS(n) /*empty*/
#else
#if defined(__s390__)
194
#if defined(__GNUC__) && __GNUC__ < 7
195 196
#define CACHE_LINE_SIZE 64U
#else
197
#define CACHE_LINE_SIZE 256U
198
#endif
199 200 201 202 203 204 205
#elif defined(__powerpc__) || defined(__aarch64__)
#define CACHE_LINE_SIZE 128U
#else
#define CACHE_LINE_SIZE 64U
#endif
#define ALIGN_AS(n) alignas(n)
#endif
206
#endif
L
Lei Jin 已提交
207

208 209
static_assert((CACHE_LINE_SIZE & (CACHE_LINE_SIZE - 1)) == 0,
              "Cache line size must be a power of 2 number of bytes");
210

S
sdong 已提交
211
extern void* cacheline_aligned_alloc(size_t size);
212

S
sdong 已提交
213
extern void cacheline_aligned_free(void* memblock);
214

215 216 217 218 219 220 221 222
#if defined(__aarch64__)
//  __builtin_prefetch(..., 1) turns into a prefetch into prfm pldl3keep. On
// arm64 we want this as close to the core as possible to turn it into a
// L1 prefetech unless locality == 0 in which case it will be turned into a
// non-temporal prefetch
#define PREFETCH(addr, rw, locality) \
  __builtin_prefetch(addr, rw, locality >= 1 ? 3 : locality)
#else
223
#define PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
224
#endif
225

226
extern void Crash(const std::string& srcfile, int srcline);
I
Igor Canadi 已提交
227 228 229

extern int GetMaxOpenFiles();

230 231
extern const size_t kPageSize;

232 233 234 235
using ThreadId = pid_t;

extern void SetCpuPriority(ThreadId id, CpuPriority priority);

236 237
int64_t GetProcessID();

238 239 240 241
// Uses platform APIs to generate a 36-character RFC-4122 UUID. Returns
// true on success or false on failure.
bool GenerateRfcUuid(std::string* output);

S
sdong 已提交
242
}  // namespace port
243
}  // namespace ROCKSDB_NAMESPACE