CSE 430 – Operating Systems –
Spring 2009
Assignment: #3
Q1]
The following code fragment is a
2-process "solution" to the critical section problem.
try[i] = 1;
while (incs[j]==1) no-op;
while (turn==j and try[j]==1) no-op;
incs[i] = 1;
critical
section
try[i] = 0;
incs[i] = 0;
turn = j;
Does the above "solution"
meet all 3 conditions of critical sections? Please explain your answer.
No
mutual exclusion.
Example:
[Initial values] turn=0,
flag[0]=false, flag[1]=false;
[Running]
P1: if (turn=1) then flag[1]=true;
P1: while (flag[0]) waiting...; // no need to wait.
CONTEXT SWITCH
P0: if (turn==0) then flag[0]=true
P0: while (flag[1]) waiting...// no need to wait.
P0: flag[0]=true;
P0: ENTERING CRITICAL SECTION
CONTEXT SWITCH
P1: flag[1]=true;
P1: ENTERING CRITICAL SECTION
Q2]
Suppose a system has an atomic
hardware instruction SHIFT, that does the follows:
SHIFT ( int *A, *B ) {
*B =*A; // ATOMICALLY
*A = 0
}
A] Implement Dijkstra
style semaphores with the shift instruction, that is
the semaphores utilize busy waiting (defined in section 6.5 in the 8th
edition of textbook).
int lock;
// Lock is initially
set to 1;
// Semphores
are defined as integers.
typedef int semaphore;
// Define
2 functions called GetCS and ReleaseCS
GetCS()
{ int temp;
temp = 0;
while (temp = 0)
shift (lock, temp); // busy loop
}
ReleaseCS()
{
lock =
1; }
// Now define the
semaphore routines.
wait(semaphore S) // or
P(S)
{
GetCS()
while (S==0) {
ReleaseCS()
GetCS();
S = S - 1;
ReleaseCS();
}
signal(semaphore S) // or
V(S)
{
GetCS();
S = S + 1;
ReleaseCS()
}
B] Implement blocking semaphores
using the shift instructions. (defined in section
6..5.2 in 8th edition of book).
To use the blocking routines... use the GetCS and ReleaseCS defined in A. //define a semaphore astypedef struct {
int count; PCBQueue Q} semaphore; wait(semaphore S) { // or P(S)
GetCS() S.count--; if (S.count<0) { move current PCB to S.Q; ReleaseCS(); block(); }} signal(semaphore S) // or V(S)
{ GetCS(); S.count++; if (S.Count<=0) { move a PCB from S.Q to ready Q; //wakeup } ReleaseCS();}
Q3]
There are 4 processes, executing
concurrently. Process P0 is in an infinite loop, incrementing the value of the
variable x (x is initialized to 0). P0 is the only process that
changes the value of x.
The rest of the processes Pi
(1<= i <=3) monitor the value of x.
Whenever x reaches a value such that it is
divisible by i, Pi prints the value of x.
For example, P3 will print the sequence 3 6 9 12 ….. as
the value of x reaches 3, 6, 9, 12 and so on.
Write the code for all the 4
processes using semaphores. Note that P1 - P3 should be identical.
// no answer provided, figure this one out, it is
straightforward
Q4]
A synchronization mechanism consists
of 2 atomic routines, ENQ(r) and DEQ(r). "r"
is a resource variable that has two fields, inuse (boolean) and queue (a queue) which is a queue of processes
waiting to acquire the resource. The definitions of ENQ and DEQ are:
ENQ(r) : if (r.inuse==1) then begin
insert current process in r.queue
block
end
else r.inuse = 1;
DEQ(r) : if r.queue == nil then inuse = false
else delete a
process from r.queue and activate it.
Construct an implementation of
ENQ/DEQ using semaphores. You can use other variables, etc that you need, but
no other atomic code or synchronization constructs other than P or V can be
used.
The resource is a Semaphore initialized to 1
P(r)
= Enq(r)
V(r)
= DEQ(r)
Q5]
Do the reverse of Q3, that is implement Semaphores using
ENQ/DEQ.
Semaphore is a structure containing
a count and two queues mutex and block.
InitSem(s, val) { //important routine
s.count = val;
ENQ(s.block) // lock the block resource
}
P(Sem) {
ENQ(sem.mutex); // get critical section
sem.count--;
if (sem.count
< 0) {
DEQ(sem.mutex);
ENQ(sem.block);} // block the caller
else
DEQ(sem.mutex);
}
V(sem) {
ENQ(sem.mutex);
sem.count
++;
if (sem.count<=0) DEQ(sem.block); // unblock a waiting process
DEQ(Sem.mutex);
}