0% found this document useful (0 votes)
306 views

HW 2

This document contains solutions to homework problems on operating systems concepts. It includes code samples and outputs for problems on random number generation using pid, measuring execution time using gettimeofday, implementing mutual exclusion using forking and threads, and generalizing strict alternation and l-exclusion for multiple processes.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
306 views

HW 2

This document contains solutions to homework problems on operating systems concepts. It includes code samples and outputs for problems on random number generation using pid, measuring execution time using gettimeofday, implementing mutual exclusion using forking and threads, and generalizing strict alternation and l-exclusion for multiple processes.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Operating Systems

(Home Work-2)

D.Harikrishna(MT2010029)

N.Sandesh(MT2010130)
03 february 2011

1
1. Look up the standard C rand() function. Using the same, create a mod-
ified function zrand() which does not have the srand feature at all, but
internally uses srand to seed the random function with the pid of the call-
ing process. Use this function in a test program and submit the code and
results of the same.
Ans:

#include<stdio.h>
void zrand(void);
main()
{
zrand();
}
void zrand(void)
{
int r,i;
int k=getpid();
printf("%d\t",k);
srand(getpid());
for(i=0;i<5;i++)
{
r=rand();
printf("%d\t",r);
}
}

The output of the program is:11013,1757021573,1470579695, 1161962081,708410923,94039433

2. Write a C procedure getTime() that can be used to return the exe- cution
time of code segments by calling it before the code segment is executed
and again after the code segment is executed.

A. Experiment with your routine to find out the smallest clock resolution
that can be obtained on your machine, and report the results (including
the values obtained). What happens when an even smaller resolution is
attempted?

Ans:
#include<stdio.h>
#include<sys/time.h>
#include<math.h>
double getTime(int);
main()

1
{
double start,stop,elapsedTime;
int i,j,n;
printf("\nenter precision value");
scanf("%d",&n);
start=getTime(n);
for(i=0;i<1000000000;i++);
stop=getTime(n);
elapsedTime=stop-start;
printf("%lf\n",elapsedTime);
}
double getTime(int x)
{
double time;
struct timeval tv;
gettimeofday(&tv,NULL);
time=tv.tv_sec*pow(10,x);
return time;
}

output :
getTime(n). Time(sec).
-3 0.003000
-4 0.000300
-5 0.000030
-6 0.000003
-7 0.000000

When we give the precision -7 the time value becomes 0.000000 , So -6


is the precision for smaller resolution value.

B. Write a simple program to generate the first 10 million prime numbers.


Generate statistics (based on at least 20 trials) using your routine for the
execution time of this program, such as minimum, maximum, average,
and standard deviation.
Ans:
#include<stdio.h>
#include<sys/time.h>
#include<math.h>
#define max 179424673
double getTime(int);
main()
{
double start,stop,elapsedTime;
int n;
long int count=0,i=max,cnt=0,c1,c2,c3;

2
static long int prime[max],p=2;
start=getTime(-6);
printf("%lf\n",start);

prime[0]=prime[1]=1;
for(c2 = 2;c2 <= i+1;c2++){
if(prime[c2] == 0){
c1=c2;
for(c3 = 2*c1;c3 <= i+1; c3 = c3+c1){
prime[c3] = 1;
}
}
}
for(p=2;p<i+1;p++)
{
if(prime[p]==0)
{
count++;

}
}

stop=getTime(-6);
elapsedTime=stop-start;
printf("%lf\n",elapsedTime);
printf("%ld\n",count);
}
double getTime(int n)
{
double time;
struct timeval tv;
gettimeofday(&tv,NULL);
printf("%d\n",n);
time=(tv.tv_sec*pow(10,6)+tv.tv_usec)/pow(10,6+(-6));
return time;
}

output :

3
sample No. Time(micro sec).
1 10869613
2 10743310
3 10740737
4 10769959
5 10781596
6 10742054
7 10748027
8 10752064
9 10719711
10 10741844
11 10746528
12 10737779
13 10753873
14 10755936
15 10757903
16 10755027
17 10762762
18 10755191
19 10763881
20 10745067

Statistics Value
Mean 10757143.00
Variance 828772992
Standard Deviation 28788.417969
Maximum value 10869613 Microsec.
Minimum value 10719711 Microsec.

3. Consider the following code which uses fork():


main()
{
int i = 0;
if (fork()) {
int j;
for (j = 0;j < 10; j++) { puts( "x" ); }
exit();
} else {
int j;
for (j = 0;j < 10; j++) { puts( "y" ); }
exit();
}
}

A. Understand what this code does, and explain its working.


Ans:

