Os Assignment-1
Os Assignment-1
Os Assignment-1
– 2nd year
Course requirement of
Subject: OS(Operating Systems)
Assignment
Let us consider following priority order queue 1 > queue 2 > queue 3. According to this
algorithm no process in the batch queue(queue 3) can run unless queue 1 and 2 are
empty. If any batch process (queue 3) is running and any system (queue 1) or Interactive
process(queue 2) enters the ready queue the batch process is preempted.
In this method each queue gets a certain portion of CPU time and can use it to schedule
its own processes.
Now let us suppose that queue 1 and 2 follow round robin with time quantum 4 and 8
respectively and queue 3 follow FCFS. One implementation of MFQS is given below –
1. When a process starts executing then it first enters queue 1.
2. In queue 1 process executes for 4 units and if it completes in this 4 unit or it gives
CPU for I/O operation in this 4 unit then the priority of this process does not change
and if it again comes in the ready queue then it again starts its execution in Queue 1.
3. If a process in queue 1 does not complete in 4 units then its priority gets reduced and
it shifted to queue 2.
4. Above points 2 and 3 are also true for queue 2 processes but the time quantum is 8
unit. In a general case if a process does not complete in a time quantum then it is
shifted to the lower priority queue.
5. In the last queue, processes are scheduled in FCFS manner.
6. A process in lower priority queue can only execute only when higher priority queues
are empty.
7. A process running in the lower priority queue is interrupted by a process arriving in
the higher priority queue.
2)TYPES OF OS
import java.io.*;
class B implements Runnable{
int available = 1 , wanted = 1;
public void run()
{
{
System.out.println("Available = " + available);
if(available>=wanted){
String name = Thread.currentThread().getName();
System.out.println(wanted + " ---> "+ name);
try{
Thread.sleep(100);
available--;
}
catch(InterruptedException ie){ie.printStackTrace();}
}
else {
System.out.println("Not possible");
}
}
}
class A{
public static void main(String args[]) {
B obj = new B();
Thread 1 = new Thread(obj);
Thread 2 = new Thread(obj);
1.start();
2.start();
}
}
There are two types of semaphores they are counting and binary semaphores. Here we use
binary semaphores.
1)Down(Semaphore S){
If(s.value==1)
s.value=0;
else{
Block the process and place its PCB in the suspended list()
}
2)Up(Semaphore S){
else{
wakeup()
}
do {
Down(empty);
Down(mutex);
Up(mutex);
Up(full);
} while(1);
In the above code, mutex, empty and full are semaphores. Here mutex is initialized to 1,
empty is initialized to n (maximum size of the buffer) and full is initialized to 0.
The mutex semaphore ensures mutual exclusion. The empty and full semaphores count the
number of empty and full spaces in the buffer.
After the item is produced, wait operation is carried out on empty. This indicates that the
empty space in the buffer has decreased by 1. Then wait operation is carried out on mutex
so that consumer process cannot interfere.
After the item is put in the buffer, signal operation is carried out on mutex and full. The
former indicates that consumer process can now act and the latter shows that the buffer is
full by 1.
do {
wait(full);
wait(mutex);
signal(mutex);
signal(empty);
. CONSUME ITEM
} while(1);
The wait operation is carried out on full. This indicates that items in the buffer have
decreased by 1. Then wait operation is carried out on mutex so that producer process
cannot interfere.
Then the item is removed from buffer. After that, signal operation is carried out on mutex
and empty. The former indicates that consumer process can now act and the latter shows
that the empty space in the buffer has increased by 1.
The readers-writers problem relates to an object such as a file that is shared between
multiple processes. Some of these processes are readers i.e. they only want to read the data
from the object and some of the processes are writers i.e. they want to write into the
object.
Reader Process
The code that defines the reader process is given below:
wait (mutex);
rc ++;
if (rc == 1)
wait (wrt);
signal(mutex);
.
. READ THE OBJECT
.
wait(mutex);
rc --;
if (rc == 0)
signal (wrt);
signal(mutex);
In the above code, mutex and wrt are semaphores that are initialized to 1. Also, rc is a
variable that is initialized to 0. The mutex semaphore ensures mutual exclusion and wrt
handles the writing mechanism and is common to the reader and writer process code.
The variable rc denotes the number of readers accessing the object. As soon as rc becomes
1, wait operation is used on wrt. This means that a writer cannot access the object anymore.
After the read operation is done, rc is decremented. When rc becomes 0, signal operation is
used on wrt. So a writer can access the object now.
Writer Process
The code that defines the writer process is given below:
wait(wrt);
.
. WRITE INTO THE OBJECT
.
signal(wrt);
If a writer wants to access the object, wait operation is performed on wrt. After that no
other writer can access the object. When a writer is done writing into the object, signal
operation is performed on wrt.
Dining-Philosophers Problem
The Dining-Philosophers Problem Consider five philosophers who spend their lives thinking
and eating. The philosophers share a circular table surrounded by five chairs, each belonging
to one philosopher.
reader process.
do
{
wait (mutex);
readcount++;
if (readcount 1)
wait (wrt);
signal(mutex);
wait(mutex);
readcount--;
if (readcount 0)
signal(wrt);
signal(mutex);
}
while (TRUE);
In the center of the table is a bowl of rice, and the table is laid with five single chopsticks .
When a philosopher thinks, she does not interact with her colleagues. From time to time, a
philosopher gets hungry and tries to pick up the two chopsticks that are closest to her (the
chopsticks that are between her and her left and right neighbors). A philosopher may pick
up only one chopstick at a time. Obviously, she cam1ot pick up a chopstick that is already in
the hand of a neighbor. When a hungry philosopher has both her chopsticks at the same
time, she eats without releasing her chopsticks. When she is finished eating, she puts down
both of her chopsticks and starts thinking again. The dining-philosophers problem is
considered a classic synchronization problem neither because of its practical importance nor
because computer scientists dislike philosophers but because it is an example of a large
class of concurrency-control problems. It is a simple representation of the need to allocate
several resources among several processes in a deadlock-free and starvation-free mam1er.
One simple solution is to represent each chopstick with a semaphore. A philosopher tries to
grab a chopstick by executing await () operation on that semaphore; she releases her
chopsticks by executing the signal() operation on the appropriate semaphores. Thus, the
shared data are semaphore chopstick[5]; where all the elements of chopstick are initialized
to 1. The structure of philosopher i. Although this solution guarantees that no two neighbors
are eating simultaneously, it nevertheless must be rejected because it could create a
deadlock. Suppose that all five philosophers become hungry simultaneously and each grabs
her left chopstick. All the elements of chopstick will now be equal to 0. When each
philosopher tries to grab her right chopstick, she will be delayed forever. Several possible
remedies to the deadlock problem are listed next. Allow at most four philosophers to be
sitting simultaneously at the table.
do
{
wait(chopstick[i]);
wait(chopstick[(i+l) % 5]);
signal(chopstick[i]);
signal(chopstick[(i+l) % 5]);
}
while (TRUE);
Allow a philosopher to pick up her chopsticks only if both chopsticks are available (to do
this, she must pick them up in a critical section). Use an asymmetric solution; that is, an odd
philosopher picks up first her left chopstick and then her right chopstick, whereas an even
philosopher picks up her right chopstick and then her left chopstick we present a solution to
the dining-philosophers problem that ensures freedom from deadlocks. Note, however, that
any satisfactory solution to the dining-philosophers problem must guard against the
possibility that one of the philosophers will starve to death. A deadlock-free solution does
not necessarily eliminate the possibility of starvation.
Lock Variable:
In this mechanism, a Lock variable lock is used. Two values of lock can be possible, either 0
or 1. Lock value 0 means that the critical section is vacant while the lock value 1 means that
it is occupied.
A process which wants to get into the critical section first checks the value of the lock
variable. If it is 0 then it sets the value of lock as 1 and enters into the critical section,
otherwise it waits.
The code for lock variable mechanism:
1. Load Lock, R0
2. CMP R0, #0
3. JNZ Step 1
4. Store #1, Lock
5. Store #0, Lock
Mutual exclusion:
Lock variable mechanism does not satisify mutual exclusion consider two processes P1 and
P2. The process P1 wants to execute its critical section. P1 gets into the entry section. Since
the value of lock is 0 hence P1 changes its value from 0 to 1 and enters into the critical
section.Meanwhile, P1 is preempted by the CPU and P2 gets scheduled. Now there is no
other process in the critical section and the value of lock variable is 0. P2 also wants to
execute its critical section. It enters into the critical section by setting the lock variable to
1.Now, CPU changes P1's state from waiting to running. P1 is yet to finish its critical section.
P1 has already checked the value of lock variable and remembers that its value was 0 when
it previously checked it. Hence, it also enters into the critical section without checking the
updated value of lock variable.Now, we got two processes in the critical section. According
to the condition of mutual exclusion, morethan one process in the critical section must not
be present at the same time.
However, the solution provided in the above segment provides mutual exclusion to some
extent but it doesn't make sure that the mutual exclusion will always be there. There is a
possibility of having more than one process in the critical section.
In order to address the problem, the operating system provides a special instruction called
Test Set Lock (TSL) instruction which simply loads the value of lock variable into the local
register R0 and sets it to 1 simultaneously
The process which executes the TSL first will enter into the critical section and no other
process after that can enter until the first process comes out. No process can execute the
critical section even in the case of preemption of the first process.
The assembly code of the solution will look like following.
1. TSL Lock, R0
2. CMP R0, #0
3. JNZ step 1
Mutual Exclusion
Mutual Exclusion is guaranteed in TSL mechanism since a process can never be preempted
just before setting the lock variable. Only one process can see the lock variable as 0 at a
particular time and that's why, the mutual exclusion is guaranteed.
Progress
According to the definition of the progress, a process which doesn't want to enter in the
critical section should not stop other processes to get into it. In TSL mechanism, a process
will execute the TSL instruction only when it wants to get into the critical section. The value
of the lock will always be 0 if no process doesn't want to enter into the critical section hence
the progress is always guaranteed in TSL.
Bounded Waiting
Bounded Waiting is not guaranteed in TSL. Some process might not get a chance for so long.
We cannot predict for a process that it will definitely get a chance to enter in critical section
after a certain time.
Semaphore:
Semaphore is an integer variable which is used by various processes in a mutually exclusion
manner to achieve synchronization.
There are two types of semaphores
1)counting semaphore
2)binary semaphore
Counting semaphore operations:
1)down operation
Down(semaphore S)
{
s.value=s.value-1;
if(s.value<0)
{
Put process in the suspended state
Sleep();
}
Else
Return
}
2)up operation
Up(semaphore S)
{
s.value=s.value+1;
if(s.value<=0)
{
Select a process from a suspended list()
Wakeup();
}
}
Monitor:
To deal with such errors, researchers have developed high-level language constructs. In this
section, we describe one fundamental high-level synchronization construct-the monitor
type. A monitor type is an ADT which presents a set of programmer-defined operations that
are provided mutual exclusion within the monitor. The monitor type also contains the
declaration of variables whose values define the state of an instance of that type, along with
the bodies of procedures or functions that operate on those variables.
Thus, a procedure defined within a monitor can access only those variables declared locally
within the monitor and its formal parameters. Similarly, the local variables of a monitor can
be accessed by only the local procedures.
procedure P1 ( . . . ) {
procedure P2 ( . . . ) {
}
procedure Pn ( . . . ) {
initialization code ( . . . ) {
}
A programmer who needs to write a tailor-made synchronization
scheme can define one or more variables of type condition:
condition x, y;
The only operations that can be invoked on a condition variable are wait ()
and signal(). The operation
x. wait();
means that the process invoking this operation is suspended until another
process invokes
x. signal();
The x. signal() operation resumes exactly one suspended process. If no
process is suspended, then the signal() operation has no effect; that is, the
state of x is the same as if the operation had never been executed
must wait. Otherwise, both P and Q would be active simultaneously within the
monitor. Note, however, that both processes can conceptually continue with
Signal and wait. P either waits until Q leaves the monitor or waits for
another condition.
Signal and continue. Q either waits until P leaves the monitor or waits