src/Emu/Utility/System/Memory/HeapAllocator.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 #include <pch.h>
00033 
00034 #include "Emu/Utility/System/Memory/HeapAllocator.h"
00035 
00036 using namespace std;
00037 using namespace Onikiri;
00038 using namespace Onikiri::EmulatorUtility;
00039 
00040 HeapAllocator::HeapAllocator(u64 pageSize) : m_pageSize(pageSize)
00041 {
00042 }
00043 
00044 bool HeapAllocator::AddMemoryBlock(u64 start, u64 length)
00045 {
00046     MemoryBlock mb;
00047     mb.Addr = start;
00048     mb.Bytes = length;
00049 
00050     // d`FbN
00051     typedef list<MemoryBlock>::iterator iterator;
00052     for (iterator e = m_freeList.begin(); e != m_freeList.end(); ++e) {
00053         if (e->Intersects(mb))
00054             return false;
00055     }
00056     for (iterator e = m_allocList.begin(); e != m_allocList.end(); ++e) {
00057         if (e->Intersects(mb))
00058             return false;
00059     }
00060     m_freeList.push_back(mb);
00061 
00062     return true;
00063 }
00064 
00065 // addr m
00066 u64 HeapAllocator::IsIntersected(u64 addr, u64 length) const
00067 {
00068     MemoryBlock mb;
00069     mb.Addr = addr;
00070     mb.Bytes = length;
00071     typedef list<MemoryBlock>::const_iterator const_iterator;
00072     for (const_iterator e = m_allocList.begin(); e != m_allocList.end(); ++e) {
00073         if (e->Intersects(mb))
00074             return true;
00075     }
00076     return false;
00077 }
00078 
00079 u64 HeapAllocator::Alloc(u64 addr, u64 length)
00080 {
00081     if (addr != 0)
00082         return 0;
00083     
00084     // legth is expanded to a page boundary.
00085     length = in_pages(length) * m_pageSize;
00086 
00087     typedef list<MemoryBlock>::iterator iterator;
00088     for (iterator e = m_freeList.begin(); e != m_freeList.end(); ++e) {
00089         // first fit
00090         if (e->Bytes > length) {
00091             // m
00092 
00093             MemoryBlock mb;
00094             mb.Addr = e->Addr;
00095             mb.Bytes = length;
00096 
00097             BlockList::iterator alloc_ins_pos = lower_bound(m_allocList.begin(), m_allocList.end(), mb);
00098             m_allocList.insert(alloc_ins_pos, mb);
00099 
00100             e->Addr = e->Addr + length;
00101             e->Bytes = e->Bytes - length;
00102             if (e->Bytes == 0)
00103                 m_freeList.erase(e);
00104             
00105             return mb.Addr;
00106         }
00107     }
00108 
00109     // mクs
00110     return 0;
00111 }
00112 
00113 u64 HeapAllocator::ReAlloc(u64 addr, u64 old_size, u64 new_size)
00114 {
00115     // ubNTCY
00116     if (old_size == new_size)
00117         return addr;
00118 
00119     typedef list<MemoryBlock>::iterator iterator;
00120 
00121     // legth is expanded to a page boundary.
00122     new_size = in_pages(new_size) * m_pageSize;
00123     BlockList::iterator alloc_it = find(m_allocList.begin(), m_allocList.end(), MemoryBlock(addr));
00124 
00125     // ubN
00126     if (alloc_it == m_allocList.end())
00127         return 0;
00128 
00129     if (new_size < old_size) {
00130         // ubN
00131 
00132         // 
00133         MemoryBlock free_mb;
00134         free_mb.Addr = alloc_it->Addr+new_size;
00135         free_mb.Bytes = alloc_it->Bytes-new_size;
00136 
00137         BlockList::iterator free_ins_pos = lower_bound(m_freeList.begin(), m_freeList.end(), free_mb);
00138         m_freeList.insert(free_ins_pos, free_mb);
00139 
00140         // ubN
00141         alloc_it->Bytes = new_size;
00142 
00143         IntegrateFreeBlocks();
00144     }
00145     else {
00146         // ubN
00147         MemoryBlock oldmb;
00148         oldmb.Addr = addr;
00149         oldmb.Bytes = old_size;
00150         // ubNT
00151         iterator next_free = upper_bound(m_freeList.begin(), m_freeList.end(), oldmb);
00152         iterator next_alloc = upper_bound(m_allocList.begin(), m_allocList.end(), oldmb);
00153 
00154         // 
00155         if (next_free == m_freeList.end())
00156             return 0;
00157         // ubNallocated
00158         if (next_alloc != m_allocList.end() && next_alloc->Addr < next_free->Addr)
00159             return 0;
00160 
00161         // 
00162         if (alloc_it->Bytes + next_free->Bytes < new_size)
00163             return 0;
00164 
00165         // remap
00166         next_free->Bytes -= new_size - alloc_it->Bytes;
00167         next_free->Addr += new_size - alloc_it->Bytes;
00168         alloc_it->Bytes = new_size;
00169 
00170         if (next_free->Bytes == 0)
00171             m_freeList.erase(next_free);
00172     }
00173     return alloc_it->Addr;
00174 }
00175 
00176 
00177 bool HeapAllocator::Free(u64 addr)
00178 {
00179     BlockList::iterator alloc_it = find(m_allocList.begin(), m_allocList.end(), MemoryBlock(addr));
00180 
00181     // ubN
00182     if (alloc_it == m_allocList.end())
00183         return false;
00184 
00185     return Free(alloc_it->Addr, alloc_it->Bytes);
00186 }
00187 
00188 bool HeapAllocator::Free(u64 addr, u64 size)
00189 {
00190     // Alloc
00191     if (m_allocList.size() == 0)
00192         return false;
00193 
00194     // allocList free_mb : [addr, addr+size) ubNT
00195     MemoryBlock free_mb(addr, size);
00196     // addr AhXubNC
00197     BlockList::iterator alloc_it = --upper_bound(m_allocList.begin(), m_allocList.end(), free_mb);
00198     // free_mb ubN
00199     if (alloc_it->Contains( free_mb ))
00200         return false;
00201 
00202     // free_mb  Free  alloc_itubN3
00203 
00204     // free_mb 
00205     u64 free_mb_end = free_mb.Addr+free_mb.Bytes;
00206     MemoryBlock alloc_mb2( free_mb_end , alloc_it->Addr+alloc_it->Bytes - free_mb_end );
00207     if (alloc_mb2.Bytes != 0)
00208         m_allocList.insert(++BlockList::iterator(alloc_it), alloc_mb2);
00209     
00210     // free_mb O
00211     alloc_it->Bytes = addr - alloc_it->Addr;
00212     if (alloc_it->Bytes == 0)
00213         m_allocList.erase(alloc_it);
00214 
00215     // free_mb
00216     BlockList::iterator free_ins_pos = lower_bound(m_freeList.begin(), m_freeList.end(), free_mb);
00217     m_freeList.insert(free_ins_pos, free_mb);
00218 
00219     IntegrateFreeBlocks();
00220 
00221     return true;
00222 }
00223 
00224 // addr AllocTCY
00225 u64 HeapAllocator::GetBlockSize(u64 addr) const
00226 {
00227     BlockList::const_iterator alloc_it = find(m_allocList.begin(), m_allocList.end(), MemoryBlock(addr));
00228 
00229     if (alloc_it == m_allocList.end())
00230         return 0;
00231     else
00232         return alloc_it->Bytes;
00233 }
00234 
00235 // 
00236 void HeapAllocator::IntegrateFreeBlocks()
00237 {
00238     typedef list<MemoryBlock>::iterator iterator;
00239 
00240     // C
00241     for (iterator e = m_freeList.begin(); e != m_freeList.end(); ++e) {
00242         iterator next;
00243         for (next = e, ++next; next != m_freeList.end(); next = e, ++next) {
00244             if (e->Addr + e->Bytes == next->Addr) {
00245                 e->Bytes += next->Bytes;
00246                 m_freeList.erase(next);
00247             }
00248             else {
00249                 break;
00250             }
00251         }
00252     }
00253 }
00254 
00255 //void HeapAllocator::Dump() const
00256 //{
00257 //  for (iterator e = m_allocList.begin(); e != m_allocList.end(); ++e) {
00258 //      cerr << "(" << e->Addr << ", " << e->Bytes << ") ";
00259 //  }
00260 //  cerr << endl;
00261 //  for (iterator e = m_freeList.begin(); e != m_freeList.end(); ++e) {
00262 //      cerr << "(" << e->Addr << ", " << e->Bytes << ") ";
00263 //  }
00264 //  cerr << endl;
00265 //}

Onikiri2に対してTue Jun 18 14:34:20 2013に生成されました。  doxygen 1.4.7