MemoryArea.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MemoryArea.cpp -----------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ErrorHandling.h> 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/RegionFactory.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryArea.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/FileSystem.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cerrno> 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <fcntl.h> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/mman.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/stat.h> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MemoryArea 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::MemoryArea(RegionFactory& pRegionFactory) 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : m_RegionFactory(pRegionFactory), 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileDescriptor(-1), 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize(0), 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AccessFlags(ReadOnly), 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State(BadBit) { 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::~MemoryArea() 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // truncate the file to real size 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (isWritable()) 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao truncate(m_FileSize); 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unmap(); 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::truncate(size_t pLength) 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isWritable()) 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (-1 == ::ftruncate(m_FileDescriptor, static_cast<off_t>(pLength))) { 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("Cannot truncate `") + 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FilePath.native() + 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("' to size: ") + 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(pLength) + 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(".\n")); 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::map(const sys::fs::Path& pPath, int pFlags) 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AccessFlags = pFlags; 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FilePath = pPath; 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags); 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (-1 == m_FileDescriptor) { 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao struct stat st; 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int stat_result = ::stat(m_FilePath.native().c_str(), &st); 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0x0 == stat_result) { 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize = static_cast<size_t>(st.st_size); 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State = GoodBit; 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize = 0x0; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= BadBit; 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::map(const sys::fs::Path& pPath, int pFlags, int pMode) 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AccessFlags = pFlags; 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FilePath = pPath; 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags, pMode); 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (-1 == m_FileDescriptor) { 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao struct stat st; 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int stat_result = ::stat(m_FilePath.native().c_str(), &st); 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0x0 == stat_result) { 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize = static_cast<size_t>(st.st_size); 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State = GoodBit; 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize = 0x0; 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= BadBit; 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::unmap() 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (isMapped()) { 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (-1 == ::close(m_FileDescriptor)) 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileDescriptor = -1; 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AccessFlags = ReadOnly; 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isMapped() const 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (-1 != m_FileDescriptor); 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isGood() const 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0x0 == (m_State & (BadBit | FailBit)); 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isBad() const 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0x0 != (m_State & BadBit); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isFailed() const 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0x0 != (m_State & FailBit); 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isEOF() const 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0x0 != (m_State & EOFBit); 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isReadable() const 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (((m_AccessFlags & AccessMask) == ReadOnly) || 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((m_AccessFlags & AccessMask) == ReadWrite)); 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isWritable() const 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (((m_AccessFlags & AccessMask) == WriteOnly) || 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((m_AccessFlags & AccessMask) == ReadWrite)); 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint MemoryArea::rdstate() const 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return m_State; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::setState(MemoryArea::IOState pState) 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= pState; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::clear(MemoryArea::IOState pState) 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State = pState; 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The layout of MemorySpace in the virtual memory space 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// | : page boundary 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// [,]: MemoryRegion 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// - : fillment 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// = : data 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |---[=|====|====|==]--| 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ^ ^ ^ ^ 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// | | | | 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// | r_start +r_len | 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.data +space.size 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.file_offset is the offset of the mapped file segment from the start of 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// (space.data, r_start) and (r_len, space.size) are zero. 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength) 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isMapped() || !isGood()) 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0x0 == pLength) 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isWritable() && (pOffset + pLength) > m_FileSize) 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (isWritable() && (pOffset + pLength) > m_FileSize) { 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If the memory area is writable, user can expand the size of file by 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // request a region larger than the file. 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // MemoryArea should enlarge the file if the requested region is larger 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // than the file. 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileSize = page_boundary(pOffset + pLength + 1); 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao truncate(m_FileSize); 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Space* space = find(pOffset, pLength); 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MemoryArea::Address r_start = 0; 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (NULL == space) { 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // the space does not exist, create a new space. 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space = new Space(this, pOffset, pLength); 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_SpaceList.push_back(space); 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(space->type = policy(pOffset, pLength)) { 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::MMAPED: { 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int mm_prot, mm_flag; 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (isWritable()) { 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mm_prot = PROT_READ | PROT_WRITE; 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mm_flag = MAP_FILE | MAP_SHARED; 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mm_prot = PROT_READ; 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mm_flag = MAP_FILE | MAP_PRIVATE; 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->file_offset = page_offset(pOffset); 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // The space's size may be larger than filesize. 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->size = page_boundary(pLength + pOffset + 1 - space->file_offset); 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->data = (Address) ::mmap(NULL, 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->size, 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mm_prot, mm_flag, 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FileDescriptor, 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->file_offset); 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (space->data == MAP_FAILED) { 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("cannot open memory map file :") + 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FilePath.native() + 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(" (") + 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao sys::fs::detail::strerror(errno) + 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(").\n")); 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao r_start = space->data + (pOffset - space->file_offset); 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::ALLOCATED_ARRAY: { 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // space->offset and space->size are set in constructor. We only need 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // to set up data. 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao space->data = new unsigned char[pLength]; 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao r_start = space->data; 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if ((m_AccessFlags & AccessMask) != WriteOnly) { 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Read data from the backend file. 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!read(*space)) { 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("Failed to read data from ") + 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_FilePath.native() + 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(" (") + 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao sys::fs::detail::strerror(errno) + 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(") at offset ") + 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(pOffset) + 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(" lenght ") + 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(pLength) + llvm::Twine(".\n")); 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } // case 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: { 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error("unhandled space type\n"); 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } // switch 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { // found 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t distance = pOffset - space->file_offset; 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao r_start = space->data + distance; 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // now, we have a legal space to hold the new MemoryRegion 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return m_RegionFactory.produce(space, r_start, pLength); 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// release - release a MemoryRegion 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::release(MemoryRegion* pRegion) 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isMapped() || !isGood()) 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Space *space = pRegion->parent(); 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_RegionFactory.destruct(pRegion); 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 == space->region_num) { 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao write(*space); 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_SpaceList.remove(*space); 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao release(space); 2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::clean() 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_RegionFactory.clear(); 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao SpaceList::iterator sIter, sEnd = m_SpaceList.end(); 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) { 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao write(*sIter); 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao release(sIter); 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_SpaceList.clear(); 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::sync() 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao SpaceList::iterator sIter, sEnd = m_SpaceList.end(); 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) { 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao write(*sIter); 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::Space* MemoryArea::find(size_t pOffset, size_t pLength) 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao SpaceList::iterator sIter, sEnd = m_SpaceList.end(); 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) { 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (sIter->file_offset <= pOffset && 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (pOffset+pLength) <= (sIter->file_offset+sIter->size) ) { // within 3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return sIter; 3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::release(MemoryArea::Space* pSpace) 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch (pSpace->type) { 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::ALLOCATED_ARRAY: { 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao delete [] pSpace->data; 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::MMAPED: { 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ::munmap(pSpace->data, pSpace->size); 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::Space::Type MemoryArea::policy(off_t pOffset, size_t pLength) 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pLength < threshold) 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return Space::ALLOCATED_ARRAY; 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return Space::MMAPED; 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaossize_t MemoryArea::readToBuffer(sys::fs::detail::Address pBuf, 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t pSize, size_t pOffset) { 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(((m_AccessFlags & AccessMask) != WriteOnly) && 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Write-only file cannot be read!"); 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ssize_t read_bytes = sys::fs::detail::pread(m_FileDescriptor, pBuf, 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSize, pOffset); 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (static_cast<size_t>(read_bytes) != pSize) { 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Some error occurred during pread(). 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (read_bytes < 0) { 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else if (static_cast<size_t>(read_bytes) < pSize) { 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= EOFBit; 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if ((m_AccessFlags & AccessMask) != ReadWrite) { 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Files which is not read-write are not allowed read beyonds the EOF 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // marker. 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= BadBit; 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= BadBit; 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return read_bytes; 3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::read(Space& pSpace) { 3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isGood() || !isReadable()) 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pSpace.type == Space::ALLOCATED_ARRAY) { 3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao readToBuffer(pSpace.data, pSpace.size, pSpace.file_offset); 3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return isGood(); 3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Data associated with mmap()'ed space is already at the position the 3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // pSpace points to. 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pSpace.type == Space::MMAPED) && "Unknown type of Space!"); 3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::write(const Space& pSpace) 3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!isMapped() || !isGood() || !isWritable()) 3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(pSpace.type) { 4025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::MMAPED: { 4035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(-1 == ::msync(pSpace.data, pSpace.size, MS_SYNC)) 4045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 4055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case Space::ALLOCATED_ARRAY: { 4085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ssize_t write_bytes = sys::fs::detail::pwrite(m_FileDescriptor, 4095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSpace.data, 4105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSpace.size, 4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSpace.file_offset); 4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 > write_bytes) { 4135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= FailBit; 4145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 == write_bytes && 0 != pSpace.size) 4175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= BadBit; 4185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if ( pSpace.size > static_cast<size_t>(write_bytes) ) 4195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_State |= EOFBit; 4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: 4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 427