Preparation for mit ose lab4


Published on

Notes from MIT OSE Lab4

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

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Preparation for mit ose lab4

  1. 1. Preparation forMIT-OSE Lab4 Ben 2012/05/29
  2. 2. ● Locking● Scheduling● Coordination and processes
  3. 3. ● Locking● Scheduling● Coordination and processes
  4. 4. Abstract SMP architecture● processors with one shared memory● devices● interrupts processed in parallel
  5. 5. Avoiding list race Lock list_lock; // one per listinsert(int data){ List *l = new List; insert(int data){ l->data = data; List *l = new List; l->data = data; acquire(&list_lock); l->next = list ; // A list = l; // B l->next = list ; // A critical section, or list = l; // B atomic section} release(&list_lock); } ● multiple processes adding to the disk queue
  6. 6. Race Condition Time A BCPU1 l->next listMemory l->next listCPU2 A B
  7. 7. Implementing lock and release● use atomic instructions (e.g., xchg)For example, the x86 <tt>xchg %eax, addr</tt> instructiondoes the following:freeze other CPUs memory activity for address addrtemp := *addr*addr := %eax%eax = tempun-freeze other memory activity
  8. 8. x86 asm to implement a spinlocklock: ; The lock variable. 1 = locked, 0 = unlocked. dd 0spin_lock: mov eax, 1 xchg eax, [lock] ; Atomically swap EAX register with lock variable. test eax, eax jnz spin_lock retspin_unlock: mov eax, 0 ; Set the EAX register to 0. xchg eax, [lock] ; Atomically swap EAX register with lock variable. ret ; The lock has been released.
  9. 9. Design Issues - locks and interrupts● ide disk generates interrupt when disk operation completes● interrupt causes ideintr to run● ideintr acquires lock? deadlock? give interrupt handler lock? (recursive locks)● xv6: critical sections have no interrupts turned on
  10. 10. Design Issues - locks and modularitymove(l1, l2) { move(l1, l2) { move(l1, l2) { acquire(l1.lock); acquire(l1.lock); acquire(l2.lock); e = del(l1) e = del(l1) release(l1.lock) e = del(l1) insert(l2, e) acquire(l2.lock); insert(l2, e) release(l1.lock) insert(l2, e) release(l2.lock) release(l2.lock)} } } original recursive Modified● recursive locks are a bad idea ideintr should certainly not use that instead of disabling interrupts!
  11. 11. ● Locking● Scheduling● Coordination and processes
  12. 12. Goals for solution● Switching transparent to user threads● User thread cannot hog a processor
  13. 13. Code - Concurrency - plock held across switch; why? yield: p is set runnable, p must completeswitch before another scheduler chooses p- hard to reason about; coroutine style helps - can two schedulers select the same runnableprocess? - why does scheduler release after loop, andre-acquire it immediately? (run with interrupts!)
  14. 14. Code - Thread clean up● lets look at kill: can we clean up killed process? (no: it might be running, holding locks etc.) before returning to user space: process kills itself by calling exit● lets look at exit; can thread delete its stack? (no: it has to switch off it!)● wait() does the cleanup
  15. 15. ● Locking● Scheduling● Coordination and processesRequired reading: remainder of proc.c, sys_wait, sys_exit, and sys_kill.
  16. 16. Coordination and more processes
  17. 17. Big pictureMultiple threads executing in the kernel andsharing memory, devices and various datastructures.● Allow more than one process to be executing to take advantage of multiple CPUs● Allow system calls that block waiting for I/O.
  18. 18. producer consumer queuestruct pcq { Need lock for pcq->ptr if multiple void *ptr; processors};void*pcqread(struct pcq *q){ while((p=q->ptr)==0); q->ptr = 0; return p;} Waste CPU Time. Instead of polling,pcqwrite(struct pcq *q, void *p) Use event-based (sleep and wakeup){ while(q->ptr != 0); q->ptr = p;}
  19. 19. Sleep & wakeupsleep(chan): sleep(void *chan, struct spinlock *lk) { curproc->chan = chan struct proc *p = curproc[cpu()]; curproc->state = SLEEPING sched() p->chan = chan; p->state = SLEEPING; release(lk); sched(); acquire(lk); } wakeup(void *chan)wakeup(chan): { foreach p in proc[]: for(each proc p) { if p->chan == chan if(p->state == SLEEPING and p->state==SLEEPING: && p->chan == chan) p->state = RUNNABLE; p->state = RUNNABLE } }
  20. 20. producer consumer queue (cont.)struct pcq { struct pcq { void *ptr; void *ptr;}; struct spinlock lock; };void* void* pcqread(struct pcq *q) {pcqread(struct pcq *q){ acquire(&q->lock); while(q->ptr == 0)sleep(q, &q->lock); while((p=q->ptr)==0); p = q->ptr; q->ptr = 0; q->ptr = 0; return p; wakeup(q); /* wake pcqwrite */} release(&q->lock); return p; }pcqwrite(struct pcq *q, void *p){ pcqwrite(struct pcq *q, void *p) { while(q->ptr != 0); acquire(&q->lock); q->ptr = p; while(q->ptr != 0) sleep(q, &q->lock);} q->ptr = p; wakeup(q); /* wake pcqread */ release(&q->lock); return p; }
  21. 21. Q&A Schduling Locking ? Threads