Spinlock Vs. Sleeping Lock Spinlock Implementation(1)

Spinlock Vs. Sleeping Lock Spinlock Implementation(1)

Semaphores EECS 3221.3 • Problems with the software solutions. Operating System Fundamentals – Complicated programming, not flexible to use. – Not easy to generalize to more complex synchronization problems. No.6 • Semaphore (a.k.a. lock): an easy-to-use synchronization tool – An integer variable S Process Synchronization(2) – wait(S) { while (S<=0) ; S-- ; Prof. Hui Jiang } Dept of Electrical Engineering and Computer – signal(S) { Science, York University S++ ; } Semaphore usage (1): Semaphore usage (2): the n-process critical-section problem as a General Synchronization Tool • The n processes share a semaphore, Semaphore mutex ; // mutex is initialized to 1. • Execute B in Pj only after A executed in Pi • Use semaphore flag initialized to 0 Process Pi do { " wait(mutex);! Pi Pj " critical section of Pi! ! … … signal(mutex);" A wait (flag) ; signal (flag) ; B remainder section of Pi ! … … ! } while (1);" " " Spinlock vs. Sleeping Lock Spinlock Implementation(1) • In uni-processor machine, disabling interrupt before modifying • Previous definition of semaphore requires busy waiting. semaphore. – It is called spinlock. – spinlock does not need context switch, but waste CPU cycles wait(S) { in a continuous loop. do { – spinlock is OK only for lock waiting is very short. Disable_Interrupt; signal(S) { • Semaphore without busy-waiting, called sleeping lock: if(S>0) { S-- ; Disable_Interrupt ; – In defining wait(), rather than busy-waiting, the process makes Enable_Interrupt ; S++ ; system calls to block itself and switch to waiting state, and return ; Enable_Interrupt ; put the process to a waiting queue associated with the } return ; semaphore. The control is transferred to CPU scheduler. Enable_Interrupt ; } – In defining signal(), the process makes system calls to pick a } while(1) ; process in the waiting queue of the semaphore, wake it up by } moving it to the ready queue to wait for CPU scheduling. – Sleeping Lock is good only for long waiting. 1 Spinlock Implementation(1) Spinlock Implementation(2) • In multi-processor machine, inhibiting interrupt of all • In uni-processor machine, disabling interrupt before modifying processors is not easy and efficient. semaphore. • Use software solution to critical-section problems – e.g., bakery algorithm. wait(S) { – Treat wait() and signal() as critical sections. do { • Or use hardware support if available: signal(S) { Disable_Interrupt; – TestAndSet() or Swap() if(S>0) { S-- ; Disable_Interrupt ; Enable_Interrupt ; S++ ; • Example: implement spinlock among two processes. return ; Enable_Interrupt ; – Use Peterson’s algorithm for protection. } return ; – Shared data: Enable_Interrupt ; } while(1) ; } } Semaphore S ; Initially S=1 boolean flag[2]; initially flag [0] = flag [1] = false. int turn; initially turn = 0 or 1. Spinlock Implementation(3) Spinlock Implementation(2) wait(S) { • In multi-processor machine, inhibiting interrupt of all int i=process_ID(); //0P0, 1P1 signal(S) { processors is neither easy nor efficient. int i=process_ID(); //0P0, 1P1 int j=(i+1)%2 ; • Use software solution to critical-section problems int j=(i+1)%2 ; do { – e.g., bakery algorithm. flag [ i ]:= true; //request to enter – Treat wait() and signal() as critical sections. flag [ i ]:= true; //request to enter turn = j; • Or use hardware support if available: while (flag [ j ] and turn = j) ; turn = j; while (flag [ j ] and turn = j) ; – TestAndSet() or Swap() if (S >0) { //critical section S--; S++; //critical section • Example: implement spinlock between N processes. flag [ i ] = false; – Use Bakery algorithm for protection. return ; flag [ i ] = false; – Shared data: } else { flag [ i ] = false; return ; Semaphore S ; Initially S=1 } } } while (1); boolean choosing[N]; (Initially false) } int number[N]; (Initially 0 ) Spinlock Implementation(3) Sleeping Lock (I) wait(S) { int i=process_ID(); signal(S) { int i=process_ID(); • Define a sleeping lock as a structure: choosing[ i ] = true; number[ i ] = max(number[0], number[1], choosing[ i ] = true; typedef struct { …, number [N – 1])+1; number[ i ] = max(number[0], number[1], int value; // Initialized to 1 choosing[ i ] = false; …, number [N – 1])+1; for (j = 0; j < N; j++) { choosing[ i ] = false; struct process *L; while (choosing[ j ]) ; for (j = 0; j < N; j++) { } semaphore; while ((number[ j ] != 0) && while (choosing[ j ]) ; (number[ j ],j)< (number[ i ],i)) ; while ((number[ j ] != 0) && } (number[ j ],j)< (number[ i ],i)) ; • Assume two system calls: if (S >0) { //critical section } S--; – block() suspends the process that invokes it. number[i] = 0; S++; //critical section – wakeup(P) resumes the execution of a blocked process P. return ; } number[i] = 0; number[i] = 0; • Equally applicable to multiple threads in one process. } while (1); return ; } } 2 Sleeping Lock (II) Two Types of Semaphores: Binary vs. Counting • Semaphore operations now defined as: • Binary semaphore (a.k.a. mutex lock) – integer value wait(S): can range only between 0 and 1; simpler to implement S.value--; by hardware. if (S.value < 0) { add this process to S.L; • Counting semaphore – integer value can range over an block(); unrestricted domain. } signal(S): • We can implement a counting semaphore S by using S.value++; two binary semaphore. if (S.value <= 0) { remove a process P from S.L; • Binary semaphore is normally used as mutex lock. wakeup(P); } • Counting semaphore can be used as shared counter, load controller, etc… Implementing counting semaphore Implementing S with two Binary Semaphores • wait(S) operation: wait_binary(S1); C--; if (C < 0) { • Data structures: signal_binary(S1); binary-semaphore S1, S2; wait_binary(S2); int C: } signal_binary(S1); • Initialization: • signal(S) operation: S1 = 1 wait_binary(S1); S2 = 0 C ++; C = initial value of semaphore S if (C <= 0) signal_binary(S2); else signal_binary(S1); Bounded-Buffer P-C Problem Classical Synchronization Problems • A producer produces some data for a consumer to consume. They share a bounded-buffer for data • The Bounded-Buffer P-C Problem transferring. • Shared memory: A buffer to hold at most n items • The Readers-Writers Problem • Shared data (three semaphores) • The Dining-Philosophers Problem Semaphore filled, empty; /*counting*/ Semaphore mutex; /* binary */ Initially: filled = 0, empty = n, mutex = 1 3 Bounded-Buffer Problem: Bounded-Buffer Problem: Producer Process Consumer Process do { do { … wait(filled) produce an item in nextp wait(mutex); … … wait(empty); remove an item from buffer to nextc wait(mutex); … … add nextp to buffer signal(mutex); … signal(empty); signal(mutex); … signal(filled); consume the item in nextc … } while (1); } while (1); The Readers-Writers Problem The 1st Readers-Writers Problem • Many processes concurrently access a data object • Use semaphore to implement 1st readers-writer problem – Readers: only read the data. – Writers: update and may write the data object. • Shared data: • Only writer needs exclusive access of the data. int readcount = 0 ; // keep track the number of readers // accessing the data object • The first readers-writers problem: – Unless a writer has already obtained permission to use the shared data, readers are always allowed to access data. Semaphore mutex = 1 ; // mutually exclusive access to // readcount among readers – May starve a writer. • The second readers-writer problem: Semaphore wrt = 1 ; // mutual exclusion to the data object // used by every writer – Once a writer is ready, the writer performs its write as soon as possible. //also set by the 1st reader to read the data – May starve a reader. // and clear by the last reader to finish reading The Dining-Philosophers Problem The 1st Readers-Writers Problem • Five philosophers are Reader Process Writer Process thinking or eating …! • Using only five …! chopsticks wait(mutex);" wait(wrt);" readcount++; "" • When thinking, no need for chopsticks. …! if (readcount == 1) wait(wrt);" writing is performed! • When eating, need two signal(mutex);" closest chopsticks. …! …! • Can pick up only one signal(wrt);" reading is performed! chopsticks … …! • Can not get the one wait(mutex);" already in the hand of a readcount--;" neighbor. if (readcount == 0) signal(wrt);" signal(mutex);" … 4 The Dining-Philosophers Problem: Semaphore Solution Incorrect Semaphore Usage • Represent each chopstick with a semaphore Semaphore chopstick[5]; // Initialized to 1 Mistake 1: Mistake 2: Mistake 3: Mistake 4: do {" Philosopher i … … … wait(chopstick[i]) ;" … (i=0,1,2,3,4) signal(mutex) ; wait(mutex) ; wait(mutex) ; wait(chopstick[(i+1) % 5]) ;" Critical … … … …" Section Critical Critical Critical … eat! Section Section Section …" signal(mutex) ; … … … signal(chopstick[i]);" wait(mutex) ; wait(mutex) ; signal(chopstick[(i+1) % 5]);" …" think! …" } while (1); Starvation and Deadlock double_rq_lock() in Linux Kernel • Starvation – infinite blocking. A process may never be double_rq_lock(struct runqueue *rq1, removed from the semaphore queue in which it is struct runqueue *rq2) suspended. { if (rq1 == rq2) • Deadlock – two or more processes are waiting infinitely for an event that can be caused by only one of the waiting spinlock(&rq1->lock); processes. else { • Let S and Q be two semaphores initialized to 1 if (rq1 < rq2) { P0 P1 spin_lock(&rq1->lock); wait(S); wait(Q); spin_lock(&rq2->lock); wait(Q); wait(S); } else { spin_lock(&rq2->lock); signal(S); signal(Q); spin_lock(&rq1->lock); signal(Q) signal(S); } } } Why not? double_rq_unlock() in Linux Kernel double_rq_lock(struct runqueue *rq1, struct runqueue *rq2)

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    7 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us