CS 3733 Operating Systems Notes: Semaphore implementation without busy waiting


The idea:

wait(S):
 S.value--;  
 if (S.value < 0) {
     <Add this process to S.list>
     <block>
 }

signal(S):

 S.value++;
 if (S.value <= 0) {
    <move a process from S.list to the ready list>
 }

Standard ways to use a semaphore:
Protect a critical section:
S is initialized to 1:

   wait(S);
     <C.S.>
   signal(S);

Make sure P1 executes before P2:
S initialized to 0:
P1
   <do something>
   signal(S);
P2
   wait(S);
   <do something>

Note: the type of queue we use will determine the order in which processes which are waiting for a given semaphore get serviced.
A FIFO queue guarantees bounded waiting, but othe queue techniques may produce starvation.

Care must be taken when dealing with semaphores:
Consider two processes P1 and P2.
P1 executes:

       wait(S);
           ...
       signal(Q);
while P2 executes:
        wait(Q);
           ...
        signal(S);
Each is waiting for the other and if the semaphores are both initialized to 0, a deadlock can occur.

Bounded buffer problem using sempahores
Assume we have n buffers.
Use three semaphores:

Producer Loop
     produce item in nextp
     wait(empty)
     wait(mutex)
        <add nextp to buffer>
     signal(mutex)
     signal(full)

Consumer Loop

     wait(full)
     wait(mutex)
        <remove item from buffer, put in nextp>
     signal(mutex)
     signal(empty)
     consume item in nextp