diff --git a/kernel/include/kernel/Memory/GeneralAllocator.h b/kernel/include/kernel/Memory/GeneralAllocator.h index 2c4dee551..19a5bb4f1 100644 --- a/kernel/include/kernel/Memory/GeneralAllocator.h +++ b/kernel/include/kernel/Memory/GeneralAllocator.h @@ -19,6 +19,8 @@ namespace Kernel vaddr_t allocate(size_t); bool deallocate(vaddr_t); + BAN::ErrorOr clone(MMU&); + private: struct Allocation { diff --git a/kernel/kernel/Memory/GeneralAllocator.cpp b/kernel/kernel/Memory/GeneralAllocator.cpp index 076a28d61..c2f24b751 100644 --- a/kernel/kernel/Memory/GeneralAllocator.cpp +++ b/kernel/kernel/Memory/GeneralAllocator.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace Kernel @@ -61,4 +62,45 @@ namespace Kernel return false; } + BAN::ErrorOr GeneralAllocator::clone(MMU& new_mmu) + { + GeneralAllocator* allocator = new GeneralAllocator(new_mmu); + if (allocator == nullptr) + return BAN::Error::from_errno(ENOMEM); + + MMUScope _(m_mmu); + ASSERT(m_mmu.is_page_free(0)); + + for (auto& allocation : m_allocations) + { + Allocation new_allocation; + ASSERT(new_mmu.is_range_free(allocation.address, allocation.pages.size() * PAGE_SIZE)); + + new_allocation.address = allocation.address; + MUST(new_allocation.pages.reserve(allocation.pages.size())); + + uint8_t flags = m_mmu.get_page_flags(allocation.address); + for (size_t i = 0; i < allocation.pages.size(); i++) + { + paddr_t paddr = Heap::get().take_free_page(); + ASSERT(paddr); + + vaddr_t vaddr = allocation.address + i * PAGE_SIZE; + + MUST(new_allocation.pages.push_back(paddr)); + new_mmu.map_page_at(paddr, vaddr, flags); + + m_mmu.map_page_at(paddr, 0, MMU::Flags::ReadWrite | MMU::Flags::Present); + m_mmu.invalidate(0); + memcpy((void*)0, (void*)vaddr, PAGE_SIZE); + } + + MUST(allocator->m_allocations.push_back(BAN::move(new_allocation))); + } + m_mmu.unmap_page(0); + m_mmu.invalidate(0); + + return allocator; + } + } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 425aa6500..591cf4bce 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -218,10 +218,10 @@ namespace Kernel ASSERT(m_threads.front() == &Thread::current()); //for (auto& allocator : m_fixed_width_allocators) - // MUST(forked->m_fixed_width_allocators.push_back(allocator.clone())); + // MUST(forked->m_fixed_width_allocators.push_back(MUST(allocator->clone(forked->mmu())))); - //if (m_general_allocator) - // forked->m_general_allocator = m_general_allocator->clone(); + if (m_general_allocator) + forked->m_general_allocator = MUST(m_general_allocator->clone(forked->mmu())); Thread* thread = MUST(m_threads.front()->clone(forked, rsp, rip)); forked->add_thread(thread); diff --git a/userspace/test/test.cpp b/userspace/test/test.cpp index 8ba9b1e6d..0f64e7aba 100644 --- a/userspace/test/test.cpp +++ b/userspace/test/test.cpp @@ -8,15 +8,18 @@ int main() { + char* string = (char*)malloc(5000); + strcpy(string, "Hello"); + printf("forking\n"); pid_t pid = fork(); if (pid == 0) { - printf("child\n"); + printf("child '%s'\n", string); return 0; } - printf("parent\n"); + printf("parent '%s'\n", string); return 0; }