4
fork() is a system call. When it is invoked it will create a new child
process of the same process. A seperate address space will be created for
that child process.The return value of fork() is 0 if it is executing in child
process, whereas in the parent process return value will be pid of the child
process.
Here, when ever the code is executed if it encounters the systemcall
fork(), it will create the new copy of the process, and this is called as
child process.So, execution of both processes(child and parent) will con-
tinue.Now in the execution part if parent executes the return value of fork
will be non-zero pid of the child process,so it will print x . Whenever child
process exeutes ,since the return value of fork is 0 it will print y value.
Thus both child and parent process will executes parallel so printing of x
and y will be in an arbitary fashion.

B. Implement an equivalent of the same without fork(), using Pthreads.

#include <stdio.h>

void *runner1(void *param)


{
int i;
for(i=0;i<10;i++)
puts("x");
}

void *runner2(void *param)


{int i;
for(i=0;i<10;i++)
puts("y");
}

int main()
{
int i;
pthread_t tid[2];
pthread_attr_t attr;
pthread_attr_init(&attr);

pthread_create(&tid[0],&attr,runner1,NULL);
pthread_create(&tid[1],&attr,runner2,NULL);

for(i=0;i<2;i++)
pthread_join(tid[i],NULL);

5
Pthreads are POSIX standard for thread creation. here instead of cre-
ating a seperate process a part of executing process will be created,so the
same resources can be accessed.thread creation() starts a seperate thread
which will be intiated from main().
In the program, thread creation() is called twice to create two pro-
cesses, which will be controlled by runner1 and runner2 functions.So threads
while executing there will be a context-switch which will leads to print x
sometimes intially then y afterwards or arbitarilly in between x or the vice
verse.

4. As discussed in class, strict alternation (using a variable turn that could


take the values 0 or 1) can be used to enforce mutual exclusion among two
processes p0 and p1.

A.Generalize the idea to get a procedure for mutual exclusion among n


processes p0 through pn−1 .

Ans:

turn : checks for its turn or not


n : Number of processes
while true do
while turn! = i do
end
critical section();
if turn = n − 1 then
turn ← 0;
else
turn ← i + 1;
end
remainder section();
end
Algorithm 1: Generalizing strict alternation for n processes

Three properties to satisfy:


Mutual-exclusion:
This program ensures mutual exclusion for n-processes, because it al-
lows only one process at a time,since turn checks whether it is its turn or
not.otherwise it will keep in busywait state untill it’s turn comes.
Bounded-wait:
This program ensures Bounded-wait ,since when a process completes
execution it cannot excute the same process again because it is setting turn

6
to other process,therefore thereis no chance of starvation,all processes will
executes in a round-robin fashion.
Progress-Condition:
This program doesn’t ensure Progress-condition, since by setting the
turn to next processes turn ,even though its not willing to enter ,the pro-
gram doesnt allow any other process unless the next process comes.

B.Generalize further, to create a procedure for l-exclusion, where n >


l ≥ 2.

Ans:

Global variables:
turn : ← intially set to 0, checks for its turn or not;
count : ← intially set to -1, specifies the number of processes in critical
section;
present : ← intially set to 0, stores the latest turn value;
while true do
if count <= L − 1 then
count ← count+1; if count >= 0 then
while turn! = j do
end
present ←j;
if present = l − 1 then
turn ← 0;
else
turn ← present+1;
end
critical section();
count ←count-1;
end
else
wait(pj );
end
end
Algorithm 2: L- Exclusion for process pj

Three conditions to satisfy l-Exclusion.


Mutual-exclusion:
This program ensures l-exclusion for n-processes, because it allows at-
most l-1 process at a time,since count value checks whether it is less than
l or not,also turn number its turn or not.otherwise it will keep in busywait
state untill it’s turn comes.
Bounded-wait:

7
This program ensures Bounded-wait ,since when a l-number of process
completes execution it cannot excute the same processes again because it is
setting turn to one more than maximum of all current processes ,therefore
there is no chance of starvation,all processes will executes in a round-robin
fashion.
Progress-Condition:
This program doesn’t ensure Progress-condition, since by setting the
turn to next processes turn ,even though its not willing to enter ,the pro-
gram doesnt allow any other process unless the next process comes.

5. A file is to be shared among different processes, each of which has a unique


process id. The file can be accessed simultaneously by several processes,
subject to the constraint that the sum of all unique pids associated with
the processes currently accessing the file must be less than some n. Write
pseudocode for a controller that coordinates access to the file.

Ans:

count : Stores the sum of all pids that are accessing the file currently.
getpid() : Gets the process-id of the corresponding process.
if count < n then
if count + getpid() < n then
count ← count + getpid();
shared lock(pi );
file access();
shared unlock(pi );
end
if process end( pi ) then
count=count-getpid();
end
end
Algorithm 3: Psuedo code for controller to access file.

6. Consider a modified producer-consumer problem where there are m pro-


ducers and n consumers, where m, n 2; producers and consumers have
unique ids 0 ≤ i ≤ m − 1 and 0 ≤ j ≤ n − 1 respectively. Each producer
has a separate buffer that it fills; when a consumer wants to consume, it
checks the buffers of producers starting from 0, and gets an item from the
first available non-empty buffer. In case all buffers are empty, it sends a
wakeup signal to all producers. If a buffer is full, the relevant producer
sends a wakeup signal to all consumers. A consumer sleeps when all buffers
are empty, and a producer sleeps when its own buffer is full.

8
A. Give na pseudocode (without semaphores or other synchronization
primitives) of the code for producer i, and similar pseudocode for con-
sumer j.

Ans:

Buf f er(i) : value of ith Buffer.


Buf f eri [SIZE] : value of SIZE th slot in i th Buffer.
SIZE :Number of data items in a Buffer.
F U LL :Max size of a Buffer.
while true do
if Buf f er(i) = FULL then
for k ←0 to n − 1 do
wakeup( consumerk );
end
sleep();
end
Buf f eri [IN]← Buf f eri [IN]+item;
IN←(IN+1)MOD SIZE;
if Buf f er(i) = 1 then
for k ←1 to n do
wakeup( consumerk );
end
end
end
Algorithm 4: produceri

9
while true do
for i ←0 to m − 1 do
if Buf f er(i) > 0 then
break;
end
end
if i¿m-1 then
for k ←1 to n do
wakeup(producerk );
end
sleep();
end
Buf f eri [OUT] ← Buf f eri [OUT]-item;
OUT←(OUT+1)MOD SIZE;
if Buf f er(i)=0 then
wakeup(produceri );
end
if Buf f er(i)=FULL-1 then
wakeup(produceri );
end
end
Algorithm 5: consumerj

B. Now carefully analyze all the problems that can occur with the above.
(Note that there are at least three new problems that did not arise with
the single-producer/single-consumer case.) Give a sketch of an improved
solution that addresses these problems.
Ans:
1.when there are m producers and n consumers ,there is a chance that
two producers will produce into the same buffer ,so first updated value will
be lost.hence leads to inconsistency. To control such situation we will as-
sume two Counting semaphore No Empty Buffers and No Full Buffers and
Binary Semaphore mutex . where Counting semaphores , No Empty Buffers
-Number of empty buffers avaliable.assume intially m. No Full Buffers -
Number of Full Buffers Available. assume intially 0.

10
while true do
if Buf f er(i) = FULL then
for k ←0 to n − 1 do
wakeup( consumerk );
end
sleep();
end
down(No Empty Buffers);
down(mutex);
Buf f eri [IN]← Buf f eri [IN]+item;
IN←(IN+1)MOD SIZE;
up(mutex);
up(No Full BUffers);
if Buf f er(i) = 1 then
for k ←1 to n do
wakeup( consumerk );
end
end
end
Algorithm 6: produceri

11
while true do
for i ←0 to m − 1 do
if Buf f er(i) > 0 then
break;
end
end
if i¿m-1 then
for k ←1 to n do
wakeup(producerk );
end
sleep();
end
down(No Full BUffers);
down(mutex);
Buf f eri [OUT] ← Buf f eri [OUT]-item;
OUT←(OUT+1)MOD SIZE;
down(mutex);
down(No Empty Buffers);
if Buf f er(i)=0 then
wakeup(produceri );
end
if Buf f er(i)=FULL-1 then
wakeup(produceri );
end
end
Algorithm 7: consumerj

2.Incorrect Signal to Producers:


Lets us assume a scenario where P1 produced at mth buffer ,now if
C1 takes the chance it starts reading from Zero th postion ,Now while
checking squentially
If the context switch happens at K th Position it will be sent to Block
state. now if another consumer C2 takes the chance , it will consume mth
buffer and if there is a context switch happens when it about to wakeup
all producers ,it will be sent to block state.now if another Producer comes
and produces at location before k.
If again C1 is given chance it will now goes upto mth Buffer and finds
all BUffers are empty,so it will give a wakeup call to all producers.which
is not true since buffer before k is full.
3.Starvation:
If there are more number of Producers(m) and very less no of con-
sumers(2), since the demand by producers cannot be meet by consumers,rate
of producing is not so good compared to rate of consuming,so there is
chance that some buffers will be left behind and never consumed This
leads to starvation.

12

You might also like