Area* AddressSpace::CreateArea(const char name[], unsigned int size, AreaWiring wiring, PageProtection protection, PageCache *cache, off_t offset, unsigned int va, int flags) { if (size % PAGE_SIZE != 0 || size == 0) return 0; if (cache != 0 && cache->Commit(offset + size) != offset + size) return 0; fAreaLock.LockWrite(); if (va == INVALID_PAGE) va = FindFreeRange(size, flags); else if (va % PAGE_SIZE != 0 || !fAreas.IsRangeFree(va, va + size - 1)) va = INVALID_PAGE; Area *area = 0; if (va != INVALID_PAGE) { area = new Area(name, protection, cache, offset, wiring); fAreas.Add(area, va, va + size - 1); if (wiring & AREA_WIRED) { for (unsigned int aroffs = 0; aroffs < size; aroffs += PAGE_SIZE) { Page *page = area->GetPageCache()->GetPage(area->GetCacheOffset() + aroffs, false); page->Wire(); fPhysicalMap->Map(va + aroffs, page->GetPhysicalAddress(), protection); } } } fChangeCount++; fAreaLock.UnlockWrite(); return area; }
status_t AddressSpace::ResizeArea(Area *area, unsigned int newSize) { if (newSize == 0) return E_INVALID_OPERATION; fAreaLock.LockWrite(); if (newSize > area->GetSize()) { // Grow the area. if (area->GetPageCache()->Commit(newSize) != newSize) { fAreaLock.UnlockWrite(); return E_NO_MEMORY; } if (area->GetBaseAddress() + newSize < area->GetBaseAddress() // wrap || !fAreas.IsRangeFree(area->GetBaseAddress() + area->GetSize(), area->GetBaseAddress() + newSize)) { fAreaLock.UnlockWrite(); return E_NO_MEMORY; } if (area->GetWiring() == AREA_WIRED) { for (unsigned int aroffs = area->GetSize(); aroffs < newSize; aroffs += PAGE_SIZE) { Page *page = area->GetPageCache()->GetPage(area->GetCacheOffset() + aroffs, false); page->Wire(); fPhysicalMap->Map(area->GetBaseAddress() + aroffs, page->GetPhysicalAddress(), area->GetProtection()); } } } else if (newSize < area->GetSize()) { // Shrink the area. fPhysicalMap->Unmap(area->GetBaseAddress() + newSize, area->GetSize() - newSize); area->GetPageCache()->Commit(newSize); } fAreas.Resize(area, newSize); fChangeCount++; fAreaLock.UnlockWrite(); return E_NO_ERROR; }