int clone_area(const char name[], void **clone_addr, int searchFlags, PageProtection protection, int sourceArea) { Area *area = static_cast<Area*>(GetResource(sourceArea, OBJ_AREA)); if (area == 0) { printf("clone_area: source area id %08x is invalid\n", sourceArea); return E_BAD_HANDLE; } unsigned int addr = INVALID_PAGE; if (searchFlags & EXACT_ADDRESS) addr = reinterpret_cast<unsigned int>(*clone_addr); // It is important that CreateArea not incur a fault! char nameCopy[OS_NAME_LENGTH]; if (!CopyUser(nameCopy, name, OS_NAME_LENGTH)) return E_BAD_ADDRESS; Area *newArea = AddressSpace::GetCurrentAddressSpace()->CreateArea(nameCopy, area->GetSize(), AREA_NOT_WIRED, protection | USER_READ | SYSTEM_READ | ((protection & USER_WRITE) ? SYSTEM_WRITE : 0), area->GetPageCache(), 0, addr, searchFlags); area->ReleaseRef(); if (newArea == 0) return E_ERROR; *clone_addr = reinterpret_cast<void*>(newArea->GetBaseAddress()); return OpenHandle(newArea); }
// Only works for areas in the current team. int resize_area(int area_id, unsigned int newSize) { Area *area = static_cast<Area*>(GetResource(area_id, OBJ_AREA)); if (area == 0) return E_BAD_HANDLE; int error = AddressSpace::GetCurrentAddressSpace()->ResizeArea(area, newSize); area->ReleaseRef(); return error; }
int delete_area(int handle) { Area *area = static_cast<Area*>(GetResource(handle, OBJ_AREA)); if (area == 0) return E_BAD_HANDLE; Thread::GetRunningThread()->GetTeam()->GetHandleTable()->Close(handle); AddressSpace::GetCurrentAddressSpace()->DeleteArea(area); area->ReleaseRef(); return E_NO_ERROR; }
AddressSpace::~AddressSpace() { for (;;) { // This is a very clunky way to step through the area tree while // removing items from it. The iterator must be re-created because // it will become invalid after each area is removed from the tree. AVLTreeIterator iterator(fAreas, true); Area *area = static_cast<Area*>(iterator.GetCurrent()); if (area == 0) break; // Don't unmap the pages because: // 1. The address space is going away anyway // 2. This would unmap the kernel. :) fAreas.Remove(area); area->ReleaseRef(); } delete fPhysicalMap; }