next up previous contents
Next: Classical Problems Up: Process Management Previous: Process Scheduling   Contents

Process Synchronization: Semaphores [75]





Critical Section: Example Problem [76]

        program code:            global variable x:
                      x=0;                       0
                      x++;                       1
                      printf x;                  1 <=== output

        PID 1          PID 2          PID 3      x:
        x=0;                                     0
        x++;                                     1
                       x=0;                      0
                                      x=0;       0
        printf x;                                0 <=== output
                       x++;                      1
                       printf x;                 1 <=== output
                                      x++;       2
                                      printf x;  2 <=== output



Critical Section: Attempted Solution [77]

Shared Variable:

int v=0; /* v==0 => critical section OPEN; v==1 => critical section CLOSED */

Code: At p_i in {1,...,n}:

   while (1) {

     /* trying region */
     while (v == 1)  /* do nothing */ ;
     
     v = 1;
     /* critical section (region) */ 
     x = 0;
     x++;
     printf x;

     v = 0;
     /* remainder region */   
   }



Critical Section: General Problem [78]



Semaphore: wait and signal [79]




\begin{picture}(805,482)(5,290)
\par\thinlines\put(100,660){\line( 0,1){ 20}}
\p...
...}}}
\put(590,458){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{GO}}}
\end{picture}



Semaphore: wait and signal [80]

                    while(1) {
                       pm_wait(sem);
                       /* critical section or region */
                       pm_signal(sem);
                    }

                    while(1) {
                       pm_wait(sem);
                       x=0;
                       x++;
                       printf x;
                       pm_signal(sem);
                    }



Semaphore: wait and signal [81]

                    struct {
                       int count=1;
                       FIFO queue;
                    } semaphore;

  wait(semaphore) : if (--semaphore.count<0){
                      put_at_tail(pid,semaphore.queue);
                      suspend(pid) }
        
signal(semaphore) : if (semaphore.count++<0){
                      pid=get_at_head(semaphore.queue);
                      ready(pid) }



Semaphore: Initialization [82]



Semaphore: Count [83]

            PID 1                 PID 2                 count
            sem=pm_seminit(1);                            1
            pm_wait(sem);                                 0
               |                  pm_wait(sem);          -1
    (critical) |
               v
            pm_signal(sem);                               0
            pm_wait(sem);            |                   -1
                                     | (critical)
                                     v
                                  pm_signal(sem);         0
               |                  pm_wait(sem);          -1
    (critical) |
               v
            pm_signal(sem);                               0



Critical Section Solution [84]

Here is a summary:

DEFINITION PROOF TECHNIQUE
MUTEX at most 1 proc in C.S. can't prove not mutex
NOT MUTEX at least 2 procs in C.S. slice before locking
PROGRESS at least 1 proc does work, liveness can't prove not progress
NOT PROGRESS 0 procs do work, deadlock, but not starvation all spinning (or blocked on semaphores)
FAIRNESS all procs do work can't prove not fairness
NOT FAIRNESS 1 proc does work at expense of another not doing work,
starvation, asymmetrical relationship
one proc releases but retakes lock, other proc just misses

Of course, it's impossible to enumerate every possible proof of NOT MUTEX. So you really don't prove that it has MUTEX. But you always try NOT MUTEX first and, if you can't find such a proof and you feel more confident about the code, you very carefully say that it does guarantee MUTEX.

This is not a proof technique of unfairness: I pick a priority scheduler, always run P0, but never run P1. P1 starves.Well, what happens if you are given some different code? Are you going to repeat the same proof? Then you are given some more code. You repeat the same argument? You're not analyzing the code you're given - and that's the main point. You have to give P1 some opportunities to run on the CPU. But you can choose those opportunities (devil's advocate), and choose these such that P0 has taken the lock back, and P1 just misses everytime.

All of the following is older detail about this topic, but the table above is the simplest way of viewing this topic.



Critical Section: Deadlock [85]

Kansas legislature:

When two trains approach each other at a crossing,

both shall come to a full stop

and neither shall start up again until the other has gone.



Semaphores: Deadlock [86]

                       pm_wait(S);
                       pm_wait(Q);
                       /* critical section */ 
                       pm_signal(S);
                       pm_signal(Q);

                       pm_wait(Q);
                       pm_wait(S);
                       /* critical section */ 
                       pm_signal(Q);
                       pm_signal(S);


next up previous contents
Next: Classical Problems Up: Process Management Previous: Process Scheduling   Contents
Ted Billard 2001-11-17