Commit 6ac63998 authored by benkma's avatar benkma

Lab 14 Finished

parent 5e25224b
......@@ -128,9 +128,9 @@ void* kalloc(size_t sz) {
asan_mark_memory(ka2pa(ptr), PAGESIZE, false);
// initialize to `int3`
memset(ptr, 0xCC, PAGESIZE);
log_printf("kalloc of order %d returning frame %d\n", pBlock->order, pBlock->frameNumber());
//log_printf("kalloc of order %d returning frame %d\n", pBlock->order, pBlock->frameNumber());
} else {
log_printf("kalloc of order %d failled\n", order);
//log_printf("kalloc of order %d failed\n", order);
}
return ptr;
}
......@@ -180,7 +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);
//log_printf("kfree of block starting at frame %d with order %d\n",pBlock->frameNumber(),pBlock->order);
auto irqs = mem_lock.lock();
......
......@@ -91,13 +91,6 @@ 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
......@@ -119,6 +112,8 @@ void cpustate::schedule(proc* yielding_from) {
// no need to skip `current_` if no other runnable procs
yielding_from = nullptr;
}
// run `current_`
set_pagetable(current_->pagetable_);
......
......@@ -13,11 +13,13 @@ proc::proc() {
}
proc::~proc() {
log_printf("proc::~proc\n");
//log_printf("proc::~proc\n");
if(!pagetable_){
return;
}
int pid = id_;
assert(!children_link_.is_linked());
assert(!exited_link_.is_linked());
{
spinlock_guard guard(ptable_lock);
ptable[pid] = nullptr;
......
......@@ -7,6 +7,10 @@
#include "k-vmiter.hh"
#include "obj/k-firstprocess.h"
// Debugging Information
#pragma GCC push_options
#pragma GCC optimize("O0")
// kernel.cc
//
// This is the kernel.
......@@ -18,11 +22,13 @@ std::atomic<unsigned long> ticks;
std::atomic<int> kdisplay;
static void tick();
static proc* create_init_process();
static void create_init_process();
static void boot_process_start(pid_t pid, const char* program_name);
void find_mapped_memory();
const pid_t INIT_PID = 1;
proc* initProc = nullptr;
spinlock children_lock; // global lock for manupulating children lists
// kernel_start(command)
......@@ -39,31 +45,33 @@ void kernel_start(const char* command) {
ptable[i] = nullptr;
}
// Start Init Process
proc* initProc = create_init_process();
// start first process
create_init_process();
boot_process_start(2, CHICKADEE_FIRST_PROCESS);
cpus[0].schedule(nullptr);
assert(false);
}
void init_process() {
// run the init process
while(true) {
initProc->syscall_waitpid(0,W_NOHANG);
initProc->yield();
}
assert(false);
}
proc* create_init_process() {
proc *initProc = knew<proc>();
void create_init_process() {
initProc = knew<proc>();
assert(initProc);
initProc->init_user(INIT_PID, early_pagetable);
initProc->init_kernel(INIT_PID, init_process);
initProc->ppid_ = INIT_PID;
{
spinlock_guard guard(ptable_lock);
assert(!ptable[INIT_PID]);
ptable[INIT_PID] = initProc;
}
return initProc;
cpus[INIT_PID % ncpu].enqueue(initProc);
}
// boot_process_start(pid, name)
......@@ -91,11 +99,6 @@ 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)
{
......@@ -104,6 +107,16 @@ void boot_process_start(pid_t pid, const char* name) {
ptable[pid] = p;
}
// add as child of init process
{
spinlock_guard guard(children_lock);
initProc->children_.push_back(p);
}
// map console to initial process
int error_code = p->syscall_map_console(ktext2pa(console));
assert(!error_code);
// add to run queue
cpus[pid % ncpu].enqueue(p);
log_printf("\nEnd boot_process_start()");
......@@ -270,12 +283,15 @@ uintptr_t proc::syscall(regstate* regs) {
return syscall_map_console(regs->reg_rdi);
case SYSCALL_EXIT:
syscall_exit(regs->reg_rdi);
syscall_exit((int32_t) regs->reg_rdi);
assert(false); // will not be reached
case SYSCALL_SLEEP:
return syscall_sleep(regs->reg_rdi);
case SYSCALL_WAITPID:
return syscall_waitpid((pid_t) regs->reg_rdi, (int) regs->reg_rsi);
default:
// no such system call
log_printf("%d: no such system call %u\n", id_, regs->reg_rax);
......@@ -283,21 +299,83 @@ uintptr_t proc::syscall(regstate* regs) {
}
}
// Debugging Information
#pragma GCC push_options
#pragma GCC optimize("O0")
int proc::syscall_exit(uint64_t exitCode) {
uintptr_t proc::syscall_waitpid(pid_t childPid, int options) {
proc *child = nullptr;
if(options & W_NOHANG) {
spinlock_guard guard1(ptable_lock);
spinlock_guard guard2(children_lock);
if(this->exited_.empty()) {
if(this->children_.empty()) {
return E_CHILD & 0xffffffff;
} else {
return E_AGAIN & 0xffffffff;
}
}
if(childPid) {
child = ptable[childPid];
// if there is no such child or it is not mine, return an error
if (!child || child->ppid_ != id_){
return E_CHILD & 0xffffffff;
}
if (child->pstate_ != ps_exit) {
return E_AGAIN & 0xffffffff;
}
exited_.erase(child);
} else {
child = this->exited_.pop_front();
}
} else {
while(true) {
{
spinlock_guard guard1(ptable_lock);
spinlock_guard guard2(children_lock);
if(this->exited_.empty() && this->children_.empty()){
return E_CHILD & 0xffffffff;
}
if (childPid) {
child = ptable[childPid];
if(!child || child->ppid_ != id_) {
return E_CHILD & 0xffffffff;
}
if(child->pstate_ == ps_exit){
exited_.erase(child);
break;
}
} else {
child = this->exited_.pop_front();
if (child) {
break;
}
}
}
yield();
}
}
assert(child);
uintptr_t result = ((int64_t) child->exitStatus_ << 32) | (child->id_ & 0xffffffff);
delete child;
return result;
}
int proc::syscall_exit(int32_t exitCode) {
this->exitStatus_ = exitCode;
set_pagetable(early_pagetable);
pstate_ = ps_exit;
{
spinlock_guard guard(ptable_lock);
for(int i = 1; i < NPROC; ++i) {
proc* otherProc = ptable[i];
if(otherProc && otherProc->ppid_ == id_) {
otherProc->ppid_ = INIT_PID;
}
{ // do child cleanup
spinlock_guard guard1(ptable_lock);
spinlock_guard guard2(children_lock);
proc* child;
while((child = this->children_.pop_front())){
child->ppid_ = INIT_PID;
initProc->children_.push_back(child);
}
while((child = this->exited_.pop_front())){
child->ppid_ = INIT_PID;
initProc->exited_.push_back(child);
}
ptable[ppid_]->children_.erase(this);
ptable[ppid_]->exited_.push_back(this);
}
yield_noreturn();
}
......@@ -320,13 +398,13 @@ int proc::syscall_map_console(uintptr_t addr) {
return 0;
}
#pragma GCC pop_options
// proc::syscall_fork(regs)
// Handle fork system call.
int proc::syscall_fork(regstate* regs) {
log_printf("\nBegin syscall_fork()");
//log_printf("\nBegin syscall_fork()");
pid_t pid = 0;
proc *child = knew<proc>();
if(!child){
......@@ -405,10 +483,15 @@ int proc::syscall_fork(regstate* regs) {
// Arranging for 0 to be returned to the child process
child->regs_->reg_rax = 0;
{
spinlock_guard guard(children_lock);
this->children_.push_back(child);
}
// Add to run queue
cpus[pid % ncpu].enqueue(child);
log_printf("End syscall_fork()");
//log_printf("End syscall_fork()");
return pid;
}
......@@ -600,9 +683,6 @@ void tick() {
* to one address, can we find the value when we read from the other address?
* Disable optimizations so we can step through this in a debugger.
*/
#pragma GCC push_options
#pragma GCC optimize ("O0")
void find_mapped_memory() {
long lowCanonical = 0x0;
long highCanonical = 0xffff800000000000;
......
......@@ -43,6 +43,15 @@ struct __attribute__((aligned(4096))) proc {
list_links runq_links_;
// manages children list
list_links children_link_;
list<proc, &proc::children_link_> children_;
// manage exit status and list
int32_t exitStatus_;
list_links exited_link_;
list<proc,&proc::exited_link_> exited_;
proc();
~proc();
......@@ -69,7 +78,8 @@ struct __attribute__((aligned(4096))) proc {
int syscall_fork(regstate* regs);
int syscall_map_console(uintptr_t addr);
int syscall_sleep(uint64_t msec);
int syscall_exit(uint64_t exitCode);
int syscall_exit(int32_t exitCode);
uintptr_t syscall_waitpid(pid_t childPid, int options);
uintptr_t syscall_read(regstate* reg);
uintptr_t syscall_write(regstate* reg);
......
......@@ -273,6 +273,7 @@ struct bitset_view {
#define SYSCALL_MAP_CONSOLE 128
#define SYSCALL_SLEEP 129
#define SYSCALL_GET_PPID 130
#define SYSCALL_WAITPID 131
// System call error return values
......
......@@ -148,7 +148,11 @@ inline pid_t sys_getppid() {
// waits for any child. If `options == W_NOHANG`, returns immediately.
inline pid_t sys_waitpid(pid_t pid, int* status = nullptr,
int options = 0) {
return E_NOSYS;
uintptr_t result = make_syscall(SYSCALL_WAITPID, (uintptr_t)pid, (uintptr_t)options);
if(status){
*status = (result >> 32) & 0xffffffff;
}
return result & 0xffffffff;
}
// sys_read(fd, buf, sz)
......
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