summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordwight <dwight@10gen.com>2011-02-21 10:48:28 -0500
committerdwight <dwight@10gen.com>2011-02-21 10:48:28 -0500
commitaf363697167c103374d7534b1af4b92f6eb3270c (patch)
tree4f6089113657c4a08d34608bc0fcb97a333549b9
parent7e13092c2f41ce844c3671cd39cf96afd8e62a90 (diff)
downloadmongo-af363697167c103374d7534b1af4b92f6eb3270c.tar.gz
SERVER-2500 windows - eliminate mapaligned
-rw-r--r--db/mongommf.cpp48
-rw-r--r--db/mongommf.h2
-rw-r--r--util/mmap.h4
-rw-r--r--util/mmap_win.cpp4
4 files changed, 52 insertions, 6 deletions
diff --git a/db/mongommf.cpp b/db/mongommf.cpp
index 20b45247670..46724c0ff1f 100644
--- a/db/mongommf.cpp
+++ b/db/mongommf.cpp
@@ -37,6 +37,48 @@ namespace mongo {
__declspec(noinline) void makeChunkWritable(size_t chunkno) {
scoped_lock lk(mapViewMutex);
+ if( writable.get(chunkno) ) // double check lock
+ return;
+
+ // remap all maps in this chunk. common case is a single map, but could have more than one with smallfiles or .ns files
+ size_t chunkStart = chunkno * MemoryMappedFile::ChunkSize;
+ size_t chunkNext = chunkStart + MemoryMappedFile::ChunkSize;
+
+ scoped_lock lk2(privateViews._mutex());
+ map<void*,MongoMMF*>::iterator i = privateViews.finditer_inlock((void*) (chunkNext-1));
+ while( 1 ) {
+ const pair<void*,MongoMMF*> x = *(--i);
+ MongoMMF *mmf = x.second;
+ if( mmf == 0 )
+ break;
+
+ size_t viewStart = (size_t) x.first;
+ size_t viewEnd = viewStart + mmf->length();
+ if( viewEnd <= chunkStart )
+ break;
+
+ size_t protectStart = max(viewStart, chunkStart);
+ dassert(protectStart<chunkNext);
+
+ size_t protectEnd = min(viewEnd, chunkNext);
+ size_t protectSize = protectEnd - protectStart;
+ dassert(protectSize>0&&protectSize<=MemoryMappedFile::ChunkSize);
+
+ DWORD old;
+ bool ok = VirtualProtect((void*)protectStart, protectSize, PAGE_WRITECOPY, &old);
+ if( !ok ) {
+ DWORD e = GetLastError();
+ log() << "VirtualProtect failed " << chunkno << hex << protectStart << ' ' << protectSize << ' ' << errnoWithDescription(e) << endl;
+ assert(false);
+ }
+ }
+
+ writable.set(chunkno);
+ }
+
+ __declspec(noinline) void makeChunkWritableOld(size_t chunkno) {
+ scoped_lock lk(mapViewMutex);
+
if( writable.get(chunkno) )
return;
@@ -118,12 +160,14 @@ namespace mongo {
void* MemoryMappedFile::createPrivateMap() {
assert( maphandle );
scoped_lock lk(mapViewMutex);
- void *p = mapaligned(maphandle, len);
+ //void *p = mapaligned(maphandle, len);
+ void *p = MapViewOfFile(maphandle, FILE_MAP_READ, 0, 0, 0);
if ( p == 0 ) {
DWORD e = GetLastError();
log() << "createPrivateMap failed " << filename() << " " << errnoWithDescription(e) << endl;
}
else {
+ clearWritableBits(p);
views.push_back(p);
}
return p;
@@ -135,7 +179,7 @@ namespace mongo {
scoped_lock lk(mapViewMutex);
- unmapped(oldPrivateAddr);
+ clearWritableBits(oldPrivateAddr);
if( !UnmapViewOfFile(oldPrivateAddr) ) {
DWORD e = GetLastError();
diff --git a/db/mongommf.h b/db/mongommf.h
index f7716735cd9..7061903512f 100644
--- a/db/mongommf.h
+++ b/db/mongommf.h
@@ -128,6 +128,8 @@ namespace mongo {
mutex& _mutex() { return _m; }
MongoMMF* find_inlock(void *p, /*out*/ size_t& ofs);
+ map<void*,MongoMMF*>::iterator PointerToMMF::finditer_inlock(void *p) { return _views.upper_bound(p); }
+
private:
mutex _m;
map<void*, MongoMMF*> _views;
diff --git a/util/mmap.h b/util/mmap.h
index 28e7be7c5fe..2ef417690c4 100644
--- a/util/mmap.h
+++ b/util/mmap.h
@@ -190,12 +190,12 @@ namespace mongo {
#ifdef _WIN32
boost::shared_ptr<mutex> _flushMutex;
- void unmapped(void *privateView);
+ void clearWritableBits(void *privateView);
public:
static const unsigned ChunkSize = 64 * 1024 * 1024;
static const unsigned NChunks = 1024 * 1024;
#else
- void unmapped(void *privateView) { }
+ void clearWritableBits(void *privateView) { }
#endif
protected:
diff --git a/util/mmap_win.cpp b/util/mmap_win.cpp
index 76837edd5c4..0b0b834becd 100644
--- a/util/mmap_win.cpp
+++ b/util/mmap_win.cpp
@@ -28,7 +28,7 @@ namespace mongo {
ourbitset writable;
/** notification on unmapping so we can clear writable bits */
- void MemoryMappedFile::unmapped(void *p) {
+ void MemoryMappedFile::clearWritableBits(void *p) {
for( unsigned i = ((size_t)p)/ChunkSize; i <= (((size_t)p)+len)/ChunkSize; i++ ) {
writable.clear(i);
assert( !writable.get(i) );
@@ -45,7 +45,7 @@ namespace mongo {
void MemoryMappedFile::close() {
for( vector<void*>::iterator i = views.begin(); i != views.end(); i++ ) {
- unmapped(*i);
+ clearWritableBits(*i);
UnmapViewOfFile(*i);
}
views.clear();