From a14d05e1b7a8390f85c8408e9efc08c55f7f4fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jyrki=20H=C3=A4m=C3=A4l=C3=A4inen?= Date: Fri, 7 Oct 2016 21:43:19 +0300 Subject: [PATCH] Windows functionality & build corrections Functionality * Use always page file backed MMF on windows (due to issue https://github.com/nodejs/node/issues/6369). * On windows pass page file name to mmap_map. * Do not CloseHandle of mapped file until cleaning up as closing handle closes also connection to page file backed MMF. * Throw unsupported error for mincore on windows Windows build * Compile flags around mincore calls * npm prepublish script changed from 'make ls' to direct call of 'node lsc...' --- package.json | 2 +- src/mman.h | 27 +++++++++++++++++++++------ src/mmap-io.cc | 48 ++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index e02992b..45cc445 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "scripts": { - "prepublish": "make ls", + "prepublish": "node node_modules/LiveScript/bin/lsc -b -c src/test.ls -o ./ && node node_modules/LiveScript/bin/lsc -b -c src/mmap-io.ls -o ./", "install": "node-gyp configure && node-gyp rebuild", "test": "node ./test.js" }, diff --git a/src/mman.h b/src/mman.h index 7b8e979..6e8c65b 100644 --- a/src/mman.h +++ b/src/mman.h @@ -3,6 +3,8 @@ #include #include +#include + #define PROT_NONE 0x00 #define PROT_READ 0x01 #define PROT_WRITE 0x02 @@ -25,7 +27,7 @@ #define MADV_WILLNEED 0x03 #define MADV_DONTNEED 0x04 -inline void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { +inline void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset, const char* name, HANDLE* filemaphandle) { if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) return MAP_FAILED; if (fd == -1) { @@ -54,10 +56,22 @@ inline void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t const DWORD dwOffsetLow = (sizeof(off_t) > sizeof(DWORD)) ? DWORD(offset & 0xFFFFFFFFL) : DWORD(offset); const DWORD dwOffsetHigh = (sizeof(off_t) > sizeof(DWORD)) ? DWORD(offset & 0xFFFFFFFFL) : DWORD(0); + std::cout << "fd is " << fd << std::endl << std::flush; + HANDLE h = (fd == -1) ? HANDLE(_get_osfhandle(fd)) : INVALID_HANDLE_VALUE; - HANDLE fm = CreateFileMapping(h, nullptr, protect, dwEndHigh, dwEndLow, nullptr); + //HANDLE h = (fd != -1) ? (HANDLE)fd : INVALID_HANDLE_VALUE; + HANDLE fm = CreateFileMapping(h, nullptr, protect, dwEndHigh, dwEndLow, name); if (fm == nullptr) + { + DWORD err = GetLastError(); + std::cout << "CreateFileMapping failed! " << err << std::endl << std::flush; return MAP_FAILED; + } + else + { + DWORD err = GetLastError(); + std::cout << "CreateFileMapping succeeded! (183 == ERROR_ALREADY_EXISTS) " << err << std::endl << std::flush; + } DWORD dwDesiredAccess; if (prot & PROT_WRITE) @@ -70,13 +84,14 @@ inline void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t dwDesiredAccess |= FILE_MAP_COPY; void* map = MapViewOfFile(fm, dwDesiredAccess, dwOffsetHigh, dwOffsetLow, length); - CloseHandle(fm); - + *filemaphandle = fm; return (map != nullptr) ? map : MAP_FAILED; } -inline int munmap(void* addr, size_t length) { - if (UnmapViewOfFile(addr)) +inline int munmap(void* addr, size_t length, HANDLE fm) { + CloseHandle(fm); + + if (UnmapViewOfFile(addr)) return 0; errno = GetLastError(); diff --git a/src/mmap-io.cc b/src/mmap-io.cc index df8252d..9277bfc 100644 --- a/src/mmap-io.cc +++ b/src/mmap-io.cc @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -34,16 +35,26 @@ using namespace v8; // Since casting `size` to `void*` feels a little "out there" considering that void* may be // 32b or 64b (or, I dunno, 47b on some quant particle system), we throw this struct in.. struct MMap { - MMap(char* data, size_t size) : data(data), size(size) {} - char* data = nullptr; +#ifdef _WIN32 + MMap(char* data, size_t size, HANDLE fm) : data(data), size(size), filemap(fm) {} +#endif + MMap(char* data, size_t size) : data(data), size(size) {} + char* data = nullptr; size_t size = 0; +#ifdef _WIN32 + HANDLE filemap = INVALID_HANDLE_VALUE; +#endif }; void do_mmap_cleanup(char* data, void* hint) { auto map_info = static_cast(hint); - munmap(data, map_info->size); - delete map_info; +#ifdef _WIN32 + munmap(data, map_info->size, map_info->filemap); +#else + munmap(data, map_info->size); +#endif + delete map_info; } inline int do_mmap_advice(char* addr, size_t length, int advise) { @@ -53,7 +64,7 @@ inline int do_mmap_advice(char* addr, size_t length, int advise) { JS_FN(mmap_map) { Nan::HandleScope(); - if (info.Length() < 4 && info.Length() > 6) { + if (info.Length() < 4 && info.Length() > 7) { return Nan::ThrowError( "map() takes 4, 5 or 6 arguments: (size :int, protection :int, flags :int, fd :int [, offset :int [, advise :int]])." ); @@ -74,7 +85,16 @@ JS_FN(mmap_map) { const off_t offset = info[4]->ToInteger()->Value(); // ToInt64()->Value(); const int advise = info[5]->ToInteger()->Value(); - char* data = static_cast( mmap( hinted_address, size, protection, flags, fd, offset) ); +#ifdef _WIN32 + v8::String::Utf8Value str(info[6]->ToString()); + const char* share_name = (const char*)(*str); + + std::cout << "sharename is " << share_name << std::endl << std::flush; + HANDLE fm; + char* data = static_cast( mmap( hinted_address, size, protection, flags, fd, offset, share_name, &fm) ); +#else + char* data = static_cast(mmap(hinted_address, size, protection, flags, fd, offset)); +#endif if (data == MAP_FAILED) { return Nan::ThrowError((std::string("mmap failed, ") + std::to_string(errno)).c_str()); @@ -102,8 +122,12 @@ JS_FN(mmap_map) { } - auto map_info = new MMap(data, size); - Nan::MaybeLocal buf = Nan::NewBuffer(data, size, do_mmap_cleanup, static_cast(map_info)); +#ifdef _WIN32 + auto map_info = new MMap(data, size, fm); +#else + auto map_info = new MMap(data, size); +#endif + Nan::MaybeLocal buf = Nan::NewBuffer(data, size, do_mmap_cleanup, static_cast(map_info)); if (buf.IsEmpty()) { return Nan::ThrowError(std::string("couldn't allocate Node Buffer()").c_str()); } else { @@ -149,6 +173,9 @@ JS_FN(mmap_advise) { JS_FN(mmap_incore) { Nan::HandleScope(); +#ifdef _WIN32 + return Nan::ThrowError("mincore not supported in windows!"); +#endif if (info.Length() != 1) { return Nan::ThrowError( "incore() takes 1 argument: (buffer :Buffer) ." @@ -182,7 +209,12 @@ JS_FN(mmap_incore) { pages++; } +#ifdef _WIN32 + int ret = -1; + errno = ENOSYS; +#else int ret = mincore(data, size, resultData); +#endif if (ret) { free(resultData);