Commit 6610fd13 authored by benkma's avatar benkma

Lab 17 completed

parent d39c7d8e
......@@ -142,11 +142,15 @@ void cpustate::init_idle_task() {
bool cpustate::hasUserProcess() {
spinlock_guard guard(runq_lock_);
while(this->runq_.front() != nullptr) {
if(runq_.front()->pagetable_ != early_pagetable){
return true;
}
this->runq_.pop_front();
}
return false;
if(current_->isUserProcess()){
return true;
}
proc *next = runq_.front();
while(next) {
if(next->isUserProcess()) {
return true;
}
next = runq_.next(next);
}
return false;
}
......@@ -175,7 +175,7 @@ inline void list<T, member>::erase(T* x) {
template <typename T, list_links (T::* member)>
inline void list<T, member>::insert(T* position, T* x) {
(x->*member).insert_before(position ? &head_ : &(position->*member));
(x->*member).insert_before(!position ? &head_ : &(position->*member));
}
template <typename T, list_links (T::* member)>
......
......@@ -29,7 +29,8 @@ void find_mapped_memory();
const pid_t INIT_PID = 1;
proc* initProc = nullptr;
spinlock children_lock; // global lock for manupulating children lists
unsigned long yieldCount = 0;
list<proc, &proc::sleep_link_> sleepers;
// kernel_start(command)
// Initialize the hardware and processes and start running. The `command`
......@@ -57,8 +58,8 @@ void init_process() {
while(true) {
initProc->syscall_waitpid(0,W_NOHANG);
initProc->yield();
haltIfNoUserProcesses();
}
haltIfNoUserProcesses();
assert(false);
}
......@@ -76,17 +77,15 @@ void create_init_process() {
}
void haltIfNoUserProcesses() {
int index = 0;
bool containsHaltProcess = false;
while(index < 16) {
if(cpus[index].hasUserProcess()){
containsHaltProcess = true;
}
index++;
}
if(!containsHaltProcess) {
process_halt();
if (!sleepers.empty()) {
return;
}
for(int i =0; i< ncpu; ++i) {
if(cpus[i].hasUserProcess()){
return;
}
}
process_halt();
}
// boot_process_start(pid, name)
......@@ -363,8 +362,10 @@ uintptr_t proc::syscall_waitpid(pid_t childPid, int options) {
break;
}
}
this->pstate_ = proc::ps_blocked;
}
yield();
++yieldCount;
}
}
assert(child);
......@@ -374,12 +375,12 @@ uintptr_t proc::syscall_waitpid(pid_t childPid, int options) {
}
int proc::syscall_exit(int32_t exitCode) {
this->exitStatus_ = exitCode;
set_pagetable(early_pagetable);
pstate_ = ps_exit;
{ // do child cleanup
spinlock_guard guard1(ptable_lock);
spinlock_guard guard2(children_lock);
this->exitStatus_ = exitCode;
set_pagetable(early_pagetable);
pstate_ = ps_exit;
proc* child;
while((child = this->children_.pop_front())){
child->ppid_ = INIT_PID;
......@@ -389,20 +390,39 @@ int proc::syscall_exit(int32_t exitCode) {
child->ppid_ = INIT_PID;
initProc->exited_.push_back(child);
}
ptable[ppid_]->children_.erase(this);
ptable[ppid_]->exited_.push_back(this);
proc *parent = ptable[ppid_];
parent->children_.erase(this);
parent->exited_.push_back(this);
if(parent->pstate_ == proc::ps_blocked) {
if(parent->sleep_link_.is_linked()) {
sleepers.erase(parent);
}
parent->pstate_ = proc::ps_runnable;
cpus[parent->id_ % ncpu].enqueue(parent);
}
}
yield_noreturn();
}
int proc::syscall_sleep(uint64_t msec){
unsigned long now = ticks;
unsigned long end = round_up(now,10) + msec;
while (now < end) {
if (!this->exited_.empty()) {
return E_INTR;
}
wakeUpTime = round_up(now,10) + msec;
while (now < wakeUpTime) {
{
spinlock_guard guard(children_lock);
if (!exited_.empty()) {
return E_INTR;
}
this->pstate_ = proc::ps_blocked;
proc *next = sleepers.front();
while(next && next->wakeUpTime < this->wakeUpTime) {
next = sleepers.next(next);
}
assert(!this->sleep_link_.is_linked());
sleepers.insert(next,this);
}
yield();
++yieldCount;
now = ticks;
}
return 0;
......@@ -694,6 +714,19 @@ void tick() {
if (kdisplay.load(std::memory_order_relaxed) == KDISPLAY_MEMVIEWER) {
memshow();
}
// Wake any sleepers if it is times
{
spinlock_guard guard(children_lock);
proc *sleeper = sleepers.front();
while (sleeper && sleeper->wakeUpTime <= ticks) {
proc *next = sleepers.next(sleeper);
sleepers.erase(sleeper);
sleeper->pstate_ = proc::ps_runnable;
cpus[sleeper->id_ % ncpu].enqueue(sleeper);
sleeper = next;
}
}
}
/* The comment at init_boot_pagetable in bootentry.s says that 1 GB of RAM
......
......@@ -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_exit
ps_blank = 0, ps_runnable = PROC_RUNNABLE, ps_broken, ps_exit, ps_blocked
};
// These four members must come first:
......@@ -52,6 +52,10 @@ struct __attribute__((aligned(4096))) proc {
list_links exited_link_;
list<proc,&proc::exited_link_> exited_;
// manage sleepers list and wake time
list_links sleep_link_;
unsigned long wakeUpTime = 0;
proc();
~proc();
......
......@@ -40,7 +40,9 @@ void process_main() {
} else {
sys_exit(0);
}
while (sys_waitpid(0, nullptr, W_NOHANG)>0){
sys_msleep(50);
}
// Tests that implicate `exit` behavior
assert(original != 1);
......
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