| 1 | /* | 
| 2 |  * Copyright (C) 2010 Apple Inc. All rights reserved. | 
| 3 |  * | 
| 4 |  * Redistribution and use in source and binary forms, with or without | 
| 5 |  * modification, are permitted provided that the following conditions | 
| 6 |  * are met: | 
| 7 |  * 1. Redistributions of source code must retain the above copyright | 
| 8 |  *    notice, this list of conditions and the following disclaimer. | 
| 9 |  * 2. Redistributions in binary form must reproduce the above copyright | 
| 10 |  *    notice, this list of conditions and the following disclaimer in the | 
| 11 |  *    documentation and/or other materials provided with the distribution. | 
| 12 |  * | 
| 13 |  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 
| 14 |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 15 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
| 16 |  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR | 
| 17 |  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
| 18 |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
| 19 |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
| 20 |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 
| 21 |  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 22 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 23 |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
| 24 |  */ | 
| 25 |  | 
| 26 | #ifndef PageReservation_h | 
| 27 | #define  | 
| 28 |  | 
| 29 | #include <wtf/PageAllocation.h> | 
| 30 |  | 
| 31 | namespace WTF { | 
| 32 |  | 
| 33 | /* | 
| 34 |     PageReservation | 
| 35 |  | 
| 36 |     Like PageAllocation, the PageReservation class provides a cross-platform memory | 
| 37 |     allocation interface, but with a set of capabilities more similar to that of | 
| 38 |     VirtualAlloc than posix mmap.  PageReservation can be used to allocate virtual | 
| 39 |     memory without committing physical memory pages using PageReservation::reserve. | 
| 40 |     Following a call to reserve all memory in the region is in a decommited state, | 
| 41 |     in which the memory should not be used (accessing the memory may cause a fault). | 
| 42 |  | 
| 43 |     Before using memory it must be committed by calling commit, which is passed start | 
| 44 |     and size values (both of which require system page size granularity).  One the | 
| 45 |     committed memory is no longer needed 'decommit' may be called to return the | 
| 46 |     memory to its devommitted state.  Commit should only be called on memory that is | 
| 47 |     currently decommitted, and decommit should only be called on memory regions that | 
| 48 |     are currently committed.  All memory should be decommited before the reservation | 
| 49 |     is deallocated.  Values in memory may not be retained accross a pair of calls if | 
| 50 |     the region of memory is decommitted and then committed again. | 
| 51 |  | 
| 52 |     Memory protection should not be changed on decommitted memory, and if protection | 
| 53 |     is changed on memory while it is committed it should be returned to the orignal | 
| 54 |     protection before decommit is called. | 
| 55 | */ | 
| 56 |  | 
| 57 | class  : private PageBlock { | 
| 58 | public: | 
| 59 |     () | 
| 60 |         : m_committed(0) | 
| 61 |         , m_writable(false) | 
| 62 |         , m_executable(false) | 
| 63 |     { | 
| 64 |     } | 
| 65 |  | 
| 66 |     using PageBlock::base; | 
| 67 |     using PageBlock::size; | 
| 68 |  | 
| 69 | #ifndef __clang__ | 
| 70 |     using PageBlock::operator bool; | 
| 71 | #else | 
| 72 |     // FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access | 
| 73 |     // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool". | 
| 74 |     () const { return PageBlock::operator bool(); } | 
| 75 | #endif | 
| 76 |  | 
| 77 |     void (void* start, size_t size) | 
| 78 |     { | 
| 79 |         ASSERT(*this); | 
| 80 |         ASSERT(isPageAligned(start)); | 
| 81 |         ASSERT(isPageAligned(size)); | 
| 82 |         ASSERT(contains(start, size)); | 
| 83 |  | 
| 84 |         m_committed += size; | 
| 85 |         OSAllocator::commit(start, size, writable: m_writable, executable: m_executable); | 
| 86 |     } | 
| 87 |  | 
| 88 |     void (void* start, size_t size) | 
| 89 |     { | 
| 90 |         ASSERT(*this); | 
| 91 |         ASSERT(isPageAligned(start)); | 
| 92 |         ASSERT(isPageAligned(size)); | 
| 93 |         ASSERT(contains(start, size)); | 
| 94 |  | 
| 95 |         m_committed -= size; | 
| 96 |         OSAllocator::decommit(start, size); | 
| 97 |     } | 
| 98 |  | 
| 99 |     size_t () | 
| 100 |     { | 
| 101 |         return m_committed; | 
| 102 |     } | 
| 103 |  | 
| 104 |     static PageReservation (size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) | 
| 105 |     { | 
| 106 |         ASSERT(isPageAligned(size)); | 
| 107 |         return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable); | 
| 108 |     } | 
| 109 |  | 
| 110 |     void () | 
| 111 |     { | 
| 112 |         ASSERT(!m_committed); | 
| 113 |  | 
| 114 |         // Clear base & size before calling release; if this is *inside* allocation | 
| 115 |         // then we won't be able to clear then after deallocating the memory. | 
| 116 |         PageReservation tmp; | 
| 117 |         std::swap(a&: tmp, b&: *this); | 
| 118 |  | 
| 119 |         ASSERT(tmp); | 
| 120 |         ASSERT(!*this); | 
| 121 |  | 
| 122 |         OSAllocator::releaseDecommitted(tmp.realBase(), tmp.realSize()); | 
| 123 |     } | 
| 124 |  | 
| 125 | private: | 
| 126 |     (void* base, size_t size, bool writable, bool executable) | 
| 127 |         : PageBlock(base, size, false) | 
| 128 |         , m_committed(0) | 
| 129 |         , m_writable(writable) | 
| 130 |         , m_executable(executable) | 
| 131 |     { | 
| 132 |     } | 
| 133 |  | 
| 134 |     size_t ; | 
| 135 |     bool ; | 
| 136 |     bool ; | 
| 137 | }; | 
| 138 |  | 
| 139 | } | 
| 140 |  | 
| 141 | using WTF::PageReservation; | 
| 142 |  | 
| 143 | #endif // PageReservation_h | 
| 144 |  |