MemoryArea.cpp revision affc150dc44fab1911775a49636d0ce85333b634
1//===- MemoryArea.cpp -----------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include <mcld/Support/RegionFactory.h> 10#include <mcld/Support/MemoryArea.h> 11#include <mcld/Support/MemoryRegion.h> 12#include <mcld/Support/FileHandle.h> 13#include <mcld/Support/MsgHandling.h> 14 15using namespace mcld; 16 17//===--------------------------------------------------------------------===// 18// MemoryArea 19 20// MemoryArea - special constructor 21// This constructor is used for *SPECIAL* situation. I'm sorry I can not 22// reveal what is the special situation. 23MemoryArea::MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse) 24 : m_RegionFactory(pRegionFactory), m_pFileHandle(NULL) { 25 m_SpaceList.push_back(&pUniverse); 26} 27 28MemoryArea::MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle) 29 : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) { 30} 31 32MemoryArea::~MemoryArea() 33{ 34} 35 36// The layout of MemorySpace in the virtual memory space 37// 38// | : page boundary 39// [,]: MemoryRegion 40// - : fillment 41// = : data 42// 43// |---[=|====|====|==]--| 44// ^ ^ ^ ^ 45// | | | | 46// | r_start +r_len | 47// space.data +space.size 48// 49// space.file_offset is the offset of the mapped file segment from the start of 50// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of 51// (space.data, r_start) and (r_len, space.size) are zero. 52// 53MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength) 54{ 55 Space* space = find(pOffset, pLength); 56 if (NULL == space) { 57 58 // not found 59 if (NULL == m_pFileHandle) { 60 // if m_pFileHandle is NULL, clients delegate us an universal Space and 61 // we never remove it. In that way, space can not be NULL. 62 unreachable(diag::err_out_of_range_region); 63 } 64 65 space = Space::createSpace(*m_pFileHandle, pOffset, pLength); 66 m_SpaceList.push_back(space); 67 } 68 69 // adjust r_start 70 off_t distance = pOffset - space->start(); 71 void* r_start = space->memory() + distance; 72 73 // now, we have a legal space to hold the new MemoryRegion 74 return m_RegionFactory.produce(*space, r_start, pLength); 75} 76 77// release - release a MemoryRegion 78void MemoryArea::release(MemoryRegion* pRegion) 79{ 80 if (NULL == pRegion) 81 return; 82 83 Space *space = pRegion->parent(); 84 m_RegionFactory.destruct(pRegion); 85 86 if (0 == space->numOfRegions()) { 87 88 if (NULL != m_pFileHandle) { 89 // if m_pFileHandle is NULL, clients delegate us an universal Space and 90 // we never remove it. Otherwise, we have to synchronize and release 91 // Space. 92 if (m_pFileHandle->isWritable()) { 93 // synchronize writable space before we release it. 94 Space::syncSpace(space, *m_pFileHandle); 95 } 96 Space::releaseSpace(space, *m_pFileHandle); 97 } 98 m_SpaceList.erase(space); 99 } 100} 101 102// clear - release all MemoryRegions 103void MemoryArea::clear() 104{ 105 if (NULL == m_pFileHandle) 106 return; 107 108 if (m_pFileHandle->isWritable()) { 109 SpaceList::iterator space, sEnd = m_SpaceList.end(); 110 for (space = m_SpaceList.begin(); space != sEnd; ++space) { 111 Space::syncSpace(space, *m_pFileHandle); 112 Space::releaseSpace(space, *m_pFileHandle); 113 } 114 } 115 else { 116 SpaceList::iterator space, sEnd = m_SpaceList.end(); 117 for (space = m_SpaceList.begin(); space != sEnd; ++space) 118 Space::releaseSpace(space, *m_pFileHandle); 119 } 120 121 m_SpaceList.clear(); 122} 123 124//===--------------------------------------------------------------------===// 125// SpaceList methods 126Space* MemoryArea::find(size_t pOffset, size_t pLength) 127{ 128 SpaceList::iterator sIter, sEnd = m_SpaceList.end(); 129 for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) { 130 if (sIter->start() <= pOffset && 131 (pOffset+pLength) <= (sIter->start()+sIter->size()) ) { 132 // within 133 return sIter; 134 } 135 } 136 return NULL; 137} 138 139const Space* MemoryArea::find(size_t pOffset, size_t pLength) const 140{ 141 SpaceList::const_iterator sIter, sEnd = m_SpaceList.end(); 142 for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) { 143 if (sIter->start() <= pOffset && 144 (pOffset+pLength) <= (sIter->start()+sIter->size()) ) { 145 // within 146 return sIter; 147 } 148 } 149 return NULL; 150} 151 152