port_win.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. // Always want minimum headers
  13. #ifndef WIN32_LEAN_AND_MEAN
  14. #define WIN32_LEAN_AND_MEAN
  15. #endif
  16. #include <windows.h>
  17. //^^ <windows.h> should be included first before other system lib
  18. #include <intrin.h>
  19. #include <malloc.h>
  20. #include <process.h>
  21. #include <stdint.h>
  22. #include <string.h>
  23. #include <cassert>
  24. #include <condition_variable>
  25. #include <limits>
  26. #include <mutex>
  27. #include <string>
  28. #include <thread>
  29. #include "port/win/win_thread.h"
  30. #include "rocksdb/port_defs.h"
  31. #undef min
  32. #undef max
  33. #undef DeleteFile
  34. #undef GetCurrentTime
  35. #ifndef strcasecmp
  36. #define strcasecmp _stricmp
  37. #endif
  38. #undef GetCurrentTime
  39. #undef DeleteFile
  40. #ifndef _SSIZE_T_DEFINED
  41. using ssize_t = SSIZE_T;
  42. #endif
  43. // size_t printf formatting named in the manner of C99 standard formatting
  44. // strings such as PRIu64
  45. // in fact, we could use that one
  46. #ifndef ROCKSDB_PRIszt
  47. #define ROCKSDB_PRIszt "Iu"
  48. #endif
  49. #ifdef _MSC_VER
  50. #define __attribute__(A)
  51. #endif
  52. namespace ROCKSDB_NAMESPACE {
  53. #define PREFETCH(addr, rw, locality)
  54. extern const bool kDefaultToAdaptiveMutex;
  55. namespace port {
  56. // "Windows is designed to run on little-endian computer architectures."
  57. // https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types
  58. constexpr bool kLittleEndian = true;
  59. #undef PLATFORM_IS_LITTLE_ENDIAN
  60. class CondVar;
  61. class Mutex {
  62. public:
  63. static const char* kName() { return "std::mutex"; }
  64. explicit Mutex(bool IGNORED_adaptive = kDefaultToAdaptiveMutex)
  65. #ifndef NDEBUG
  66. : locked_(false)
  67. #endif
  68. {
  69. (void)IGNORED_adaptive;
  70. }
  71. ~Mutex();
  72. void Lock() {
  73. mutex_.lock();
  74. #ifndef NDEBUG
  75. locked_ = true;
  76. #endif
  77. }
  78. void Unlock() {
  79. #ifndef NDEBUG
  80. locked_ = false;
  81. #endif
  82. mutex_.unlock();
  83. }
  84. bool TryLock() {
  85. bool ret = mutex_.try_lock();
  86. #ifndef NDEBUG
  87. if (ret) {
  88. locked_ = true;
  89. }
  90. #endif
  91. return ret;
  92. }
  93. // this will assert if the mutex is not locked
  94. // it does NOT verify that mutex is held by a calling thread
  95. void AssertHeld() const {
  96. #ifndef NDEBUG
  97. assert(locked_);
  98. #endif
  99. }
  100. // Also implement std Lockable
  101. inline void lock() { Lock(); }
  102. inline void unlock() { Unlock(); }
  103. inline bool try_lock() { return TryLock(); }
  104. // Mutex is move only with lock ownership transfer
  105. Mutex(const Mutex&) = delete;
  106. void operator=(const Mutex&) = delete;
  107. private:
  108. friend class CondVar;
  109. std::mutex& getLock() { return mutex_; }
  110. std::mutex mutex_;
  111. #ifndef NDEBUG
  112. bool locked_;
  113. #endif
  114. };
  115. class RWMutex {
  116. public:
  117. RWMutex() { InitializeSRWLock(&srwLock_); }
  118. // No copying allowed
  119. RWMutex(const RWMutex&) = delete;
  120. void operator=(const RWMutex&) = delete;
  121. void ReadLock() { AcquireSRWLockShared(&srwLock_); }
  122. void WriteLock() { AcquireSRWLockExclusive(&srwLock_); }
  123. void ReadUnlock() { ReleaseSRWLockShared(&srwLock_); }
  124. void WriteUnlock() { ReleaseSRWLockExclusive(&srwLock_); }
  125. // Empty as in POSIX
  126. void AssertHeld() const {}
  127. private:
  128. SRWLOCK srwLock_;
  129. };
  130. class CondVar {
  131. public:
  132. explicit CondVar(Mutex* mu) : mu_(mu) {}
  133. ~CondVar();
  134. Mutex* GetMutex() const { return mu_; }
  135. void Wait();
  136. bool TimedWait(uint64_t expiration_time);
  137. void Signal();
  138. void SignalAll();
  139. // Condition var is not copy/move constructible
  140. CondVar(const CondVar&) = delete;
  141. CondVar& operator=(const CondVar&) = delete;
  142. CondVar(CondVar&&) = delete;
  143. CondVar& operator=(CondVar&&) = delete;
  144. private:
  145. std::condition_variable cv_;
  146. Mutex* mu_;
  147. };
  148. #ifdef _POSIX_THREADS
  149. using Thread = std::thread;
  150. #else
  151. // Wrapper around the platform efficient
  152. // or otherwise preferrable implementation
  153. using Thread = WindowsThread;
  154. #endif
  155. // OnceInit type helps emulate
  156. // Posix semantics with initialization
  157. // adopted in the project
  158. struct OnceType {
  159. struct Init {};
  160. OnceType() {}
  161. OnceType(const Init&) {}
  162. OnceType(const OnceType&) = delete;
  163. OnceType& operator=(const OnceType&) = delete;
  164. std::once_flag flag_;
  165. };
  166. #define LEVELDB_ONCE_INIT port::OnceType::Init()
  167. void InitOnce(OnceType* once, void (*initializer)());
  168. #ifndef CACHE_LINE_SIZE
  169. #define CACHE_LINE_SIZE 64U
  170. #endif
  171. #ifdef ROCKSDB_JEMALLOC
  172. // Separate inlines so they can be replaced if needed
  173. void* jemalloc_aligned_alloc(size_t size, size_t alignment) noexcept;
  174. void jemalloc_aligned_free(void* p) noexcept;
  175. #endif
  176. inline void* cacheline_aligned_alloc(size_t size) {
  177. #ifdef ROCKSDB_JEMALLOC
  178. return jemalloc_aligned_alloc(size, CACHE_LINE_SIZE);
  179. #else
  180. return _aligned_malloc(size, CACHE_LINE_SIZE);
  181. #endif
  182. }
  183. inline void cacheline_aligned_free(void* memblock) {
  184. #ifdef ROCKSDB_JEMALLOC
  185. jemalloc_aligned_free(memblock);
  186. #else
  187. _aligned_free(memblock);
  188. #endif
  189. }
  190. extern const size_t kPageSize;
  191. // Part of C++11
  192. #define ALIGN_AS(n) alignas(n)
  193. static inline void AsmVolatilePause() {
  194. #if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM)
  195. YieldProcessor();
  196. #endif
  197. // it would be nice to get "wfe" on ARM here
  198. }
  199. int PhysicalCoreID();
  200. // For Thread Local Storage abstraction
  201. using pthread_key_t = DWORD;
  202. inline int pthread_key_create(pthread_key_t* key, void (*destructor)(void*)) {
  203. // Not used
  204. (void)destructor;
  205. pthread_key_t k = TlsAlloc();
  206. if (TLS_OUT_OF_INDEXES == k) {
  207. return ENOMEM;
  208. }
  209. *key = k;
  210. return 0;
  211. }
  212. inline int pthread_key_delete(pthread_key_t key) {
  213. if (!TlsFree(key)) {
  214. return EINVAL;
  215. }
  216. return 0;
  217. }
  218. inline int pthread_setspecific(pthread_key_t key, const void* value) {
  219. if (!TlsSetValue(key, const_cast<void*>(value))) {
  220. return ENOMEM;
  221. }
  222. return 0;
  223. }
  224. inline void* pthread_getspecific(pthread_key_t key) {
  225. void* result = TlsGetValue(key);
  226. if (!result) {
  227. if (GetLastError() != ERROR_SUCCESS) {
  228. errno = EINVAL;
  229. } else {
  230. errno = NOERROR;
  231. }
  232. }
  233. return result;
  234. }
  235. // UNIX equiv although errno numbers will be off
  236. // using C-runtime to implement. Note, this does not
  237. // feel space with zeros in case the file is extended.
  238. int truncate(const char* path, int64_t length);
  239. int Truncate(std::string path, int64_t length);
  240. void Crash(const std::string& srcfile, int srcline);
  241. int GetMaxOpenFiles();
  242. std::string utf16_to_utf8(const std::wstring& utf16);
  243. std::wstring utf8_to_utf16(const std::string& utf8);
  244. using ThreadId = int;
  245. void SetCpuPriority(ThreadId id, CpuPriority priority);
  246. int64_t GetProcessID();
  247. // Uses platform APIs to generate a 36-character RFC-4122 UUID. Returns
  248. // true on success or false on failure.
  249. bool GenerateRfcUuid(std::string* output);
  250. } // namespace port
  251. #ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
  252. #define RX_FILESTRING std::wstring
  253. #define RX_FN(a) ROCKSDB_NAMESPACE::port::utf8_to_utf16(a)
  254. #define FN_TO_RX(a) ROCKSDB_NAMESPACE::port::utf16_to_utf8(a)
  255. #define RX_FNCMP(a, b) ::wcscmp(a, RX_FN(b).c_str())
  256. #define RX_FNLEN(a) ::wcslen(a)
  257. #define RX_DeleteFile DeleteFileW
  258. #define RX_CreateFile CreateFileW
  259. #define RX_CreateFileMapping CreateFileMappingW
  260. #define RX_GetFileAttributesEx GetFileAttributesExW
  261. #define RX_FindFirstFileEx FindFirstFileExW
  262. #define RX_FindNextFile FindNextFileW
  263. #define RX_WIN32_FIND_DATA WIN32_FIND_DATAW
  264. #define RX_CreateDirectory CreateDirectoryW
  265. #define RX_RemoveDirectory RemoveDirectoryW
  266. #define RX_GetFileAttributesEx GetFileAttributesExW
  267. #define RX_MoveFileEx MoveFileExW
  268. #define RX_CreateHardLink CreateHardLinkW
  269. #define RX_PathIsRelative PathIsRelativeW
  270. #define RX_GetCurrentDirectory GetCurrentDirectoryW
  271. #define RX_GetDiskFreeSpaceEx GetDiskFreeSpaceExW
  272. #define RX_PathIsDirectory PathIsDirectoryW
  273. #else
  274. #define RX_FILESTRING std::string
  275. #define RX_FN(a) a
  276. #define FN_TO_RX(a) a
  277. #define RX_FNCMP(a, b) strcmp(a, b)
  278. #define RX_FNLEN(a) strlen(a)
  279. #define RX_DeleteFile DeleteFileA
  280. #define RX_CreateFile CreateFileA
  281. #define RX_CreateFileMapping CreateFileMappingA
  282. #define RX_GetFileAttributesEx GetFileAttributesExA
  283. #define RX_FindFirstFileEx FindFirstFileExA
  284. #define RX_CreateDirectory CreateDirectoryA
  285. #define RX_FindNextFile FindNextFileA
  286. #define RX_WIN32_FIND_DATA WIN32_FIND_DATAA
  287. #define RX_CreateDirectory CreateDirectoryA
  288. #define RX_RemoveDirectory RemoveDirectoryA
  289. #define RX_GetFileAttributesEx GetFileAttributesExA
  290. #define RX_MoveFileEx MoveFileExA
  291. #define RX_CreateHardLink CreateHardLinkA
  292. #define RX_PathIsRelative PathIsRelativeA
  293. #define RX_GetCurrentDirectory GetCurrentDirectoryA
  294. #define RX_GetDiskFreeSpaceEx GetDiskFreeSpaceExA
  295. #define RX_PathIsDirectory PathIsDirectoryA
  296. #endif
  297. using port::pthread_getspecific;
  298. using port::pthread_key_create;
  299. using port::pthread_key_delete;
  300. using port::pthread_key_t;
  301. using port::pthread_setspecific;
  302. using port::truncate;
  303. } // namespace ROCKSDB_NAMESPACE