Skip to content

Commit

Permalink
Windows functionality & build corrections
Browse files Browse the repository at this point in the history
Functionality
* Use always page file backed MMF on windows (due to issue nodejs/node#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...'
  • Loading branch information
jykahama committed Jun 26, 2017
1 parent cccdcd6 commit a14d05e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
27 changes: 21 additions & 6 deletions src/mman.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <windows.h>
#include <sys/types.h>

#include <iostream>

#define PROT_NONE 0x00
#define PROT_READ 0x01
#define PROT_WRITE 0x02
Expand All @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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();
Expand Down
48 changes: 40 additions & 8 deletions src/mmap-io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <nan.h>
#include <errno.h>
#include <string>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
Expand All @@ -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<MMap*>(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) {
Expand All @@ -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]])."
);
Expand All @@ -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<char*>( 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<char*>( mmap( hinted_address, size, protection, flags, fd, offset, share_name, &fm) );
#else
char* data = static_cast<char*>(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());
Expand Down Expand Up @@ -102,8 +122,12 @@ JS_FN(mmap_map) {

}

auto map_info = new MMap(data, size);
Nan::MaybeLocal<Object> buf = Nan::NewBuffer(data, size, do_mmap_cleanup, static_cast<void*>(map_info));
#ifdef _WIN32
auto map_info = new MMap(data, size, fm);
#else
auto map_info = new MMap(data, size);
#endif
Nan::MaybeLocal<Object> buf = Nan::NewBuffer(data, size, do_mmap_cleanup, static_cast<void*>(map_info));
if (buf.IsEmpty()) {
return Nan::ThrowError(std::string("couldn't allocate Node Buffer()").c_str());
} else {
Expand Down Expand Up @@ -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) ."
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit a14d05e

Please sign in to comment.