제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