Commit 74a76c44 authored by 某某某's avatar 某某某
Browse files

静态优先级调度实现

No related merge requests found
Showing with 458 additions and 26 deletions
+458 -26
......@@ -13,6 +13,7 @@
#include "include/file.h"
#include "include/trap.h"
#include "include/vm.h"
#include "include/timer.h"
struct cpu cpus[NCPU];
......@@ -21,8 +22,14 @@ struct proc proc[NPROC];
struct proc *initproc;
struct queue_t pqueue_1;
struct queue_t pqueue_2;
struct queue_t pqueue_3;
struct queue_t pqueue_4;
int nextpid = 1;
struct spinlock pid_lock;
struct spinlock pqueue_lock;
extern void forkret(void);
extern void swtch(struct context*, struct context*);
......@@ -54,6 +61,7 @@ procinit(void)
struct proc *p;
initlock(&pid_lock, "nextpid");
initlock(&pqueue_lock, "pqueue");
for(p = proc; p < &proc[NPROC]; p++) {
initlock(&p->lock, "proc");
......@@ -140,10 +148,17 @@ allocproc(void)
found:
p->pid = allocpid();
p->ctime = ticks;
p->rutime = 0;
p->retime = 0;
p->sltime = 0;
// Allocate a trapframe page.
if((p->trapframe = (struct trapframe *)kalloc()) == NULL){
release(&p->lock);
p->ctime = 0;
return NULL;
}
......@@ -153,6 +168,7 @@ found:
(p->kpagetable = proc_kpagetable()) == NULL) {
freeproc(p);
release(&p->lock);
p->ctime = 0;
return NULL;
}
......@@ -191,6 +207,28 @@ freeproc(struct proc *p)
p->killed = 0;
p->xstate = 0;
p->state = UNUSED;
p->ctime = 0;
p->rutime = 0;
p->retime = 0;
p->sltime = 0;
switch (p->priority)
{ // 删除等待队列中的进程
case 1:
removeq(&pqueue_1, p);
break;
case 2:
removeq(&pqueue_2, p);
break;
case 3:
removeq(&pqueue_3, p);
break;
case 4:
removeq(&pqueue_4, p);
break;
default:;
}
}
// Create a user page table for a given process,
......@@ -284,6 +322,7 @@ uchar initcode[] = {
void
userinit(void)
{
pinit();
struct proc *p;
p = allocproc();
......@@ -304,6 +343,10 @@ userinit(void)
p->tmask = 0;
p->priority = 2;
enqueue(&pqueue_2, p);
release(&p->lock);
#ifdef DEBUG
printf("userinit\n");
......@@ -375,6 +418,26 @@ fork(void)
np->state = RUNNABLE;
np->priority = p->priority;
switch (np->priority)
{
case 1:
enqueue(&pqueue_1, np);
break;
case 2:
enqueue(&pqueue_2, np);
break;
case 3:
enqueue(&pqueue_3, np);
break;
case 4:
enqueue(&pqueue_4, np);
break;
default:
panic("priority should be 1-4\n");
}
release(&np->lock);
return pid;
......@@ -637,6 +700,56 @@ wait(uint64 addr)
}
}
int waitSH(int* rutime, int* retime, int* sltime)
{
struct proc *np;
int havekids, pid;
struct proc *p = myproc();
// hold p->lock for the whole time to avoid lost
// wakeups from a child's exit().
acquire(&p->lock);
for(;;){
// Scan through table looking for exited children.
havekids = 0;
for(np = proc; np < &proc[NPROC]; np++){
// this code uses np->parent without holding np->lock.
// acquiring the lock first would cause a deadlock,
// since np might be an ancestor, and we already hold p->lock.
if(np->parent == p){
// np->parent can't change between the check and the acquire()
// because only the parent changes it, and we're the parent.
acquire(&np->lock);
havekids = 1;
if(np->state == ZOMBIE){
// Found one.
pid = np->pid;
*rutime = np->rutime;
*retime = np->retime;
*sltime = np->sltime;
freeproc(np);
release(&np->lock);
release(&p->lock);
return pid;
}
release(&np->lock);
}
}
// No point waiting if we don't have any children.
if(!havekids || p->killed){
release(&p->lock);
return -1;
}
// Wait for a child to exit.
sleep(p, &p->lock); //DOC: wait-sleep
}
}
// Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up.
// Scheduler never returns. It loops, doing:
......@@ -652,38 +765,97 @@ scheduler(void)
extern pagetable_t kernel_pagetable;
c->proc = 0;
for(;;){
// Avoid deadlock by ensuring that devices can interrupt.
for (;;)
{
intr_on();
int found = 0;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&pqueue_lock);
p = headq(&pqueue_1);
if (p == 0)
{
p = headq(&pqueue_2);
}
if (p == 0)
{
p = headq(&pqueue_3);
}
if (p == 0)
{
p = headq(&pqueue_4);
}
release(&pqueue_lock);
if (p) //添加last_proc是否处于RUNABLE状态
{ // 若找得到进程,则运行它,否则暂时释放ptable锁,开启中断,然后再次获取ptable锁,继续从第一优先级队列开始寻找
//printf("%d is being scheduled on cpu: %d, its priority is %d.\n", p->pid, cpuid(), p->priority);
acquire(&p->lock);
if(p->state == RUNNABLE) {
// Switch to chosen process. It is the process's job
// to release its lock and then reacquire it
// before jumping back to us.
// printf("[scheduler]found runnable proc with pid: %d\n", p->pid);
p->state = RUNNING;
c->proc = p;
w_satp(MAKE_SATP(p->kpagetable));
sfence_vma();
swtch(&c->context, &p->context);
w_satp(MAKE_SATP(kernel_pagetable));
sfence_vma();
// Process is done running for now.
// It should have changed its p->state before coming back.
c->proc = 0;
found = 1;
if(p->state != RUNNABLE) {
release(&p->lock);
continue;
}
//printf("11111\n");
p->state = RUNNING;
c->proc = p;
w_satp(MAKE_SATP(p->kpagetable));
//printf("22222\n");
sfence_vma();
//printf("33333\n");
swtch(&c->context, &p->context);
//printf("44444\n");
w_satp(MAKE_SATP(kernel_pagetable));
//printf("55555\n");
sfence_vma();
//printf("66666\n");
// c->proc = p;
// switchuvm(p);
// p->state = RUNNING;
// swtch(&(c->context), &p->context);
// switchkvm();
// Process is done running for now.
// It should have changed its p->state before coming back.
c->proc = 0;
release(&p->lock);
}
if(found == 0) {
intr_on();
asm volatile("wfi");
}
}
// c->proc = 0;
// for(;;){
// // Avoid deadlock by ensuring that devices can interrupt.
// intr_on();
// int found = 0;
// for(p = proc; p < &proc[NPROC]; p++) {
// acquire(&p->lock);
// if(p->state == RUNNABLE) {
// // Switch to chosen process. It is the process's job
// // to release its lock and then reacquire it
// // before jumping back to us.
// // printf("[scheduler]found runnable proc with pid: %d\n", p->pid);
// p->state = RUNNING;
// c->proc = p;
// w_satp(MAKE_SATP(p->kpagetable));
// sfence_vma();
// swtch(&c->context, &p->context);
// w_satp(MAKE_SATP(kernel_pagetable));
// sfence_vma();
// // Process is done running for now.
// // It should have changed its p->state before coming back.
// c->proc = 0;
// found = 1;
// }
// release(&p->lock);
// }
// if(found == 0) {
// intr_on();
// asm volatile("wfi");
// }
// }
}
// Switch to scheduler. Must hold only p->lock
......@@ -910,3 +1082,170 @@ procnum(void)
return num;
}
void
pqueue_init(struct queue_t *queue, int priority)
{
queue->priority=priority; //为方便输出debug,加入变量priority
queue->size=0;
for(int i=0; i<NPROC; i++) //初始时指针为0
queue->proc[i]=0;
}
void
pinit(void)
{
//initlock(&ptable.lock, "ptable");
pqueue_init(&pqueue_1,1);
pqueue_init(&pqueue_2,2);
pqueue_init(&pqueue_3,3);
pqueue_init(&pqueue_4,4);
}
void
enqueue(struct queue_t *q, struct proc *p)
{
//printf("proc %d enqueueing %d.\n", p->pid, q->priority);
int pos;
pos = q->size - 1;
while(pos >= 0 && q->proc[pos]->ctime > p->ctime){ //从后往前扫描
q->proc[pos+1] = q->proc[pos]; //如果目前进程比新插入进程到达晚,就把它向后挪一个位置
pos--;
}
// 目前pos指向的进程比插入的进程到达时间早或相同。
q->proc[pos+1] = p;
q->size ++;
}
void
removeq(struct queue_t* q, struct proc *p)
{
//printf("removing %d from q: %d\n",p->pid, q->priority);
int pos;
int found = 0;
pos = 0;
while(pos < q->size){
if(q->proc[pos]==p){ //从前往后,找到该进程
found=1;
break;
}
else{
pos++;
}
}
if(found){ //若找到,此时pos指向要删除的进程
while(pos < q->size-1){ //从 pos 到倒数第二个进程位置
q->proc[pos] = q->proc[pos+1]; //将所有进程往前挪一个位置
pos++;
}
q->proc[q->size-1] = 0;
q->size --;
}
}
struct proc*
headq(struct queue_t* q)
{
struct proc* p = 0;
int pos;
for(pos = 0; pos < q->size; pos++){
if(q->proc[pos]->state == RUNNABLE){ //找到第一个RUNNABLE进程,注意等待队列是从到达时间小到大排序的
p = q->proc[pos];
break;
}
}
return p;
}
void
update()
{
struct proc *p;
for (p = proc; p < &proc[NPROC]; p++)
{
acquire(&p->lock);
switch (p->state)
{ // 遍历整个表,判断进程状态
case RUNNING: // 运行中
p->rutime++; // 则运行时间增加一个时间片
break;
case SLEEPING: // 休眠中
p->sltime++; // 休眠时间增加一个时间片
break;
case RUNNABLE: // 等待中
p->retime++; // 等待时间增加一个时间片
break;
default:; // default,有ZOMBIE\EMBRYO\UNUSED,这些状态我们不关心
}
release(&p->lock); // 释放锁
}
}
int set_priority(int pid, int priority)
{
struct proc *p = 0;
for (p = proc; p < &proc[NPROC]; p++)
{
acquire(&p->lock);
if (p->pid == pid)
{
if (p->priority != priority)
{
switch (p->priority)
{
case 1:
removeq(&pqueue_1, p);
break;
case 2:
removeq(&pqueue_2, p);
break;
case 3:
removeq(&pqueue_3, p);
break;
case 4:
removeq(&pqueue_4, p);
break;
default:;
}
switch (priority)
{
case 1:
enqueue(&pqueue_1, p);
break;
case 2:
enqueue(&pqueue_2, p);
break;
case 3:
enqueue(&pqueue_3, p);
break;
case 4:
enqueue(&pqueue_4, p);
break;
default:;
}
}
p->priority = priority;
release(&p->lock);
return 0;
}
release(&p->lock);
}
return -1;
}
......@@ -32,8 +32,16 @@ set_next_timeout() {
}
void timer_tick() {
// if(cpuid() == 0){ //如果是cpu0收到了这个时钟中断,才将tick增加1;这样对于不同的cpu,时钟都是保持同步的,所有的cpu都会共用这个tick变量。
// acquire(&tickslock);
// ticks++;
// wakeup(&ticks);
// release(&tickslock);
// }
acquire(&tickslock);
ticks++;
update();
wakeup(&ticks);
release(&tickslock);
set_next_timeout();
......
#include "kernel/include/types.h"
#include "kernel/include/stat.h"
#include "xv6-user/user.h"
int main(int argc, char* argv[])
{
if(argc!=2){
printf("usage: priority_sta <fork number> \n");
exit(0);
}
int forknumber=atoi(argv[1]);
int status;
for(int i=0;i<forknumber;i++)
{
printf("fork %d\n", i);
status=fork();
if(status)
{
printf("%d start to set priority\n",status);
set_priority(status, (i+3)%4+1); //在父进程中,将每个子进程的优先级设置为i%4+1.
printf("%d set priority done\n", status);
}
if(status==0){
for(int count=0;count<40; count++){
printf(" ");
for(int k=0;k<1000000;k++){
int result=0;
for( int j=0; j<5000; j++){
result+=j*j;
result-=j*j;
result= result/j;
result=result*j;
result = result+result/j;
}
}
}
exit(0);
}
}
int rutime;
int retime;
int sltime;
int pid;
int sum=0;
while((pid = waitsch(&rutime,&retime,&sltime))!=-1){
sum+= rutime+retime+sltime;
}
printf(" average turn-around time of %d process is %d\n", forknumber, sum/forknumber);
exit(0);
// printf("Change priority test\n");
// int parent_pid = getpid();
// printf("Parent pid: %d\n", parent_pid);
// int pid = fork();
// if(pid == 0)
// {
// set_priority(getpid(), 4);
// for(int i = 0; i < 100; i++)
// {
// printf("priority: %d\n", 88);
// }
// }
// else
// {
// for(int i = 0; i < 100; i++)
// {
// printf("priority: %d\n", 10);
// }
// wait(0);
// }
// exit(0);
}
\ No newline at end of file
Supports Markdown
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