CPS110 Exam2 with answers April 1, 2004

 

Do one question from each category, plus an additional question.  Each worth 25 points.

Synchronization:
 

1. Highway 110 is a two-lane road that passes through a one-lane bridge.  A car
can safely enter the bridge if and only if there are no oncoming cars in the
bridge.  You may assume that each car is represented by a thread that calls
Enter (int direction) and Leave() functions, passing an argument indicating the
direction of travel. The traffic light policy is that cars are allowed through
in sequence.  If there is a car waiting to go in the opposite direction, then
that car should get the right of way, and be allowed to pass. Implement Enter
and Leave functions that avoids deadlocks and starvations using any of the
following synchronization primitives : locks, condition variables, mutexes,
semaphores.

     Lock L; Condition W[2];
     int cars[2]={0,0}, wait[2]={0,0}, cdir=0;

     void Enter(int dir) {
         L->Acquire();
         int od = 1-dir;
         wait[dir]++;
         while ((cars[od]>0)||((wait[od]>0)&&(cdir==dir))) {
              W[dir]->Wait(L);
              }
         cars[dir]++;
         wait[dir]--;
         cdir=dir;
         L->Release();
         }

     void Leave(int dir) {
         L->Acquire();
         cars[dir]--;
         if (cars[dir]==0) W[1-dir]->Broadcast(L);
         L->Release();
         }

     Explanation:  If there are cars on the bridge going the other way, OR if
     the last car to enter the bridge was going MY way, and there are cars
     going the other way waiting to cross, I wait.

     This is somewhat inefficient, since when there are cars waiting to cross
     in BOTH directions, it allows only one car at a time to enter the
     bridge, in alternate directions.  However, this makes inefficient use of
     th bridge, since it takes time for a car to cross.  More cars could
     cross if several were allowed onto the bridge in a given direction,
     before stopping that flow, and allowing cars from the other direction to
     cross.  This would clear both lines faster.

     Also, the Broadcast wakes up all waiting cars.  If there are still cars
     waiting going in my direction, then only one of the awakened cars will
     actually make it onto the bridge -- the first car to enter the bridge
     will change cdir, stopping the line of cars.  Thus the Broadcast causes
     more processes to awaken than can actually run -- all must execute the
     tests and issue new Wait() operations.  This uses extra processor
     cycles.

2. In an electronic funds transfer system, there are hundreds of identical
processes that work as follows: each process reads in input line specifying an
amount of money, the account number to be credited, and the account number to
be debited (i.e., both account numbers known). The process must lock both
accounts, then transfer the money, and finally release the locks when finished.
The primitive you have available for your use locks a single account at a time
(e.g,.  lock(acctnum) ). Locks must be held on both accounts while transferring
money otherwise errors could result. Even with thousands of accounts, if there
are many processes running in parallel, there is a real danger of encountering
already locked accounts when requesting locks and, thus, the danger of
deadlock. Describe a scheme to do this that avoids deadlocks and starvation.
     The key to avoiding deadlock is to acquire the locks in some fixed
     order, say in increasing numeric order.  In this way, there can be no
     cycle of lock holds:
         Transfer(int A1, int A2, int Amount) {
              if (A1==A2) return;
              if (A1<A2) { lock(A1); lock(A2); }
              else {lock(A2); lock(A1); }
                  /*  Do the funds transfer here.  */
              unlock(A1); unlock(A2);
              }

     Starvation:  A tranaction could be prevented from eve running if other
     transactions were constantly granted the lock for one of the accounts
     needed.  To prevent this, the system lock monitor must grant requests
     for a given lock in some fair order, ensuring that no request waits
     forever.  For example, it might use the First Come First Served order.

Scheduling:

3. Consider a system with two processes, H, a high priority process, and L, a
low priority process. The scheduler chooses the highest priority ready process
to be the one to run at each scheduling opportunity. Suppose that L has just
run and entered a critical section protected by a spin-lock (a busy-waiting
implementation). Now H becomes ready to run, having completed some I/O
that previously had it blocked, and is scheduled immediately. Then H tries to
enter its critical section by trying to acquire the spin-lock. Assuming you
can modify the code of processes H and L, without changing the priorities, what
could you change so that this is avoided ? What can you change at the OS level
to prevent this ? Explain your answer.
     You can change the code so that a Lock, rather than a spin-lock, is used
     to protect the critical section.  (Any scheme which blocks when access
     to the CS is denied will work.)  With this change, when H tries to enter
     the CS, H blocks, and is no longer running.  This allows the
     lower-priority process L to run, and hopefully exit the CS.

     Note: Other processes of priority between H and L might still run,
     preventing L from actually getting any CPU time.)

     At the OS level, I'd have to change the scheduling rule (assuming the
     code is still using spin-locks).  The new rule would be to run H only
     until it uses T[H] time units, then pre-empt H, and run L for T[L] time
     units.  The idea is to ensure that L gets SOME execution time, while
     still ensuring that H gets more.  To do this, set T[H]>T[L].
     The difficulty with this scheme is that H may not get enough execution
     time to meet it deadline, if there is such a deadline.

