When mapping a file into memory we do now immediately map all active

pages into the team's address space. Doing that is relatively cheap and
saves later page faults.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27380 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-08 13:45:27 +00:00
parent 032d13f49a
commit 6f3ee1f167
+62
View File
@@ -2087,6 +2087,33 @@ vm_create_vnode_cache(struct vnode *vnode, struct VMCache **cache)
}
/*! \a cache must be locked. The area's address space must be read-locked.
*/
static void
pre_map_area_pages(vm_area* area, VMCache* cache)
{
addr_t baseAddress = area->base;
addr_t cacheOffset = area->cache_offset;
page_num_t firstPage = cacheOffset / B_PAGE_SIZE;
page_num_t endPage = firstPage + area->size / B_PAGE_SIZE;
for (VMCachePagesTree::Iterator it
= cache->pages.GetIterator(firstPage, true, true);
vm_page *page = it.Next();) {
if (page->cache_offset >= endPage)
break;
// skip inactive pages
if (page->state == PAGE_STATE_BUSY || page->usage_count <= 0)
continue;
vm_map_page(area, page,
baseAddress + (page->cache_offset * B_PAGE_SIZE - cacheOffset),
B_READ_AREA | B_KERNEL_READ_AREA);
}
}
/*! Will map the file specified by \a fd to an area in memory.
The file will be mirrored beginning at the specified \a offset. The
\a offset and \a size arguments have to be page aligned.
@@ -2139,6 +2166,38 @@ _vm_map_file(team_id team, const char *name, void **_address, uint32 addressSpec
return status;
CObjectDeleter<struct vnode> vnodePutter(vnode, vfs_put_vnode);
// If we're going to pre-map pages, we need to reserve the pages needed by
// the mapping backend upfront.
page_num_t reservedPreMapPages = 0;
if ((protection & B_READ_AREA) != 0) {
AddressSpaceWriteLocker locker;
status = locker.SetTo(team);
if (status != B_OK)
return status;
vm_translation_map *map = &locker.AddressSpace()->translation_map;
reservedPreMapPages = map->ops->map_max_pages_need(map, 0, size - 1);
locker.Unlock();
vm_page_reserve_pages(reservedPreMapPages);
}
struct PageUnreserver {
PageUnreserver(page_num_t count)
: fCount(count)
{
}
~PageUnreserver()
{
if (fCount > 0)
vm_page_unreserve_pages(fCount);
}
page_num_t fCount;
} pageUnreserver(reservedPreMapPages);
AddressSpaceWriteLocker locker(team);
if (!locker.IsLocked())
return B_BAD_TEAM_ID;
@@ -2161,6 +2220,9 @@ _vm_map_file(team_id team, const char *name, void **_address, uint32 addressSpec
cache->ReleaseRefLocked();
}
if (status == B_OK && (protection & B_READ_AREA) != 0)
pre_map_area_pages(area, cache);
cache->Unlock();
if (status < B_OK)