]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/port/win/port_win.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / port / win / port_win.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same 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 #if !defined(OS_WIN) && !defined(WIN32) && !defined(_WIN32)
11 #error Windows Specific Code
12 #endif
13
14 #include "port/win/port_win.h"
15
16 #include <io.h>
17 #include "port/dirent.h"
18 #include "port/sys_time.h"
19
20 #include <cstdlib>
21 #include <stdio.h>
22 #include <assert.h>
23 #include <string.h>
24
25 #include <memory>
26 #include <exception>
27 #include <chrono>
28
29 #include "util/logging.h"
30
31 namespace rocksdb {
32 namespace port {
33
34 void gettimeofday(struct timeval* tv, struct timezone* /* tz */) {
35 using namespace std::chrono;
36
37 microseconds usNow(
38 duration_cast<microseconds>(system_clock::now().time_since_epoch()));
39
40 seconds secNow(duration_cast<seconds>(usNow));
41
42 tv->tv_sec = static_cast<long>(secNow.count());
43 tv->tv_usec = static_cast<long>(usNow.count() -
44 duration_cast<microseconds>(secNow).count());
45 }
46
47 Mutex::~Mutex() {}
48
49 CondVar::~CondVar() {}
50
51 void CondVar::Wait() {
52 // Caller must ensure that mutex is held prior to calling this method
53 std::unique_lock<std::mutex> lk(mu_->getLock(), std::adopt_lock);
54 #ifndef NDEBUG
55 mu_->locked_ = false;
56 #endif
57 cv_.wait(lk);
58 #ifndef NDEBUG
59 mu_->locked_ = true;
60 #endif
61 // Release ownership of the lock as we don't want it to be unlocked when
62 // it goes out of scope (as we adopted the lock and didn't lock it ourselves)
63 lk.release();
64 }
65
66 bool CondVar::TimedWait(uint64_t abs_time_us) {
67
68 using namespace std::chrono;
69
70 // MSVC++ library implements wait_until in terms of wait_for so
71 // we need to convert absolute wait into relative wait.
72 microseconds usAbsTime(abs_time_us);
73
74 microseconds usNow(
75 duration_cast<microseconds>(system_clock::now().time_since_epoch()));
76 microseconds relTimeUs =
77 (usAbsTime > usNow) ? (usAbsTime - usNow) : microseconds::zero();
78
79 // Caller must ensure that mutex is held prior to calling this method
80 std::unique_lock<std::mutex> lk(mu_->getLock(), std::adopt_lock);
81 #ifndef NDEBUG
82 mu_->locked_ = false;
83 #endif
84 std::cv_status cvStatus = cv_.wait_for(lk, relTimeUs);
85 #ifndef NDEBUG
86 mu_->locked_ = true;
87 #endif
88 // Release ownership of the lock as we don't want it to be unlocked when
89 // it goes out of scope (as we adopted the lock and didn't lock it ourselves)
90 lk.release();
91
92 if (cvStatus == std::cv_status::timeout) {
93 return true;
94 }
95
96 return false;
97 }
98
99 void CondVar::Signal() { cv_.notify_one(); }
100
101 void CondVar::SignalAll() { cv_.notify_all(); }
102
103 int PhysicalCoreID() { return GetCurrentProcessorNumber(); }
104
105 void InitOnce(OnceType* once, void (*initializer)()) {
106 std::call_once(once->flag_, initializer);
107 }
108
109 // Private structure, exposed only by pointer
110 struct DIR {
111 intptr_t handle_;
112 bool firstread_;
113 struct __finddata64_t data_;
114 dirent entry_;
115
116 DIR() : handle_(-1), firstread_(true) {}
117
118 DIR(const DIR&) = delete;
119 DIR& operator=(const DIR&) = delete;
120
121 ~DIR() {
122 if (-1 != handle_) {
123 _findclose(handle_);
124 }
125 }
126 };
127
128 DIR* opendir(const char* name) {
129 if (!name || *name == 0) {
130 errno = ENOENT;
131 return nullptr;
132 }
133
134 std::string pattern(name);
135 pattern.append("\\").append("*");
136
137 std::unique_ptr<DIR> dir(new DIR);
138
139 dir->handle_ = _findfirst64(pattern.c_str(), &dir->data_);
140
141 if (dir->handle_ == -1) {
142 return nullptr;
143 }
144
145 strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name), dir->data_.name);
146
147 return dir.release();
148 }
149
150 struct dirent* readdir(DIR* dirp) {
151 if (!dirp || dirp->handle_ == -1) {
152 errno = EBADF;
153 return nullptr;
154 }
155
156 if (dirp->firstread_) {
157 dirp->firstread_ = false;
158 return &dirp->entry_;
159 }
160
161 auto ret = _findnext64(dirp->handle_, &dirp->data_);
162
163 if (ret != 0) {
164 return nullptr;
165 }
166
167 strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name), dirp->data_.name);
168
169 return &dirp->entry_;
170 }
171
172 int closedir(DIR* dirp) {
173 delete dirp;
174 return 0;
175 }
176
177 int truncate(const char* path, int64_t len) {
178 if (path == nullptr) {
179 errno = EFAULT;
180 return -1;
181 }
182
183 if (len < 0) {
184 errno = EINVAL;
185 return -1;
186 }
187
188 HANDLE hFile =
189 CreateFile(path, GENERIC_READ | GENERIC_WRITE,
190 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
191 NULL, // Security attrs
192 OPEN_EXISTING, // Truncate existing file only
193 FILE_ATTRIBUTE_NORMAL, NULL);
194
195 if (INVALID_HANDLE_VALUE == hFile) {
196 auto lastError = GetLastError();
197 if (lastError == ERROR_FILE_NOT_FOUND) {
198 errno = ENOENT;
199 } else if (lastError == ERROR_ACCESS_DENIED) {
200 errno = EACCES;
201 } else {
202 errno = EIO;
203 }
204 return -1;
205 }
206
207 int result = 0;
208 FILE_END_OF_FILE_INFO end_of_file;
209 end_of_file.EndOfFile.QuadPart = len;
210
211 if (!SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file,
212 sizeof(FILE_END_OF_FILE_INFO))) {
213 errno = EIO;
214 result = -1;
215 }
216
217 CloseHandle(hFile);
218 return result;
219 }
220
221 void Crash(const std::string& srcfile, int srcline) {
222 fprintf(stdout, "Crashing at %s:%d\n", srcfile.c_str(), srcline);
223 fflush(stdout);
224 abort();
225 }
226
227 int GetMaxOpenFiles() { return -1; }
228
229 } // namespace port
230 } // namespace rocksdb
231
232 #ifdef JEMALLOC
233
234 #include "jemalloc/jemalloc.h"
235
236 #ifndef JEMALLOC_NON_INIT
237
238 namespace rocksdb {
239
240 namespace port {
241
242 __declspec(noinline) void WINAPI InitializeJemalloc() {
243 je_init();
244 atexit(je_uninit);
245 }
246
247 } // port
248 } // rocksdb
249
250 extern "C" {
251
252 #ifdef _WIN64
253
254 #pragma comment(linker, "/INCLUDE:p_rocksdb_init_jemalloc")
255
256 typedef void(WINAPI* CRT_Startup_Routine)(void);
257
258 // .CRT section is merged with .rdata on x64 so it must be constant data.
259 // must be of external linkage
260 // We put this into XCT since we want to run this earlier than C++ static
261 // constructors
262 // which are placed into XCU
263 #pragma const_seg(".CRT$XCT")
264 extern const CRT_Startup_Routine p_rocksdb_init_jemalloc;
265 const CRT_Startup_Routine p_rocksdb_init_jemalloc =
266 rocksdb::port::InitializeJemalloc;
267 #pragma const_seg()
268
269 #else // _WIN64
270
271 // x86 untested
272
273 #pragma comment(linker, "/INCLUDE:_p_rocksdb_init_jemalloc")
274
275 #pragma section(".CRT$XCT", read)
276 JEMALLOC_SECTION(".CRT$XCT") JEMALLOC_ATTR(used) static const void(
277 WINAPI* p_rocksdb_init_jemalloc)(void) = rocksdb::port::InitializeJemalloc;
278
279 #endif // _WIN64
280
281 } // extern "C"
282
283 #endif // JEMALLOC_NON_INIT
284
285 // Global operators to be replaced by a linker
286
287 void* operator new(size_t size) {
288 void* p = je_malloc(size);
289 if (!p) {
290 throw std::bad_alloc();
291 }
292 return p;
293 }
294
295 void* operator new[](size_t size) {
296 void* p = je_malloc(size);
297 if (!p) {
298 throw std::bad_alloc();
299 }
300 return p;
301 }
302
303 void operator delete(void* p) { je_free(p); }
304
305 void operator delete[](void* p) { je_free(p); }
306
307 #endif // JEMALLOC