Commit eddbc88e authored by benkma's avatar benkma

Finished Lab 11

parent 1233725a
......@@ -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() {
......
......@@ -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
......
......@@ -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));
......
......@@ -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`
......
......@@ -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_);
......
......@@ -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<proc>();
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;
}
......
......@@ -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
......
......@@ -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");
......
......@@ -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");
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment