port_win.h 9.3 KB

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