diff --git a/src/Win32_Interop/Win32_Common.cpp b/src/Win32_Interop/Win32_Common.cpp
new file mode 100644
index 00000000..22cb853f
--- /dev/null
+++ b/src/Win32_Interop/Win32_Common.cpp
@@ -0,0 +1,48 @@
+/*
+* Copyright (c), Microsoft Open Technologies, Inc.
+* All rights reserved.
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* - Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "Win32_Common.h"
+
+namespace Globals
+{
+ size_t pageSize = 0;
+}
+
+/* This function is used to force the VEH on the entire size of the buffer length,
+ in the event that the buffer crosses the memory page boundaries */
+void EnsureMemoryIsMapped(const void *buffer, size_t size) {
+ /* Use 'volatile' to make sure the compiler doesn't remove "c = *((char*) (p + offset));" */
+ volatile char c;
+ char* p = (char*) buffer;
+ char* pStart = p - ((size_t) p % Globals::pageSize);
+ char* pEnd = p + size;
+ if ((size_t) (pEnd - pStart) > Globals::pageSize) {
+ size_t offset = 0;
+ while (offset < size) {
+ if (size < offset) {
+ offset = size;
+ } else {
+ offset += Globals::pageSize;
+ }
+ c = *((char*) (p + offset));
+ }
+ }
+}
diff --git a/src/Win32_Interop/Win32_Common.h b/src/Win32_Interop/Win32_Common.h
new file mode 100644
index 00000000..57094f77
--- /dev/null
+++ b/src/Win32_Interop/Win32_Common.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c), Microsoft Open Technologies, Inc.
+* All rights reserved.
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* - Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef WIN32_COMMON_H
+#define WIN32_COMMON_H
+
+void EnsureMemoryIsMapped(const void *buffer, size_t size);
+
+namespace Globals {
+ // forward declarations only
+ extern size_t pageSize;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/Win32_Interop/Win32_Interop.vcxproj b/src/Win32_Interop/Win32_Interop.vcxproj
index 85de0e5f..473c3e22 100644
--- a/src/Win32_Interop/Win32_Interop.vcxproj
+++ b/src/Win32_Interop/Win32_Interop.vcxproj
@@ -22,6 +22,7 @@
+
@@ -45,6 +46,7 @@
+
diff --git a/src/Win32_Interop/Win32_QFork.cpp b/src/Win32_Interop/Win32_QFork.cpp
index 6fd83e06..1dd65dfe 100644
--- a/src/Win32_Interop/Win32_QFork.cpp
+++ b/src/Win32_Interop/Win32_QFork.cpp
@@ -22,6 +22,7 @@
#include "win32_types.h"
#include "Win32_FDAPI.h"
+#include "Win32_Common.h"
#include
#include
@@ -161,7 +162,6 @@ const SIZE_T cAllocationGranularity = 1 << 18; // 256KB per h
const int cMaxBlocks = 1 << 24; // 256KB * 16M heap blocks = 4TB. 4TB is the largest memory config Windows supports at present.
const char* cMapFileBaseName = "RedisQFork";
const int cDeadForkWait = 30000;
-size_t pageSize = 0;
#ifndef _WIN64
size_t cDefaultmaxHeap32Bit = 1 << 29; // 512MB
@@ -693,7 +693,7 @@ StartupStatus QForkStartup(int argc, char** argv) {
::redisLog(REDIS_WARNING, "Failing startup.\n");
return StartupStatus::ssFAILED;
}
- pageSize = perfinfo.PageSize;
+ Globals::pageSize = perfinfo.PageSize;
/*
Not specifying the maxmemory or maxheap flags will result in the default behavior of: new key generation not
@@ -740,7 +740,7 @@ StartupStatus QForkStartup(int argc, char** argv) {
maxheapBytes = cSentinelHeapSize;
} else {
#ifdef _WIN64
- maxheapBytes = perfinfo.PhysicalTotal * pageSize;
+ maxheapBytes = perfinfo.PhysicalTotal * Globals::pageSize;
#else
maxheapBytes = cDefaultmaxHeap32Bit;
#endif
diff --git a/src/Win32_Interop/Win32_fdapi_crt.cpp b/src/Win32_Interop/Win32_fdapi_crt.cpp
index f112ca1c..62d2e466 100644
--- a/src/Win32_Interop/Win32_fdapi_crt.cpp
+++ b/src/Win32_Interop/Win32_fdapi_crt.cpp
@@ -21,6 +21,7 @@
*/
#include "Win32_fdapi_crt.h"
+#include "Win32_Common.h"
#include
#include
@@ -56,22 +57,14 @@ int crtsetmode(int fd, int mode) {
return ::_setmode(fd, mode);
}
-size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
+size_t crt_fwrite(const void *buffer, size_t size, size_t count, FILE *file) {
// fwrite() somehow locks its view of the buffer. If during a fork operation the buffer has not been loaded into the forkee's process space,
// the VEH will be called to load the missing pages. Although the page gets loaded, fwrite() will not see the loaded page. The result is
// that fwrite will fail with errno set to ERROR_INVALID_USER_BUFFER. The fix is to force the buffer into memory before fwrite(). This only
- // impacts wirites that straddle page boundaries.
- const intptr_t pageSize = 4096;
- char* p = (char*)_Str;
- char* pageStart = p - ((intptr_t)p % pageSize);
- char* pEnd = p + _Size;
- if ((intptr_t)(pEnd - pageStart) > pageSize) {
- for (size_t n = 0; n < _Size; n++) {
- char x = *((char*)_Str + n);
- }
- }
+ // impacts writes that straddle page boundaries.
+ EnsureMemoryIsMapped(buffer, size);
+ return ::fwrite(buffer, size, count, file);
- return ::fwrite(_Str, _Size, _Count, _File);
}
int crt_fclose(FILE* file) {
@@ -93,4 +86,3 @@ int crt_access(const char *pathname, int mode) {
__int64 crt_lseek64(int fd, __int64 offset, int origin) {
return _lseeki64(fd, offset, origin);
}
-
diff --git a/src/Win32_Interop/Win32_fdapi_crt.h b/src/Win32_Interop/Win32_fdapi_crt.h
index 6b59515e..5ce6244b 100644
--- a/src/Win32_Interop/Win32_fdapi_crt.h
+++ b/src/Win32_Interop/Win32_fdapi_crt.h
@@ -32,7 +32,7 @@ int crt_open(const char *filename, int oflag, int pmode);
int crt_open_osfhandle(intptr_t osfhandle, int flags);
intptr_t crtget_osfhandle(int fd);
int crtsetmode(int fd, int mode);
-size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File);
+size_t crt_fwrite(const void *buffer, size_t size, size_t count, FILE *file);
int crt_fclose(FILE* file);
int crt_fileno(FILE* file);