port_posix.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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/rocksdb_namespace.h"
  14. // size_t printf formatting named in the manner of C99 standard formatting
  15. // strings such as PRIu64
  16. // in fact, we could use that one
  17. #define ROCKSDB_PRIszt "zu"
  18. #define __declspec(S)
  19. #define ROCKSDB_NOEXCEPT noexcept
  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 <sys/types.h>
  37. #include <arpa/nameser_compat.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) ||\
  65. defined(OS_OPENBSD) || 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. // For use at db/file_indexer.h kLevelMaxIndex
  78. const uint32_t kMaxUint32 = std::numeric_limits<uint32_t>::max();
  79. const int kMaxInt32 = std::numeric_limits<int32_t>::max();
  80. const int kMinInt32 = std::numeric_limits<int32_t>::min();
  81. const uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max();
  82. const int64_t kMaxInt64 = std::numeric_limits<int64_t>::max();
  83. const int64_t kMinInt64 = std::numeric_limits<int64_t>::min();
  84. const size_t kMaxSizet = std::numeric_limits<size_t>::max();
  85. constexpr bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
  86. #undef PLATFORM_IS_LITTLE_ENDIAN
  87. class CondVar;
  88. class Mutex {
  89. public:
  90. explicit Mutex(bool adaptive = kDefaultToAdaptiveMutex);
  91. // No copying
  92. Mutex(const Mutex&) = delete;
  93. void operator=(const Mutex&) = delete;
  94. ~Mutex();
  95. void Lock();
  96. void Unlock();
  97. // this will assert if the mutex is not locked
  98. // it does NOT verify that mutex is held by a calling thread
  99. void AssertHeld();
  100. private:
  101. friend class CondVar;
  102. pthread_mutex_t mu_;
  103. #ifndef NDEBUG
  104. bool locked_;
  105. #endif
  106. };
  107. class RWMutex {
  108. public:
  109. RWMutex();
  110. // No copying allowed
  111. RWMutex(const RWMutex&) = delete;
  112. void operator=(const RWMutex&) = delete;
  113. ~RWMutex();
  114. void ReadLock();
  115. void WriteLock();
  116. void ReadUnlock();
  117. void WriteUnlock();
  118. void AssertHeld() { }
  119. private:
  120. pthread_rwlock_t mu_; // the underlying platform mutex
  121. };
  122. class CondVar {
  123. public:
  124. explicit CondVar(Mutex* mu);
  125. ~CondVar();
  126. void Wait();
  127. // Timed condition wait. Returns true if timeout occurred.
  128. bool TimedWait(uint64_t abs_time_us);
  129. void Signal();
  130. void SignalAll();
  131. private:
  132. pthread_cond_t cv_;
  133. Mutex* mu_;
  134. };
  135. using Thread = std::thread;
  136. static inline void AsmVolatilePause() {
  137. #if defined(__i386__) || defined(__x86_64__)
  138. asm volatile("pause");
  139. #elif defined(__aarch64__)
  140. asm volatile("wfe");
  141. #elif defined(__powerpc64__)
  142. asm volatile("or 27,27,27");
  143. #endif
  144. // it's okay for other platforms to be no-ops
  145. }
  146. // Returns -1 if not available on this platform
  147. extern int PhysicalCoreID();
  148. typedef pthread_once_t OnceType;
  149. #define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
  150. extern void InitOnce(OnceType* once, void (*initializer)());
  151. #ifndef CACHE_LINE_SIZE
  152. // To test behavior with non-native cache line size, e.g. for
  153. // Bloom filters, set TEST_CACHE_LINE_SIZE to the desired test size.
  154. // This disables ALIGN_AS to keep it from failing compilation.
  155. #ifdef TEST_CACHE_LINE_SIZE
  156. #define CACHE_LINE_SIZE TEST_CACHE_LINE_SIZE
  157. #define ALIGN_AS(n) /*empty*/
  158. #else
  159. #if defined(__s390__)
  160. #define CACHE_LINE_SIZE 256U
  161. #elif defined(__powerpc__) || defined(__aarch64__)
  162. #define CACHE_LINE_SIZE 128U
  163. #else
  164. #define CACHE_LINE_SIZE 64U
  165. #endif
  166. #define ALIGN_AS(n) alignas(n)
  167. #endif
  168. #endif
  169. static_assert((CACHE_LINE_SIZE & (CACHE_LINE_SIZE - 1)) == 0,
  170. "Cache line size must be a power of 2 number of bytes");
  171. extern void *cacheline_aligned_alloc(size_t size);
  172. extern void cacheline_aligned_free(void *memblock);
  173. #define PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
  174. extern void Crash(const std::string& srcfile, int srcline);
  175. extern int GetMaxOpenFiles();
  176. extern const size_t kPageSize;
  177. } // namespace port
  178. } // namespace ROCKSDB_NAMESPACE