Successfully reported this slideshow.

AOS Lab 6: Scheduling

656 views

Published on

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

AOS Lab 6: Scheduling

  1. 1. Lab 6: Scheduling Advanced Operating Systems Zubair Nabi zubair.nabi@itu.edu.pk March 6, 2013
  2. 2. Introduction 1 An operating system runs more processes than it has processors
  3. 3. Introduction 1 An operating system runs more processes than it has processors 2 Needs some plan to time share the processors between the processes
  4. 4. Introduction 1 An operating system runs more processes than it has processors 2 Needs some plan to time share the processors between the processes 3 A common approach is to provide each process with a virtual processor – An illusion that it has exclusive access to the processor
  5. 5. Introduction 1 An operating system runs more processes than it has processors 2 Needs some plan to time share the processors between the processes 3 A common approach is to provide each process with a virtual processor – An illusion that it has exclusive access to the processor 4 It is then the job of the OS to multiplex these multiple virtual processors on the underlying physical processors
  6. 6. Scheduling triggers 1 A process does I/O, put it to sleep, and schedule another process
  7. 7. Scheduling triggers 1 A process does I/O, put it to sleep, and schedule another process 2 Use timer interrupts to stop running on a processor after a fixed time quantum (100 msec)
  8. 8. Context switching • Used to achieve multiplexing
  9. 9. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed
  10. 10. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 Process’s kernel thread to the current CPU’s scheduler thread
  11. 11. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 2 Process’s kernel thread to the current CPU’s scheduler thread Scheduler’s thread to a process’s kernel thread
  12. 12. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 2 Process’s kernel thread to the current CPU’s scheduler thread Scheduler’s thread to a process’s kernel thread • No direct switching from one user-space process to another
  13. 13. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 2 Process’s kernel thread to the current CPU’s scheduler thread Scheduler’s thread to a process’s kernel thread • No direct switching from one user-space process to another • Each process has its own kernel stack and register set (its context)
  14. 14. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 2 Process’s kernel thread to the current CPU’s scheduler thread Scheduler’s thread to a process’s kernel thread • No direct switching from one user-space process to another • Each process has its own kernel stack and register set (its context) • Each CPU has its own scheduler thread
  15. 15. Context switching • Used to achieve multiplexing • Internally two low-level context switches are performed 1 2 Process’s kernel thread to the current CPU’s scheduler thread Scheduler’s thread to a process’s kernel thread • No direct switching from one user-space process to another • Each process has its own kernel stack and register set (its context) • Each CPU has its own scheduler thread • Context switch involves saving the old thread’s CPU registers and restoring previously-saved registers of the new thread (enabled by swtch)
  16. 16. swtch • Saves and restores contexts
  17. 17. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new
  18. 18. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter
  19. 19. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context
  20. 20. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context • Flow in case of an interrupt:
  21. 21. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context • Flow in case of an interrupt: 1 trap handles the interrupt and the calls yield
  22. 22. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context • Flow in case of an interrupt: 1 trap handles the interrupt and the calls yield 2 yield makes a call to sched
  23. 23. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context • Flow in case of an interrupt: 1 trap handles the interrupt and the calls yield 2 yield makes a call to sched 3 sched invokes swtch(&proc->context, cpu->scheduler)
  24. 24. swtch • Saves and restores contexts • Takes two arguments: struct context **old and struct context *new • Replaces the former with the latter • Each time a process has to give up the CPU, its kernel thread invokes swtch to save its own context and switch to the scheduler context • Flow in case of an interrupt: 1 trap handles the interrupt and the calls yield 2 yield makes a call to sched 3 sched invokes swtch(&proc->context, cpu->scheduler) 4 Control returns to the scheduler thread
  25. 25. Scheduling mechanism • Each process that wants to give up the processor:
  26. 26. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock)
  27. 27. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock) 2 Releases any other locks that it is holding
  28. 28. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock) 2 3 Releases any other locks that it is holding Updates proc->state (its own state)
  29. 29. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock) Releases any other locks that it is holding Updates proc->state (its own state) 4 Calls sched 2 3
  30. 30. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock) Releases any other locks that it is holding Updates proc->state (its own state) 4 Calls sched 2 3 • Mechanism followed by yield, and sleep and exit
  31. 31. Scheduling mechanism • Each process that wants to give up the processor: 1 Acquires ptable.lock (process table lock) Releases any other locks that it is holding Updates proc->state (its own state) 4 Calls sched 2 3 • Mechanism followed by yield, and sleep and exit • sched ensures that these steps are followed
  32. 32. sched 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void sched (void) { int intena ; if(! holding (& ptable .lock )) panic (" sched ptable .lock"); if(cpu−>ncli != 1) panic (" sched locks "); if(proc−>state == RUNNING ) panic (" sched running "); if( readeflags ()& FL_IF ) panic (" sched interruptible "); intena = cpu−>intena ; swtch (& proc−>context , cpu−>scheduler ); cpu−>intena = intena ; }
  33. 33. yield 1 2 3 4 5 6 void yield (void) { acquire (& ptable .lock ); proc−>state = RUNNABLE ; sched (); release (& ptable .lock ); }
  34. 34. Scheduling mechanism (2) • Why must a process acquire ptable.lock before a call to swtch? • Breaks the convention that the thread that acquires a lock is also responsible for releasing the lock
  35. 35. Scheduling mechanism (2) • Why must a process acquire ptable.lock before a call to swtch? • Breaks the convention that the thread that acquires a lock is also responsible for releasing the lock • Without acquiring ptable.lock, two CPUs might want to schedule the same process because they can access ptable
  36. 36. scheduler • Simple loop: find a process to run, run it until it stops, repeat
  37. 37. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why?
  38. 38. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE)
  39. 39. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) 1 Idle looping while holding a lock would not allow any other CPU to access the process table
  40. 40. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1
  41. 41. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1 • The first process with p->state == RUNNABLE is selected
  42. 42. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1 • The first process with p->state == RUNNABLE is selected • The process is assigned to the per-CPU proc
  43. 43. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1 • The first process with p->state == RUNNABLE is selected • The process is assigned to the per-CPU proc • The process’s page table is switched to via switchuvm
  44. 44. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1 • The first process with p->state == RUNNABLE is selected • The process is assigned to the per-CPU proc • The process’s page table is switched to via switchuvm • The process is marked as RUNNING
  45. 45. scheduler • Simple loop: find a process to run, run it until it stops, repeat • Acquires and releases ptable.lock, and enables interrupts on every iteration. Why? • If CPU is idle (no RUNNABLE) Idle looping while holding a lock would not allow any other CPU to access the process table 2 Idle looping (all processes are waiting for I/O) while interrupts are disabled would not allow any I/O to arrive 1 • The first process with p->state == RUNNABLE is selected • The process is assigned to the per-CPU proc • The process’s page table is switched to via switchuvm • The process is marked as RUNNING • swtch is called to start running it
  46. 46. scheduler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void scheduler (void) { struct proc ∗p; for (;;){ sti (); acquire (& ptable .lock ); for(p = ptable .proc; p < & ptable .proc[ NPROC ]; p++){ if(p−>state != RUNNABLE ) continue ; proc = p; switchuvm (p); p−>state = RUNNING ; swtch (&cpu−>scheduler , proc−>context ); switchkvm (); proc = 0; }
  47. 47. Sleep and wakeup • sleep and wakeup enable an IPC mechanism
  48. 48. Sleep and wakeup • sleep and wakeup enable an IPC mechanism • Enable sequence coordination or conditional synchronization
  49. 49. Sleep and wakeup • sleep and wakeup enable an IPC mechanism • Enable sequence coordination or conditional synchronization • sleep allows one process to sleep waiting for an event
  50. 50. Sleep and wakeup • sleep and wakeup enable an IPC mechanism • Enable sequence coordination or conditional synchronization • sleep allows one process to sleep waiting for an event • wakeup allows another process to wake up processes sleeping on an event
  51. 51. Queue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct q { void ∗ptr; }; void∗ send( struct q ∗q, void ∗q) { while(q−>ptr != 0) ; q−>ptr = p; } void∗ recv( struct q void ∗p; while ((p = q−>ptr) == 0) ; q−>ptr = 0; return p; } ∗p) {
  52. 52. Queue with sleep and wakeup 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void∗ send( struct q ∗q, void ∗q) { while(q−>ptr != 0) ; q−>ptr = p; wakeup (q); } void∗ recv( struct q void ∗p; while ((p = q−>ptr) == 0) sleep (q); q−>ptr = 0; return p; } ∗p) {
  53. 53. Queue with sleep and wakeup and locking 1 2 3 4 struct q { struct spinlock lock; void }; ∗ptr;
  54. 54. Queue with sleep and wakeup and locking (2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void∗ send( struct q ∗q, void acquire (&q−>lock ); while(q−>ptr != 0) ; q−>ptr = p; wakeup (q); release (&q−>lock ); } void∗ recv( struct q void ∗q) { ∗p; acquire (&q−>lock ); while ((p = q−>ptr) == 0) sleep (q); q−>ptr = 0; release (&q−>lock ); return p; } ∗p) {
  55. 55. Queue with sleep and wakeup and implicit locking 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void∗ send( struct q ∗q, void acquire (&q−>lock ); while(q−>ptr != 0) ; q−>ptr = p; wakeup (q); release (&q−>lock ); } void∗ recv( struct q void ∗q) { ∗p; acquire (&q−>lock ); while ((p = q−>ptr) == 0) sleep (q, &q−>lock ); q−>ptr = 0; release (&q−>lock ); return p; } ∗p) {
  56. 56. sleep 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void sleep (void ∗chan , struct spinlock if(proc == 0) panic (" sleep "); if(lk == 0) panic (" sleep without lk"); if(lk != & ptable .lock ){ acquire (& ptable .lock ); release (lk ); } proc−>chan = chan; proc−>state = SLEEPING ; sched (); proc−>chan = 0; if(lk != & ptable .lock ){ release (& ptable .lock ); acquire (lk ); } } ∗lk) {
  57. 57. wakeup 1 2 3 4 5 6 7 8 9 10 11 12 static void wakeup1 (void struct proc ∗chan) { ∗p; for(p = ptable .proc; p < & ptable .proc[ NPROC ]; p++) if(p−>state == SLEEPING && p−>chan == chan) p−>state = RUNNABLE ; } void wakeup (void ∗chan) acquire (& ptable .lock ); wakeup1 (chan ); release (& ptable .lock ); } {
  58. 58. Today’s Task • ptable.lock is a very coarse-grained lock which protects the entire process table • Design a mechanism (in terms of pseudocode) that splits it up into multiple locks • Explain why your solution will improve performance while ensuring protection
  59. 59. Reading(s) • Chapter 5, “Scheduling” from “xv6: a simple, Unix-like teaching operating system”

×