-
Notifications
You must be signed in to change notification settings - Fork 1
Project 02. Light weight Process (milestone3)
Yooniversal edited this page Jul 26, 2022
·
1 revision
void
exit(void)
{
...
acquire(&ptable.lock);
// clear all threads of current process
if(curproc->is_thread == 0) {
for(p=ptable.proc; p<&ptable.proc[NPROC]; ++p) {
if(!p || p->is_thread == 0 || p->pid != curproc->pid)
continue;
deallocuvm(p->pgdir, p->stack + 2*PGSIZE, p->stack);
kfree(p->kstack);
p->kstack = 0;
p->sz = 0;
p->state = UNUSED;
p->pid = 0;
p->parent = 0;
p->killed = 0;
p->name[0] = 0;
p->tickets = 0;
p->lev = 0;
p->in_mlfq = 0;
stack_st[p->stack_id] = 0;
p->is_thread = 0;
p->tid = 0;
p->master = 0;
p->stack = 0;
p->stack_id = 0;
p->used_all_time = 0;
p->ret_val = 0;
--thd_cnt;
p->master->tcnt--;
}
}
// Parent might be sleeping in wait().
wakeup1(curproc->parent);
// Pass abandoned children to init.
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->parent == curproc){
p->parent = initproc;
if(p->state == ZOMBIE)
wakeup1(initproc);
}
}
// Jump into the scheduler, never to return.
curproc->state = ZOMBIE;
sched();
panic("zombie exit");
}
- If a process which isn't a thread calls
exit()
, then clean up all threads of the process
Otherwise, do the same mechanism of originalexit()
-
fork()
makes only master process but not thread
Thread is created bythread_create()
which has simliar way withfork()
but makes the thread having same address and pid - Because of the reason above, code of
fork()
is not modified
int
exec(char *path, char **argv)
{
...
// Initalize all threads of process
// Threads of current process must be cleaned up
acquire(&ptable.lock);
for(p=ptable.proc; p<&ptable.proc[NPROC]; p++) {
if(!p || p->is_thread == 0 || p->pid != curproc->pid)
continue;
release(&ptable.lock);
for(fd=0; fd<NOFILE; ++fd)
if(p->ofile[fd]) {
fileclose(p->ofile[fd]);
p->ofile[fd] = 0;
}
begin_op();
iput(p->cwd);
end_op();
p->cwd = 0;
acquire(&ptable.lock);
deallocuvm(p->pgdir, p->stack + 2*PGSIZE, p->stack);
kfree(p->kstack);
p->kstack = 0;
p->sz = 0;
p->state = UNUSED;
p->pid = 0;
p->parent = 0;
p->killed = 0;
p->name[0] = 0;
p->tid = 0;
p->master = 0;
p->stack = 0;
p->stack_id = 0;
p->ret_val = 0;
}
release(&ptable.lock);
// Commit to the user image.
oldpgdir = curproc->pgdir;
curproc->pgdir = pgdir;
curproc->sz = sz;
curproc->tf->eip = elf.entry; // main
curproc->tf->esp = sp;
switchuvm(curproc);
freevm(oldpgdir);
return 0;
bad:
...
}
- For using new process, clean up all threads of current process And clean up current process, too
int
growproc(int n)
{
uint sz;
struct proc *curproc = myproc();
// Make multiple threads do not influence each other by locking
acquire(&ptable.lock);
sz = curproc->sz;
if(n > 0){
if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1;
} else if(n < 0){
if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1;
}
release(&ptable.lock);
curproc->sz = sz;
switchuvm(curproc);
return 0;
}
- To prevent working
sbrk()
simultaneously from multiple threads, use lock at start point - Because
sys_sbrk(void)
usegrowproc()
, added some codes ingrowproc()
- This function kills the process who has same pid with parameter
pid
- In
thread_create()
, thread has same pid with master process
So ifkill(int pid)
is called, then all threads of master process havingpid
must be killed - No addtional code in here
- If a thread calls
sleep()
, thensleep()
changes state of the thread toSLEEPING
But It doesn't influence to master process - It works enough with original code of
sleep()
, so no additional code in here
// in proc.c
void
sched(void)
{
...
intena = mycpu()->intena;
if(p->master->used_all_time) {
p->master->used_all_time = 0;
swtch(&p->context, mycpu()->scheduler);
} else {
if(p->is_thread) {
np = select_thread(p->master);
if(!np)
swtch(&(myproc()->context), mycpu()->scheduler);
else {
// run next thread but not go though scheduler
// switch directly
mycpu()->proc = np;
switchuvm(np);
np->state = RUNNING;
swtch(&(myproc()->context), np->context);
}
} else {
swtch(&(myproc()->context), mycpu()->scheduler);
}
}
mycpu()->intena = intena;
}
// in newfunc.c
int
set_cpu_share(int share)
{
...
// Initialize process
p->tickets = cur_t;
p->lev = 3;
p->used_time = 0;
p->in_mlfq = 0;
p->pass = get_min_pass();
p->stride = TOTAL_TICKETS / cur_t;
enqueue_to_sq(p);
mlfq.tickets = mlfq_sum;
sq.tickets = sq_sum;
mlfq.cnt--;
// Initialize threads of current process
struct proc *thd;
for(thd=ptable.proc; thd<&ptable.proc[NPROC]; ++thd) {
if(!thd || thd->is_thread == 0 || thd->pid != p->pid)
continue;
thd->lev = 3;
thd->in_mlfq = 0;
thd->tickets = p->tickets;
}
release(&ptable.lock);
return 0;
}
- In
scheduler()
, it selects a process by whether MLFQ or Stride scheduling corresponding to which it belongs to
It doesn't pick thread inscheduler()
- After master process is selected, work with threads belongs to master process until it meets the time criteria
Switching next thread doesn't go throughscheduler()
but do directly insched()
by callingswtch()
- Because time quantum of thread is 1 ticks, it calls
yield()
whenever reaches intrap()
after running
And updateused_time
andpass
of master process - When master process calls
set_cpu_share()
, all threads of master process will be managed by stride scheduling
- Passed racingtest, basictest, jointest1, jointest2
- Failed to pass stresstest
- Passed racingtest, basictest, jointest1, jointest2
- Failed to pass stresstest