diff --git a/k-alloc.cc b/k-alloc.cc index f7b52e5210a6f869a9f3f896d8cbdefee88d8e80..899e3bbaa518f1ad8dcc9587356b2542b6f6f205 100644 --- a/k-alloc.cc +++ b/k-alloc.cc @@ -180,6 +180,7 @@ void kfree(void* ptr) { block *pBlock = block::blockAtKernelAddress(ptr); assert(!(pBlock->isFree)); assert(pBlock->ka == ptr); + log_printf("kfree of block starting at frame %d with order %d\n",pBlock->frameNumber(),pBlock->order); auto irqs = mem_lock.lock(); @@ -188,6 +189,7 @@ void kfree(void* ptr) { pBlock->cloalesce(); mem_lock.unlock(irqs); + } void block::cloalesce() { diff --git a/k-cpu.cc b/k-cpu.cc index 061fcfa1b9b3e637a464bccabeaa44b6f6fdf859..d6fd6ba6f699b6562ef2ee082660e539c98122e3 100644 --- a/k-cpu.cc +++ b/k-cpu.cc @@ -91,6 +91,13 @@ void cpustate::schedule(proc* yielding_from) { // increment schedule counter ++nschedule_; + if(yielding_from->pstate_ == proc::ps_exit) { + log_printf("\nStart exit for PID %d\n", yielding_from->id_); + delete yielding_from; + yielding_from = idle_task_; + log_printf("End Process exit\n\n"); + } + // find a runnable process while (!current_ || current_->pstate_ != proc::ps_runnable diff --git a/k-memviewer.cc b/k-memviewer.cc index 69574b971420973b499fd9a356b0186f1e1f8e11..ce4d7236fd6db10b8986dad595d75a29d9dbae67 100644 --- a/k-memviewer.cc +++ b/k-memviewer.cc @@ -97,7 +97,7 @@ void memusage::refresh() { auto irqs = p->lock_pagetable_read(); if (p->pagetable_ && p->pagetable_ != early_pagetable) { - for (ptiter it(p); it.low(); it.next()) { + for (ptiter it(p,pid); it.low(); it.next()) { mark(it.pa(), f_kernel | f_process(pid)); } mark(ka2pa(p->pagetable_), f_kernel | f_process(pid)); diff --git a/k-proc.cc b/k-proc.cc index e2079f2ad12457dc31c55481c0c7d61e983c69ba..6318d4c07d64f306964a4cd77c16cae8e61f189d 100644 --- a/k-proc.cc +++ b/k-proc.cc @@ -12,6 +12,30 @@ spinlock ptable_lock; // protects `ptable` proc::proc() { } +proc::~proc() { + log_printf("proc::~proc\n"); + if(!pagetable_){ + return; + } + int pid = id_; + { + spinlock_guard guard(ptable_lock); + ptable[pid] = nullptr; + } + for (vmiter parentIterator(this); parentIterator.low(); parentIterator.next()) { + if (parentIterator.user()) { + auto range = physical_ranges.find((uintptr_t) parentIterator.pa()); + bool isConsole = range->type() == mem_console; + if(!isConsole) { + parentIterator.kfree_page(); + } + } + } + for (ptiter it(pagetable_,0); it.low(); it.next()) { + it.kfree_ptp(); // `kfree(ptp())` + clear mapping + } + delete pagetable_; +} // proc::init_user(pid, pt) // Initialize this `proc` as a new runnable user process with PID `pid` diff --git a/k-vmiter.hh b/k-vmiter.hh index 54f6c2f2512bcd224678e1be820237dd738baa67..d05f214f57fa1352b58fa40040d035af4f9d13b3 100644 --- a/k-vmiter.hh +++ b/k-vmiter.hh @@ -104,8 +104,8 @@ class vmiter { class ptiter { public: // Initialize a physical iterator for `pt` with initial virtual address 0 - inline ptiter(x86_64_pagetable* pt); - inline ptiter(const proc* p); + inline ptiter(x86_64_pagetable* pt, uintptr_t va); + inline ptiter(const proc* p, uintptr_t va); // Return true once `ptiter` has iterated over all page table pages // (not including the top-level page table page) @@ -235,12 +235,12 @@ inline void vmiter::kfree_page() { *pep_ = 0; } -inline ptiter::ptiter(x86_64_pagetable* pt) +inline ptiter::ptiter(x86_64_pagetable* pt, uintptr_t va) : pt_(pt) { - go(0); + go(va); } -inline ptiter::ptiter(const proc* p) - : ptiter(p->pagetable_) { +inline ptiter::ptiter(const proc* p, uintptr_t va) + : ptiter(p->pagetable_, va) { } inline uintptr_t ptiter::va() const { return va_ & ~pageoffmask(level_); diff --git a/kernel.cc b/kernel.cc index 7febbe8c39ebb558d3ff4777a5a4d80bdb62c991..55c4390edb46524a99c760a3ed933aa3f3bf74eb 100644 --- a/kernel.cc +++ b/kernel.cc @@ -51,6 +51,7 @@ void kernel_start(const char* command) { // Only called at initial boot time. void boot_process_start(pid_t pid, const char* name) { + log_printf("\nBegin boot_process_start()\n"); // look up process image in initfs memfile_loader ld(memfile::initfs_lookup(name), kalloc_pagetable()); assert(ld.memfile_ && ld.pagetable_); @@ -67,6 +68,11 @@ void boot_process_start(pid_t pid, const char* name) { vmiter(p, MEMSIZE_VIRTUAL - PAGESIZE).map(stkpg, PTE_PWU); p->regs_->reg_rsp = MEMSIZE_VIRTUAL; + + // map console to initial process + int error_code = p->syscall_map_console(ktext2pa(console)); + assert(!error_code); + // add to process table (requires lock in case another CPU is already // running processes) { @@ -77,6 +83,7 @@ void boot_process_start(pid_t pid, const char* name) { // add to run queue cpus[pid % ncpu].enqueue(p); + log_printf("\nEnd boot_process_start()"); } @@ -234,7 +241,14 @@ uintptr_t proc::syscall(regstate* regs) { return bufcache::get().sync(drop); } case SYSCALL_MAP_CONSOLE: - return syscall_map_console(regs); + return syscall_map_console(regs->reg_rdi); + + case SYSCALL_EXIT: + set_pagetable(early_pagetable); + pstate_ = ps_exit; + yield_noreturn(); + assert(false); // will not be reached + default: // no such system call log_printf("%d: no such system call %u\n", id_, regs->reg_rax); @@ -245,8 +259,7 @@ uintptr_t proc::syscall(regstate* regs) { // Debugging Information #pragma GCC push_options #pragma GCC optimize("O0") -int proc::syscall_map_console(regstate* regs) { - uintptr_t addr = regs->reg_rdi; +int proc::syscall_map_console(uintptr_t addr) { if(addr % PAGESIZE || addr > VA_LOWMAX) { return E_INVAL; } @@ -260,11 +273,13 @@ int proc::syscall_map_console(regstate* regs) { // Handle fork system call. int proc::syscall_fork(regstate* regs) { + log_printf("\nBegin syscall_fork()"); pid_t pid = 0; proc *child = knew(); x86_64_pagetable* pt = kalloc_pagetable(); - assert(child); - + if(!child){ + return E_NOSYS; + } { spinlock_guard guard(ptable_lock); for(int i = 1; i < NPROC; ++i) { @@ -275,29 +290,60 @@ int proc::syscall_fork(regstate* regs) { } } } - assert(pid); + if(!pid) { + delete child; + return E_NOSYS; + } + if(!pt) { + { + spinlock_guard guard(ptable_lock); + ptable[pid] = nullptr; + } + delete child; + return E_NOSYS; + } child->init_user(pid, pt); // Copy user-accessible Memory + bool memError = false; for (vmiter parentIterator(this); parentIterator.low(); parentIterator.next()) { if (parentIterator.user()) { vmiter childIterator = vmiter(pt, parentIterator.va()); auto range = physical_ranges.find((uintptr_t) parentIterator.pa()); - if(range->type() == mem_console) { - childIterator.map(parentIterator.pa(), parentIterator.perm()); + bool isConsole = range->type() == mem_console; + if(isConsole) { + int result = childIterator.try_map(parentIterator.pa(), parentIterator.perm()); + if (result) { + memError = true; + break; + } } else { // Allocate a new frame for the child void *newFrame = kalloc(PAGESIZE); - assert(newFrame); - + if(!newFrame){ + memError = true; + break; + } // Copy the parent's page contents to the child's page memcpy(newFrame, parentIterator.kptr(), PAGESIZE); - // Map the child's virtual address to the new frame with the proper permission - childIterator.map(ka2pa(newFrame), parentIterator.perm()); + int result = childIterator.try_map(ka2pa(newFrame), parentIterator.perm()); + if (result) { + memError = true; + break; + } } } } + + if(memError) { + { + spinlock_guard guard(ptable_lock); + ptable[pid] = nullptr; + } + delete child; + return E_NOSYS; + } // Copy Registers memcpy(child->regs_, regs, sizeof(regstate)); @@ -308,6 +354,7 @@ int proc::syscall_fork(regstate* regs) { // Add to run queue cpus[pid % ncpu].enqueue(child); + log_printf("End syscall_fork()"); return pid; } diff --git a/kernel.hh b/kernel.hh index d7fdb3a80f43653543cd8b4ea72702901ed4aabf..116b6ca162a05dcf7ce8e45e71e5d1a3c44fe7a9 100644 --- a/kernel.hh +++ b/kernel.hh @@ -24,7 +24,7 @@ struct elf_program; // Process descriptor type struct __attribute__((aligned(4096))) proc { enum pstate_t { - ps_blank = 0, ps_runnable = PROC_RUNNABLE, ps_broken + ps_blank = 0, ps_runnable = PROC_RUNNABLE, ps_broken, ps_exit }; // These four members must come first: @@ -43,6 +43,7 @@ struct __attribute__((aligned(4096))) proc { proc(); + ~proc(); NO_COPY_OR_ASSIGN(proc); inline bool contains(uintptr_t addr) const; @@ -64,6 +65,7 @@ struct __attribute__((aligned(4096))) proc { inline bool resumable() const; int syscall_fork(regstate* regs); + int syscall_map_console(uintptr_t addr); uintptr_t syscall_read(regstate* reg); uintptr_t syscall_write(regstate* reg); @@ -74,7 +76,7 @@ struct __attribute__((aligned(4096))) proc { private: static int load_segment(const elf_program& ph, proc_loader& ld); - int syscall_map_console(regstate* reg); + }; #define NPROC 16 diff --git a/p-allocator.cc b/p-allocator.cc index cf4c029f058199070d3bdb1bed2d4f43b1dbbb8c..0ac2ee68a01732b2f5eecc2d942c14a8d250c048 100644 --- a/p-allocator.cc +++ b/p-allocator.cc @@ -13,8 +13,8 @@ uint8_t* stack_bottom; void process_main() { sys_kdisplay(KDISPLAY_MEMVIEWER); - //int error_code = sys_map_console(console); - //assert(!error_code); + // Console assignment: + /*console_printf(0x5000, "Hello Professor Foster,\n"); console_printf(0x5000, "We are in week four of the quarter and I'm learning a lot of\n"); console_printf(0x5000, "C++ programming in OS!\n"); diff --git a/p-testkalloc.cc b/p-testkalloc.cc index dd350c2600b034bc7c310f58e88b9101a2e14101..504947965ed627745a2ae4788e8ca8f39e5a3af2 100644 --- a/p-testkalloc.cc +++ b/p-testkalloc.cc @@ -7,5 +7,12 @@ void process_main() { // Note that panic() will prouce a page fault if there is no console // (https://github.com/CS161/chickadee/issues/14) + int pid = sys_fork(); + if(pid){ + sys_exit(0); + } + while (true) { + sys_yield(); + } panic("testkalloc not implemented!\n"); }