You are on page 1of 7

ASSIGNMENT-3 REPORT

OPERATING SYSTEMS-2
AMITANSHU SAHOO
ME18BTECH11050

IMPORTANT CONCEPTS
The assignment deals with the concept of three mutual exclusion algorithm to deal with
the problem of critical section.
Critical Section – It is the part of the code where the process may be accessing and
updating data that is shared with at least one other process.
The critical section problem is to design an algorithm to synchronize the access to this
part of the code ensuring that no two process access the critical section at the same
time.
Entry Section – It is the section of the code which implements the algorithm to
synchronize the entry to the critical section.
Exit Section – It is the part of the code where the critical section gets over and the
algorithm permits other process to enter the critical section.
Remainder Section – This is the section of the code that does not include the critical
section. In this section the processes do not access any shared data.
A solution to the critical section problem must satisfy the following three conditions: -
• Mutual Exclusion – Only a single process can be present within the critical
section at a given point of time.
• Progress - If no process is executing the critical section and some process wishes
to enter the area then only the process which are not executing in the reminder
section can participate in deciding which will enter its critical section next and
this selection cannot be postponed indefinitely.
• Bounded Waiting – There exists a bound to the number of process that can enter
the critical section after a certain process has made to request to enter the
critical section. In this way it is assured that none of the processes are starving.
Structure Used: -
• Struct t_data – This struct carries three information into the thread. The ID of the
thread, sleep time t1 and sleep time t2 which are exponential distributed.

Function Used: -
• void* CS_test () – This is the function that implements the critical section of the
code. It is used as the runner function for each of the thread. The structure t_data
is passed as argument to this thread.
• Convert_to_1D () - fstream is not synchronized in C++, so 2 processes can
attempt to edit a file at the same time. The resultant output will be garbage value
stored in the file. To deal with the problem, the outputs from the CS_test function
are written to a global 2D array such that the areas of the areas of the array are
accessed by a unique process indexed by the thread ID.
The 2D array is converted into a 1D array after the all the threads are executed
using this function. The 1D array is sorted according to time stamp and a master
array containing the output in the order of the timestamp are printed to the file.
• Insertion_sort () - This is a simple insertion sort algorithm which sorts the 1D
array of file output strings according to corresponding time stamp array.
• Merge () - The sorted arrays are merged, and a master log file array is made
which is printed to the file output.

Arrays Used –
• String log_file_req [50][10] –It procures all the request statements for all the
threads across k iterations.
• String log_file_ent [50][10] - It procures all the entry statements for all the
threads across k iterations.
• String log_file_ext [50][10] – It procures all the exit statements for all the threads
across k iterations.
• Double req_time [50][10] – It procures all the request timestamps for all the
threads across k iterations.
• Double ent_time [50][10] – It procures all the entry timestamps for all the
threads across k iterations.
• Double ext_time [50][10] – It procures all the exit timestamps for all the threads
across k iterations.
• Double waiting_time [50] – It stores the sum of waiting times for all the threads
looping over the k requests.
• Double worst_case [50] – Its stores the worst-case waiting time for each thread.
• Double master_req_time [500] – It stores the request time of all threads across k
iterations in a 1D manner.
• Double master_ent_time [500] – It stores the entry time of all threads across k
iterations in a 1D manner.
• Double master_ext_time [500] – It stores the exit time of all threads across k
iterations in a 1D manner.
• String master_req_string [500] – It stores the request statements of all threads
across k iterations in a 1D manner.
• String master_ent_string [500] - It stores the entry statements of all threads
across k iterations in a 1D manner.
• String master_ext_string [500] - It stores the exit statements of all threads across
k iterations in a 1D manner.
• Double master_log_time [1500] – It is the master array that contains the sorted
time_stamps of all the statements.
• String master_log_file [1500] – It is the master array of strings which is sorted
according to time stamps. This array is written to the output file.

General Code Flow Across All Algorithms: -


1. We first initialize all 2D arrays, waiting_time array and the worst_case array
globally.
2. We initialize timeval struct instances to store the timestamps globally and define
structures and function as described above.
3. In the main program, at the starting, we store the starting time of the program.
All the statement times are referenced from this starting time of the program in
milliseconds.
4. We then input the values of number of threads, k, lambda1 and lambda2 from
the input file.
5. Using lambda1 and lambda2 we initiate sleep times for all the threads using
exponential distribution.
6. After this we call the threads with the CS_test function and its arguments.
7. After all the threads are executed the 2D array are converted into 1D array, they
are sorted and merged to make the logfile to be printed to the output file.
8. The arrays of waiting time and worst_case is used to compute the average
waiting time of the processes and the worst_case waiting time which are printed
to the window.
TAS
The algorithm: -
I leverage the C++ atomic library to use the TAS algorithm. The algorithm as is used in
the code is given as follows: -
For each of the k iterations {
********** entry section **********
While (lock.test_and_set ());
**********critical section**********
**********exit_section**********
Lock.clear()
**********remainder section**********
}

CAS
The algorithm: -
I leverage the C++ atomic library to use the CAS algorithm. The algorithm as is used in
the code is given as follows: -
For each of the k iterations {
********** entry section **********
While (! atomic_compare_exchange_strong (&lock, &expected,1)) {
Expected = 0;
}
**********critical section**********
**********exit_section**********
Lock = 0;
**********remainder section**********
}
CAS-Bounded
I leverage the C++ atomic library to use the CAS-Bounded algorithm. The algorithm as
is used in the code is given as follows: -
For each of the k iterations {
********** entry section **********
Waiting [ID] = true;
Int key = 1;
While () {
Key =! atomic_compare_exchange_strong(&lock, &expected,1);
Expected = 0;

}
Waiting [ID] = false;
**********critical section**********
**********exit_section**********
Int j = (data->ID + 1) %num_threads;
While ((j!= data->ID) && !waiting[j]){
j = (j+1) %num_threads;
}
If (j == data->ID) {
Lock = 0.
}
Else {
Waiting[j] = false.
}
**********remainder section**********
}
Graphical Analysis
All the graphical analysis is done by taking the data points which are average over five
runs of the algorithms with lambda1 = 5 and lambda2 = 10.

Average Waiting Time: -

1. As we can see from the graph, the performance of TAS is worst for number of
processes between 20 to 40. TAS is performing well at higher number of
processes.
2. CAS has the least average waiting time, and its performance becomes equivalent
to TAS at the high number of processes.
3. The CAS_Bounded algorithm average waiting time lies somewhat in the middle of
the two algorithms and tends to perform worst around 40-50 processes
segment.
Average Worst Case Time: -

1. As can be clearly observed, due to the bounded waiting time nature of the CAS-
Bounded algorithm it performs the best at having the lowest worst case waiting
time.
2. TAS shows somewhat same nature as the previous graph performing worst
among all.
3. CAS lies in the middle with its performance becoming equivalent to TAS at the
higher number of processes end.

You might also like