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.
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.
10 #if !defined(OS_WIN) && !defined(WIN32) && !defined(_WIN32)
11 #error Windows Specific Code
14 #include "port/win/port_win.h"
17 #include "port/dirent.h"
18 #include "port/sys_time.h"
29 #include "util/logging.h"
34 void gettimeofday(struct timeval
* tv
, struct timezone
* /* tz */) {
35 using namespace std::chrono
;
38 duration_cast
<microseconds
>(system_clock::now().time_since_epoch()));
40 seconds
secNow(duration_cast
<seconds
>(usNow
));
42 tv
->tv_sec
= static_cast<long>(secNow
.count());
43 tv
->tv_usec
= static_cast<long>(usNow
.count() -
44 duration_cast
<microseconds
>(secNow
).count());
49 CondVar::~CondVar() {}
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
);
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)
66 bool CondVar::TimedWait(uint64_t abs_time_us
) {
68 using namespace std::chrono
;
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
);
75 duration_cast
<microseconds
>(system_clock::now().time_since_epoch()));
76 microseconds relTimeUs
=
77 (usAbsTime
> usNow
) ? (usAbsTime
- usNow
) : microseconds::zero();
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
);
84 std::cv_status cvStatus
= cv_
.wait_for(lk
, relTimeUs
);
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)
92 if (cvStatus
== std::cv_status::timeout
) {
99 void CondVar::Signal() { cv_
.notify_one(); }
101 void CondVar::SignalAll() { cv_
.notify_all(); }
103 int PhysicalCoreID() { return GetCurrentProcessorNumber(); }
105 void InitOnce(OnceType
* once
, void (*initializer
)()) {
106 std::call_once(once
->flag_
, initializer
);
109 // Private structure, exposed only by pointer
113 struct __finddata64_t data_
;
116 DIR() : handle_(-1), firstread_(true) {}
118 DIR(const DIR&) = delete;
119 DIR& operator=(const DIR&) = delete;
128 DIR* opendir(const char* name
) {
129 if (!name
|| *name
== 0) {
134 std::string
pattern(name
);
135 pattern
.append("\\").append("*");
137 std::unique_ptr
<DIR> dir(new DIR);
139 dir
->handle_
= _findfirst64(pattern
.c_str(), &dir
->data_
);
141 if (dir
->handle_
== -1) {
145 strcpy_s(dir
->entry_
.d_name
, sizeof(dir
->entry_
.d_name
), dir
->data_
.name
);
147 return dir
.release();
150 struct dirent
* readdir(DIR* dirp
) {
151 if (!dirp
|| dirp
->handle_
== -1) {
156 if (dirp
->firstread_
) {
157 dirp
->firstread_
= false;
158 return &dirp
->entry_
;
161 auto ret
= _findnext64(dirp
->handle_
, &dirp
->data_
);
167 strcpy_s(dirp
->entry_
.d_name
, sizeof(dirp
->entry_
.d_name
), dirp
->data_
.name
);
169 return &dirp
->entry_
;
172 int closedir(DIR* dirp
) {
177 int truncate(const char* path
, int64_t len
) {
178 if (path
== nullptr) {
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
);
195 if (INVALID_HANDLE_VALUE
== hFile
) {
196 auto lastError
= GetLastError();
197 if (lastError
== ERROR_FILE_NOT_FOUND
) {
199 } else if (lastError
== ERROR_ACCESS_DENIED
) {
208 FILE_END_OF_FILE_INFO end_of_file
;
209 end_of_file
.EndOfFile
.QuadPart
= len
;
211 if (!SetFileInformationByHandle(hFile
, FileEndOfFileInfo
, &end_of_file
,
212 sizeof(FILE_END_OF_FILE_INFO
))) {
221 void Crash(const std::string
& srcfile
, int srcline
) {
222 fprintf(stdout
, "Crashing at %s:%d\n", srcfile
.c_str(), srcline
);
227 int GetMaxOpenFiles() { return -1; }
230 } // namespace rocksdb
234 #include "jemalloc/jemalloc.h"
236 #ifndef JEMALLOC_NON_INIT
242 __declspec(noinline
) void WINAPI
InitializeJemalloc() {
254 #pragma comment(linker, "/INCLUDE:p_rocksdb_init_jemalloc")
256 typedef void(WINAPI
* CRT_Startup_Routine
)(void);
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
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
;
273 #pragma comment(linker, "/INCLUDE:_p_rocksdb_init_jemalloc")
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
;
283 #endif // JEMALLOC_NON_INIT
285 // Global operators to be replaced by a linker
287 void* operator new(size_t size
) {
288 void* p
= je_malloc(size
);
290 throw std::bad_alloc();
295 void* operator new[](size_t size
) {
296 void* p
= je_malloc(size
);
298 throw std::bad_alloc();
303 void operator delete(void* p
) { je_free(p
); }
305 void operator delete[](void* p
) { je_free(p
); }