Skip to content
GitLab
Explore
Projects
Groups
Topics
Snippets
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
educg-net-28668-2608132
OSKernel2024-JTing-107
Commits
74a76c44
Commit
74a76c44
authored
2 months ago
by
某某某
Browse files
Options
Download
Patches
Plain Diff
静态优先级调度实现
parent
8d7a1aa2
main
develop
fb
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
kernel/proc.c
+365
-26
kernel/proc.c
kernel/timer.c
+8
-0
kernel/timer.c
xv6-user/change_priority.c
+85
-0
xv6-user/change_priority.c
with
458 additions
and
26 deletions
+458
-26
kernel/proc.c
+
365
−
26
View file @
74a76c44
...
...
@@ -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
;
}
This diff is collapsed.
Click to expand it.
kernel/timer.c
+
8
−
0
View file @
74a76c44
...
...
@@ -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
();
...
...
This diff is collapsed.
Click to expand it.
xv6-user/change_priority.c
0 → 100644
+
85
−
0
View file @
74a76c44
#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
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Topics
Snippets