4. A computer system runs a stream S of jobs in First Come First Served order.
The stream of jobs arrival times is normally distributed with mean arrival rate
of 1 job every 40 seconds.  The CPU requirement of the jobs is normally
distributed, with a mean of 10 seconds per job.  In addition, two high-priority
real-time jobs must also run on the same computer.  Job A requires 5 seconds
every 30 seconds, and job B requires 2 seconds every 6 seconds.  Design a
scheduling policy for this system that ensures the deadlines for the real-time
jobs are met.  Specify whether your scheduler uses preemption or not.  Specify
the rules which the scheduler uses to choose the next job to run, and the
rule(s) used for choosing the scheduler decision times (e.g., when the next job
from S completes, or after X seconds.)
     Policy:  Give the real-time jobs higher priority than any job in S.
     Schedule the real-time jobs using Earlist Deadline First.
     The schedule uses pre-emption.
         Whenever a real-time deadline passes, the running job is
         interrupted, and the scheduler determines which real-time job's
         deadline comes next, and runs that job.
         When ANY job finishes, the scheduler again makes a decision.  If
         both RT jobs have completed their current work, the scheduler
         resumes the current job from S (if it had been interrrupted), or
         picks the next job from S in FCFS order, and starts running it.
     Decisions are made:  At any RT job deadline, and when any job finishes.
     Rule:  If any RT job has work to do in this period, run that RT job
     whose next deadline comes earliest.  Otherwise, resume or start the
     first job in the FCFS queue of stream S.

Memory management :

5.
(a) A computer with 32-bit virtual addresses uses a two-level page table.
Virtual addresses are split into a 9-bit top-level page table field, an 11-bit
second-level page table field, and an offset. How large are the pages and how
many are there in the address space ?
     Virtual Page Number occupies 9+11 bits, while the page offset occupies
     the rest.  VPN is 20 bits, Offset is 32-20=12 bits. So there are
     2**12=4096 bytes per page, and there are 2**20 pages in the address
     space.

(b) A machine has 48-bit virtual addresses and 32-bit physical addresses. Pages
are 8K. How many entries are needed for a conventional page table? For an
inverted page table ?
     8K byte page requires an Offset field of 13 bits, since 8K=2**13
     The size of the VPN field is then 48-13 = 35 bits.
     This means that a conventional page table, with one entry per virtual
     page, needs 2**35 entries.  (This is some 32 billion entries.)
     An inverted page table needs one entry per Physical page.  There are
     32-13 = 19 bits in the physical page frame number, and hence 2**19
     entries in an invertd page table.  (2**19 is about 1/2 million -- a
     feasible page table size.)


6.  Consider an application accessing the pages in the folowing order:
1 2 3 4 1 2 ... with { 1 2 3 4} repeated M times.  Assume a memory contains
just 3 page frames which is initially empty.  Show the first reference on which
LRU and OPT make DIFFERENT decisions.  What are those decisions?  Finally,
estimate how many page faults LRU will make, and how many OPT will make
on this reference string and explain why.
     1 2 3 <4> 1 2 3 4
     At the first reference to page 4, memory will hold pages 1 2 3.  LRU
     will choose to replace the page refernced longest ago, which is page 1.
     OPT will look ahead, and find the page which will be first referenced
     farthest into the future, so OPT will pick page 3.

     I'll show the reference string on line 1, and below each reference, show
     the contents of memory AFTER that reference in a column, giving the page
     in frame i in row i.  The *'s mark page faults:

     LRU:
     * * * * * *
     1 2 3 4 1 2 3 4 1 2 3 4
     1 1 1 4 4
     - 2 2 2 1
     _ _ 3 3 3
     So LRU appears to fault at every reference.  LRU:  4M faults.

     OPT
     * * * *     *     *
     1 2 3 4 1 2 3 4 1 2 3 4
     1 1 1 1     1     2
     - 2 2 2     3     3
     _ _ 3 4     4     4
     So OPT appears to fault once every 3 references.  OPT:  4M/3+2
     (The +2 accounts for the first iteration, when nothing was in memory,
     and 2 extra faults occur.)

     Why:  LRU looks into the past, and in this case by accident makes the
     worst poccilbe decision at every fault.  OPT, seeing the future, avoids
     some faults, by keeping in memory those pages that WILL be referenced in
     the immediate future (next).