blob: feb6fe1240e7bad106d28cdcdde05dc35ba97c67 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef PageReservation_h
#define PageReservation_h
#include <wtf/PageAllocation.h>
namespace WTF {
/*
PageReservation
Like PageAllocation, the PageReservation class provides a cross-platform memory
allocation interface, but with a set of capabilities more similar to that of
VirtualAlloc than posix mmap. PageReservation can be used to allocate virtual
memory without committing physical memory pages using PageReservation::reserve.
Following a call to reserve all memory in the region is in a decommited state,
in which the memory should not be used (accessing the memory may cause a fault).
Before using memory it must be committed by calling commit, which is passed start
and size values (both of which require system page size granularity). One the
committed memory is no longer needed 'decommit' may be called to return the
memory to its devommitted state. Commit should only be called on memory that is
currently decommitted, and decommit should only be called on memory regions that
are currently committed. All memory should be decommited before the reservation
is deallocated. Values in memory may not be retained accross a pair of calls if
the region of memory is decommitted and then committed again.
Memory protection should not be changed on decommitted memory, and if protection
is changed on memory while it is committed it should be returned to the orignal
protection before decommit is called.
*/
class PageReservation : private PageBlock {
public:
PageReservation()
: m_committed(0)
, m_writable(false)
, m_executable(false)
{
}
using PageBlock::base;
using PageBlock::size;
using PageBlock::operator bool;
void commit(void* start, size_t size)
{
ASSERT(*this);
ASSERT(isPageAligned(start));
ASSERT(isPageAligned(size));
ASSERT(contains(start, size));
m_committed += size;
OSAllocator::commit(start, size, m_writable, m_executable);
}
void decommit(void* start, size_t size)
{
ASSERT(*this);
ASSERT(isPageAligned(start));
ASSERT(isPageAligned(size));
ASSERT(contains(start, size));
m_committed -= size;
OSAllocator::decommit(start, size);
}
size_t committed()
{
return m_committed;
}
static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
{
ASSERT(isPageAligned(size));
return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false);
}
static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
{
ASSERT(isPageAligned(size));
return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true);
}
void deallocate()
{
ASSERT(!m_committed);
// Clear base & size before calling release; if this is *inside* allocation
// then we won't be able to clear then after deallocating the memory.
PageReservation tmp;
std::swap(tmp, *this);
ASSERT(tmp);
ASSERT(!*this);
OSAllocator::releaseDecommitted(tmp.base(), tmp.size());
}
private:
PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages)
: PageBlock(base, size, hasGuardPages)
, m_committed(0)
, m_writable(writable)
, m_executable(executable)
{
}
size_t m_committed;
bool m_writable;
bool m_executable;
};
}
using WTF::PageReservation;
#endif // PageReservation_h