port_posix.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. //
  10. // See port_example.h for documentation for the following types/functions.
  11. #pragma once
  12. #include <thread>
  13. #include "rocksdb/port_defs.h"
  14. #include "rocksdb/rocksdb_namespace.h"
  15. // size_t printf formatting named in the manner of C99 standard formatting
  16. // strings such as PRIu64
  17. // in fact, we could use that one
  18. #define ROCKSDB_PRIszt "zu"
  19. #define __declspec(S)
  20. #undef PLATFORM_IS_LITTLE_ENDIAN
  21. #if defined(OS_MACOSX)
  22. #include <machine/endian.h>
  23. #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER)
  24. #define PLATFORM_IS_LITTLE_ENDIAN \
  25. (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN)
  26. #endif
  27. #elif defined(OS_SOLARIS)
  28. #include <sys/isa_defs.h>
  29. #ifdef _LITTLE_ENDIAN
  30. #define PLATFORM_IS_LITTLE_ENDIAN true
  31. #else
  32. #define PLATFORM_IS_LITTLE_ENDIAN false
  33. #endif
  34. #include <alloca.h>
  35. #elif defined(OS_AIX)
  36. #include <arpa/nameser_compat.h>
  37. #include <sys/types.h>
  38. #define PLATFORM_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
  39. #include <alloca.h>
  40. #elif defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || \
  41. defined(OS_DRAGONFLYBSD) || defined(OS_ANDROID)
  42. #include <sys/endian.h>
  43. #include <sys/types.h>
  44. #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
  45. #else
  46. #include <endian.h>
  47. #endif
  48. #include <pthread.h>
  49. #include <stdint.h>
  50. #include <string.h>
  51. #include <limits>
  52. #include <string>
  53. #ifndef PLATFORM_IS_LITTLE_ENDIAN
  54. #define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
  55. #endif
  56. #if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) || \
  57. defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) || \
  58. defined(OS_ANDROID) || defined(CYGWIN) || defined(OS_AIX)
  59. // Use fread/fwrite/fflush on platforms without _unlocked variants
  60. #define fread_unlocked fread
  61. #define fwrite_unlocked fwrite
  62. #define fflush_unlocked fflush
  63. #endif
  64. #if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || \
  65. defined(OS_DRAGONFLYBSD)
  66. // Use fsync() on platforms without fdatasync()
  67. #define fdatasync fsync
  68. #endif
  69. #if defined(OS_ANDROID) && __ANDROID_API__ < 9
  70. // fdatasync() was only introduced in API level 9 on Android. Use fsync()
  71. // when targeting older platforms.
  72. #define fdatasync fsync
  73. #endif
  74. namespace ROCKSDB_NAMESPACE {
  75. extern const bool kDefaultToAdaptiveMutex;
  76. namespace port {
  77. constexpr bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
  78. #undef PLATFORM_IS_LITTLE_ENDIAN
  79. class CondVar;
  80. class Mutex {
  81. public:
  82. static const char* kName() { return "pthread_mutex_t"; }
  83. explicit Mutex(bool adaptive = kDefaultToAdaptiveMutex);
  84. // No copying
  85. Mutex(const Mutex&) = delete;
  86. void operator=(const Mutex&) = delete;
  87. ~Mutex();
  88. void Lock();
  89. void Unlock();
  90. bool TryLock();
  91. // This will fail assertion if the mutex is not locked.
  92. // It does NOT verify that mutex is held by a calling thread.
  93. void AssertHeld() const;
  94. // Also implement std Lockable
  95. inline void lock() { Lock(); }
  96. inline void unlock() { Unlock(); }
  97. inline bool try_lock() { return TryLock(); }
  98. private:
  99. friend class CondVar;
  100. pthread_mutex_t mu_;
  101. #ifndef NDEBUG
  102. bool locked_ = false;
  103. #endif
  104. };
  105. class RWMutex {
  106. public:
  107. RWMutex();
  108. // No copying allowed
  109. RWMutex(const RWMutex&) = delete;
  110. void operator=(const RWMutex&) = delete;
  111. ~RWMutex();
  112. void ReadLock();
  113. void WriteLock();
  114. void ReadUnlock();
  115. void WriteUnlock();
  116. void AssertHeld() const {}
  117. private:
  118. pthread_rwlock_t mu_; // the underlying platform mutex
  119. };
  120. class CondVar {
  121. public:
  122. explicit CondVar(Mutex* mu);
  123. ~CondVar();
  124. Mutex* GetMutex() const { return mu_; }
  125. void Wait();
  126. // Timed condition wait. Returns true if timeout occurred.
  127. bool TimedWait(uint64_t abs_time_us);
  128. void Signal();
  129. void SignalAll();
  130. private:
  131. pthread_cond_t cv_;
  132. Mutex* mu_;
  133. };
  134. using Thread = std::thread;
  135. static inline void AsmVolatilePause() {
  136. #if defined(__i386__) || defined(__x86_64__)
  137. asm volatile("pause");
  138. #elif defined(__aarch64__)
  139. asm volatile("isb");
  140. #elif defined(__powerpc64__)
  141. asm volatile("or 27,27,27");
  142. #elif defined(__loongarch64)
  143. asm volatile("dbar 0");
  144. #endif
  145. // it's okay for other platforms to be no-ops
  146. }
  147. // Returns -1 if not available on this platform
  148. int PhysicalCoreID();
  149. using OnceType = pthread_once_t;
  150. #define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
  151. void InitOnce(OnceType* once, void (*initializer)());
  152. #ifndef CACHE_LINE_SIZE
  153. // To test behavior with non-native cache line size, e.g. for
  154. // Bloom filters, set TEST_CACHE_LINE_SIZE to the desired test size.
  155. // This disables ALIGN_AS to keep it from failing compilation.
  156. #ifdef TEST_CACHE_LINE_SIZE
  157. #define CACHE_LINE_SIZE TEST_CACHE_LINE_SIZE
  158. #define ALIGN_AS(n) /*empty*/
  159. #else
  160. #if defined(__s390__)
  161. #if defined(__GNUC__) && __GNUC__ < 7
  162. #define CACHE_LINE_SIZE 64U
  163. #else
  164. #define CACHE_LINE_SIZE 256U
  165. #endif
  166. #elif defined(__powerpc__) || defined(__aarch64__)
  167. #define CACHE_LINE_SIZE 128U
  168. #else
  169. #define CACHE_LINE_SIZE 64U
  170. #endif
  171. #define ALIGN_AS(n) alignas(n)
  172. #endif
  173. #endif
  174. static_assert((CACHE_LINE_SIZE & (CACHE_LINE_SIZE - 1)) == 0,
  175. "Cache line size must be a power of 2 number of bytes");
  176. void* cacheline_aligned_alloc(size_t size);
  177. void cacheline_aligned_free(void* memblock);
  178. #if defined(__aarch64__)
  179. // __builtin_prefetch(..., 1) turns into a prefetch into prfm pldl3keep. On
  180. // arm64 we want this as close to the core as possible to turn it into a
  181. // L1 prefetech unless locality == 0 in which case it will be turned into a
  182. // non-temporal prefetch
  183. #define PREFETCH(addr, rw, locality) \
  184. __builtin_prefetch(addr, rw, locality >= 1 ? 3 : locality)
  185. #else
  186. #define PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
  187. #endif
  188. void Crash(const std::string& srcfile, int srcline);
  189. int GetMaxOpenFiles();
  190. extern const size_t kPageSize;
  191. using ThreadId = pid_t;
  192. void SetCpuPriority(ThreadId id, CpuPriority priority);
  193. int64_t GetProcessID();
  194. // Uses platform APIs to generate a 36-character RFC-4122 UUID. Returns
  195. // true on success or false on failure.
  196. bool GenerateRfcUuid(std::string* output);
  197. } // namespace port
  198. } // namespace ROCKSDB_NAMESPACE