Priority Arrays

advertisement
제39강 : Scheduling
Ch 4 Scheduling
Linux supports realtime jobs
Soft-Realtime
For faster response, preempt task in kernel mode
1
Priority
• Priority changes dynamically
– priority++  CPU preempted for I/O?
(I/O bound)
– priority --  CPU preempted while computing? (CPU-bound)
• Base priority (initial value)
– Standard priority
– Real-time priority
• Who runs next?  Runnable (ready) process with
remaining timeslice
AND
highest
priority
2
Timeslice
• Preempted?  preempted task can use remaining timeslice later
Task is runnable(ready) iff timeslice remain
eg Task is given 100 ms. timeslice.
After 20 m., CPU preempted.
Use 80 ms. later
• A task used all the timeslice?
this task cannot run on CPU
wait until all other tasks exhausted their timeslices
recalculate timeslice for this task based on priority
Lower priority or
Higher priority or
Less interactive
More interactive
Minimum
10ms
Default
100ms
Maximum
200ms
3
Ready Queue
per each CPU
list of all runnable tasks
Ready
Queue
Hi-Priority
Queue
High priority tasks
Low-Priority
Queue
Low priority tasks
Priority 1 Queue
Priority 1 tasks
Priority 2 Queue
Priority 3 Queue
Priority 3 tasks
Priority 4 Queue
Priority 5 Queue
Priority 5 tasks
4
Ready Queue
per each CPU
binary
2
0
0
1
head
pointer
..
.
132
1
bitmap[BITMAP_SIZE]
list of priority 2 tasks
2
..
.
132
list of priority 132 tasks
queue[MAX_PRIO]
struct prio_array {
int nr_active;
unsigned long bitmap[BITMAP_SIZE];
struct list_head queue[MAX_PRIO];
};
/* number of tasks */
/* priority bitmap */
/* priority queues */
5
Priority Arrays Diagram
(per each CPU)
prio_array
bit 2
priority 2
(1)
..
.
scan
priority
132
bit 132
list of runnable tasks
2
(2) traverse
task list
list of runnable tasks
priority 132
bitmap[BITMAP_SIZE]
queue[MAX_PRIO]
6
Two Priority Arrays per CPU
Expired array
bit 2
priority 2
list of runnable
tasksexpired)
(timeslice
2
..
.
bit 2
bit 132
priority 2 132
2
priority 132
Each
CPU
(3)
Active array
timeslice
(timeslice remain)
expired?
list of runnable tasks
..
.
list of runnable tasks
132
bit 132
priority 132
bitmap[BITMAP_SIZE]
list of runnable tasks
queue[MAX_PRIO]
7
Two Priority Arrays per CPU
Expired array
bit 2
priority 2
2
(3)
list of runnable
tasksexpired)
(timeslice
timeslice
..
expired?
.
Each
CPU
Active array
(timeslice remain)
list of runnable tasks
..
(4)
.
bit 132
priority
132 array becomes empty?
Active
i.e. all tasks used timeslice
all tasks moved to Expired array
then
inter-change 2 priority arrays
(new timeslicesqueue[MAX_PRIO]
are given to all tasks)
bitmap[BITMAP_SIZE]
132
8
Recalculating timeslice
1. task’s timeslice reaches 0
2. move it to the expired array.
3. recalculated its timeslice
4. All tasks have moved to expired array?
 Switch active & expired arrays.
struct prio_arry array = rq->active;
if (! array->nr_active) {
rq->active = rq->expired;
rq->expired = array;
}
/* array is temporary; get active prio_array */
/* there is no active tasks here */
/* switch between active and expired */
9
Two Priority Arrays per CPU
Expired array
(timeslice expired)
Ready
Queue
Each
CPU
Active array
(timeslice remain)
Ready
Queue
10
Data Structure for Each CPU Scheduling
struct
runqueue {
spinlock_t
lock; /* obtain locks in ascending address – deadlock */
unsigned long nr_running, nr_switches, expired_timestamp, nr_uninterruptible;
task_struct
*curr;
/* currently running task */
struct mm_struct
*prev_mm;
prio_array
*active, *expired;
/* priority arrays */
int
prev_cpu_load[NR_CPUS];
task_t
*migration_thread;
struct list_head
migration_queue;
atomic_t
nr_iowait;
};
runqueue1
active priority arrays
expired priority arrays
CPU2 runqueue2
active priority arrays
expired priority arrays
CPU3 runqueue3
active priority arrays
expired priority arrays
CPU1
Expired
Active
..
.. .
.
Each
CPU
11
bitmap
queue
Scheduling Algorithm
• O(1) scheduler schedule()
constant-time scheduling regardless of # of processes
task_t *prev, *next;
prio_array_t *array;
struct list_head *queue;
int idx;
array = rq->active;
idx = sched_find_first_bit(array->bitmap);
CPU1
runqueue1
active priority arrays
expired priority arrays
CPU2
runqueue2
active priority arrays
expired priority arrays
/* given CPU, get active prio_array */
/* find highest priority level */
queue = array->queue + idx;
/* find highest priority queue */
next = list_entry (queue->next, task_t, run_list); /* get the next runnable task */
12
Others
• The load balancer
– If runqueues are unbalanced in a multiprocessor
– move processes from busier runqueue
to current runqueue
• Real-time
– Soft real-time behavior -- no deadline guarantee
– One can set/get scheduling policy
• SCHED_FIFO
no timeslice (non-preemptible)
• SCHED_RR
realtime round-robin
• (SCHED_OTHER is non-realtime normal scheduling)
13
Kernel mode task preemption
&
Critical Section problem
14
Mutual Exclusion
Process B
Process A
Read x into register (11)
Operation with ALU register (12)
Write back to storage box (12)
Shared
Memory
x
Allow only one process
to enter critical section
at a time (exclude other process)
Read x into register (12)
Operation with ALU register (13)
Write back to storage box (13)
correct result
15
---Functions in kernel
sh
mail
user
proc
---Stack frame for function
return address
parameter
local variables
user
Kernel Stack
read( )
Global Variables
proc
send( )
Lions kernel
treated entire kernel as one critical section (excessive)
Linux kernel
can preempt if not accessing shared variable
shared variable access = critical section (lock/unlock)
16
When can you preempt CPU from a task
running in kernel mode?
Critical Section
Two Variables
Lock
Unlock
1. preempt_count (in thread_info) per thread
•
number of locks held by this thread = ZERO?
 “thread is not inside critical section”
 one can preempt this kernel mode thread
2. need_resched flag
•
If set  “higher priority process is waiting to run”
preempt_count=0 AND need_resched
means
”this thread can be preempted” AND ”other thread is waiting”
17
When does kernel preemption occurs?
1. When kernel becomes preemptible again
–
That is, after unlock(), test
–
–
(preempt_count=0) AND (need_resched is set)
If TRUE, call schedule()
2. When interrupt handler returns to kernel, test
–
–
(preempt_count=0) AND (need_resched is set)
If TRUE, call schedule()
3. Kernel explicitly calls schedule()
–
–
when this thread is returning to user mode
when this thread is going to sleep
18
preemption points
call
I.H. Interrupt Handler
C.S. Critical Section
schedule()
I. H.
sleep
(1) return
from
interrupt
(2) going
to
sleep
C. S.
(3) exit
Critical
Section
(unlock)
kernel mode
I. H.
(4) sys call
is done
(1) return
from
interrupt
user mode
19
schedule()
• schedule() selects new process to run (like swtch())
it calls context_swtch()
(like savu())
• context_switch() calls
– virtual memory mapping:
– processor state switching:
switch_mm()
switch_to()
(save and restore stack information & CPU registers)
• Similar to UNIX’s swtch() savu() retu(), …
20
Download