+ All Categories
Home > Documents > S-mp rep FIN

S-mp rep FIN

Date post: 13-Jul-2015
Category:
Upload: shaik-rizwana
View: 50 times
Download: 0 times
Share this document with a friend
Popular Tags:

of 38

Transcript

SYNCHRONIZATION

Shaik.Rizwana Kurra Kaavya

160409737123 160409737122

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING MUFFAKHAM JAH COLLEGE OF ENGINEERING AND TECHNOLOGY (Affiliated to Osmania University) Hyderabad 2011

Mini Project report submitted in partial fulfillment of the requirement for the award of the Degree of B.E By Shaik.Rizwana Kurra Kaavya 160409737123 160409737122

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING MUFFAKHAM JAH COLLEGE OF ENGINEERING AND TECHNOLOGY (Affiliated to Osmania University) Hyderabad 2011

Certificate This is to certify that the project report entitled SYNCRONIZATION being Submitted by Mrs. Shaik.Rizwana and Mrs. Kurra Kaavya in partial fulfillment for the award of the Degree of Bachelor of Engineering in IT to the Osmania University is a record of bonafied work carried out by him under my guidance and supervision.

Dr.A.A.Moiz Qyser. (Head of the Department)

Guide Name M.A.RASHEED Designation B.E.

ACKNOWLEDGEMENT

The present study is on synchronization which has widest applications. The repot work embodied in this project has been carried out under the supervision of project guide Mr.M.A.Rasheed We are grateful to him for giving us an opportunity and encouragement of gaining practical and theoretical knowledge of the project. We respectfully express our indebtness for his encouragement and keen interest shown throughout the project work. We wish to express our deep sense of gratitude to him for guiding us all through the work.

ABSTRACT

A cooperating process is one that can affect or be affect or be affected by other processes executing in the system. Cooperating processes can either directly share a logical address space or be allowed to share data only through files or messages. In this we discuss various mechanisms to ensure the orderly execution of cooperating processes that share a logical address space, so that data consistency is maintained. We developed a model of a system consisting of cooperating sequential processess . We illustrated this model with the Producer Consumer Problem which is representative of operating systems. In the following we explore several more solutions to the critical-section problem using techniques ranging from hardware to software based APIs available to application programmers. We solve it by simply inhibiting interrupts during the time the wait() and signal() operations are executing. This scheme works in a single processor environment because, once interrupts are inhibited, instructions from different processes cannot be interleaved. Some of these mechanisms may result in a situation where processes are waiting indefinitely in a waiting state. This situation is called a deadlock. There are number of different methods that an operating system can use to prevent or deal with deadlocks. We actually discuss about classic problems of synchronization. We solve those problems using semaphores

TABLE OF CONTENTS1) INTRODUCTION OPERATING SYSTEM TYPES 2) PROCESS SYNCHRONIZATION DEAD LOCK 3) SEMOPHORES 4) MUTUAL EXCLUSION SEMOPHORES VS MUTEX CRITICAL SECTION 5) CLASSIC PROBLEMS OF SYNCHRONIZATION 6) DINING PHILOSOPHERS PROBLEM 7) DESCRIPTION OF BANKING ALGORITHM ADVANTAGES 8) PRODUCER CONSUMER PROBLEM 9) SLEEPING BARBER PROBLEM 10) READER-WRITERS PROBLEM 11) CIGARRETTE SMOKERS PROBLEM SOLUTION ANALYSIS 12) SOURCE CODE 13) OUTPUT 14) REFERENCES 3 4 3 4 1

2

5 6 7 8 5

3 4 37

INTRODUCTION

OPERATING SYSTEM:

An operating system (OS) is software, consisting of programs and data that runs on computers and manages the computer hardware and provides common services for efficient execution of various application software. For hardware functions such as input and output and memory allocation, the operating system acts as an intermediary between application programs and the computer hardware, although the application code is usually executed directly by the hardware, but will frequently call the OS or be interrupted by it. Operating systems are found on almost any device that contains a computerfrom cellular phones and video game consoles to supercomputers and web servers.

Types of Operating SystemsThere are several types of operating systems, with Windows, Linux and Macintosh suites being the most widely used. Here is an overview on each system:

Windows: Windows is the popular Microsoft brand preferred by most personal users. This systemhas come a long way from version 1.0 all the way up to the new Windows 7 and soon to be released Windows. Next. Although Windows has made strides in regard to security, it has a reputation for being one of the most vulnerable systems.

UNIX: The UNIX operating system has been around for years, and it is well known for its stability.UNIX is often used more as a server than a workstation and is mostly not used by people due to its steep learning curve.

Linux: Linux is based on the UNIX system, with the source code being a part of GNU open-sourceproject. Both systems are very secure but far more complex than Windows.

Macintosh: Recent versions of the Macintosh operating system, including the Mac OS X, followthe secure architecture of UNIX. Systems developed by Apple are efficient and easy to use, but can only function on Apple branded hardware.

Process Synchronization: Cooperating processes - made possible by multiprogramming, time-sharing, and parallelprocessing. Multiple cooperating processes introduce potential problems - non-determinacy in the computations, deadlocks etc. Race conditions - situations where several processes access and manipulate the same data concurrently, and the outcome of the execution depend on the particular order in which the access takes place. To prevent race condition concurrent processes must be synchronized.

Concurrent processes or threads often need access to shared data and shared resources Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes. Process synchronization refers to the idea that multiple processes are to join up or handshake at a certain point, so as to reach an agreement or commit to a certain sequence of action. Process synchronization or serialization, strictly defined, is the application of particular mechanisms to ensure that two concurrently executing processes do not execute specific portions of a program at the same time. If one process has begun to execute a serialized portion of the program, any other process trying to execute this portion must wait until the first process finishes. Synchronization is used to control access to state both in small-scale multiprocessing systems -- in multithreaded and multiprocessor computers -- and in distributed computers consisting of thousands of units -- in banking and database systems, in web servers, and so on. Process synchronization entails coordination of parallel running threads/ processes to complete a task ensuring correct runtime order. It means that one process must wait for another one to finish its running operation before proceeding. This concept is very important in cases of parallel computing. Synchronization can be categorized as follows: Non-Blocking Synchronization Synchronous Communication Operations Lock/Semaphore Barrier

DeadlockDeadlock refers to a specific condition when two or more processes are each waiting for each other to release a resource, or more than two processes are waiting for resources in a circular chain. Deadlock is a common problem in multiprocessing where many processes share a specific type of mutually exclusive resource known as a software lock or soft lock. Computers intended for the timesharing and/or real-time markets are often equipped with a hard lock which guarantees exclusive access to processes, forcing serialized access. Deadlocks are particularly troubling because there is no general solution to avoid (soft) deadlocks.

Semaphore:Semaphore is a protected variable or abstract data type that constitutes a classic method of controlling access by multiple processes to a common resource in a parallel programming environment. A semaphore generally takes one of two forms: binary and counting. A binary semaphore can range only between 0 and 1. It is also known as Mutex locks as they are locks that provide mutual exclusion. A counting semaphore is a counter for a set of resources. Semaphores are accessed using the operations wait( ) and signal( ). Implementation of Semaphore: procedure V (S : Semaphore); begin (* Atomic operation: increment the semaphore. *) S := S + 1; end; (* Atomic operation: decrement the semaphore. *) procedure P (S : Semaphore); begin (* Whole operation is atomic *) repeat Wait(); until S > 0; S := S - 1; end;

The value of the semaphore S is the number of units of the resource that have not been claimed. If there is only one such resource, a binary semaphore is used as a simple "true/false" flag. The P operation wastes time or sleeps until a resource controlled by the semaphore becomes available, at which time the resource is immediately claimed. The V operation is the inverse: it makes a resource available again after the process has finished using it. To avoid starvation, a semaphore may have an associated queue of processes (usually a first-in, first out). If a process performs a P operation on a semaphore that has the value zero, the process is added to the semaphore's queue. When another process increments the semaphore by performing a V operation, and there are processes on the queue, one of them is removed from the queue and resumes execution. When processes have different priorities the queue may be ordered by priority, so that the highest priority process is taken from the queue first. To guarantee that two or more processes do not attempt to simultaneously modify the same semaphore, the operations that actually increment or decrement the semaphore are designated as atomic, meaning they cannot be interrupted, such as by preemption. This requirement may be met by using a machine instruction that is able to read, modify and write the semaphore in a single operation. In the absence of such a hardware instruction, an atomic operation may be synthesized by temporarily suspending preemption or, less desirably, by temporarily disabling hardware interrupts.

Mutual Exclusion:Mutual exclusion (also called mutex) algorithms are used in concurrent programming to avoid the simultaneous use of a common resource, such as a global variable, by pieces of computer code called critical sections. A critical section is a piece of code in which a process or thread accesses a common resource. The critical section by itself is not a mechanism or algorithm for mutual exclusion. A program, process, or thread can have the critical section in it without any mechanism or algorithm which implements mutual exclusion.

Semaphore vs. Mutex Mutexes are typically used to serialize access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Critical SectionIn concurrent programming a critical section is a piece of code that accesses a shared resource (data structure or device) that must not be concurrently accessed by more than one thread of execution. A critical section will usually terminate in fixed time, and a thread, task or process will have to wait a fixed time to enter it (bounded waiting). Some synchronization mechanism is required at the entry and exit of the critical section to ensure exclusive use. By carefully controlling which variables are modified inside and outside the critical section usually, by accessing important state only from within, concurrent access to that state is prevented. A critical section is typically used when a multithreaded program must update multiple related variables without a separate thread making conflicting changes to that data. In a related situation, a critical section may be used to ensure a shared resource, for example a printer, can only be accessed by one process at a time. It can be summarized as: It is a set of instructions that must be controlled so as to allow exclusive access to one process The execution of the critical section by processes is mutually exclusive in time General Structure: repeat critical section

remainder section until FALSE

Solution to the Critical Section Problem must meet three conditions...1.

Mutual Exclusion: If a process is executing in its critical section, no other process is

executing in its critical section. 2. Progress: If no process is executing in its critical section and there exists some processes that wish to enter their critical sections, then only those processes that are not executing in their remainder section can participate in the decision of which will enter its critical section next, and this decision cannot be postponed indefinitely o if no process is in critical section, can decide quickly who enters o only one process can enter the critical section so in practice, others are put on the queue 3. Bounded Waiting: There must exist a bound on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted

PROBLEMS OF PROCESS SYNCHRONISATIONTo better understand what kind of process synchronization is necessary to avoid race conditions, models of synchronization problems are used. Each model depicts a particular scenario of concurrent execution and presents particular requirements on process synchronization. The problems discussed below are as follows:

Banking Algorithm. Dining Philosophers Problem. Producer Consumer Problem. Sleeping Barbers Problem. Cigarette Smokers Problem. Readers Writers problem.

DINING PHILOSOPHERS PROBLEMDining philosophers problem is an illustrative example of a common computing problem in concurrency. It is a classic multi-process synchronization problem. In 1965, Edsger Dijkstra set an examination question on a synchronization problem where five computers competed for access to five shared tape drive peripherals. Soon afterwards the problem was retold by Tony Hoare as the dining philosophers problem. This is a theoretical explanation of deadlock and resource starvation by assuming that each philosopher takes a different fork as a first priority and then looks for another. The goal of the problem is to create a program that simulates the behavior of 5 philosophers gathered around a table to think and eat. Each philosopher thinks for a while, then eats then thinks again, and so on, independently of the others. Each philosopher has one fork, but needs two forks to eat. Thus

the philosophers decide to share their forks. When a philosopher wants to eat, he takes the fork on his left, when it is available, then the fork on his right, eats, and then puts both forks back.

After the philosophers have thought and eaten several times, it may happen that all philosophers simultaneously decide to eat. They take their left fork, and find the right fork already taken by their right neighbor. In this case, if nothing has been foreseen, the philosophers will stay in that situation (deadlock) indefinitely. The program should avoid that situation. The dining philosophers problem is sometimes explained using rice and chopsticks rather than spaghetti and forks, as it is more intuitively obvious that two chopsticks are required to begin eating. The philosophers never speak to each other, which create a dangerous possibility of deadlock when every philosopher holds a left fork and waits perpetually for a right fork (or vice versa). Originally used as a means of illustrating the problem of deadlock, this system reaches deadlock when there is a 'cycle of unwarranted requests'. In this case philosopher P1 waits for the fork grabbed by philosopher P2 who is waiting for the fork of philosopher P3 and so forth, making a circular chain. Starvation might also occur independently of deadlock if a philosopher is unable to acquire both forks because of a timing problem. . If all five philosophers appear in the dining room at exactly the same time and each picks up the left fork at the same time the philosophers will wait five minutes until they all put their forks down and then wait a further five minutes before they all pick them up again.

In general the dining philosophers problem is a generic and abstract problem used for explaining various issues which arise in problems which hold mutual exclusion as a core idea. The various kinds of failures these philosophers may experience are analogous to the difficulties that arise in real computer programming when multiple programs need exclusive access to shared resources. These issues are studied in the branch of Concurrent Programming. The original problems of Dijkstra were related to external devices like tape drives. However, the difficulties studied in the Dining Philosophers problem arise far more often when multiple processes access sets of data that are being updated. Systems that must deal with a large number of parallel processes, such as operating system kernels, use thousands of locks and synchronizations that require strict adherence to methods and protocols if such problems as deadlock, starvation, or data corruption are to be avoided

DESCRIPTION OF BANKERS ALGORITHMThe Banker's algorithm is a resource allocation & deadlock avoidance algorithm developed by Edsger Dijkstra that tests for safety by simulating the allocation of pre-determined maximum possible amounts of all resources, and then makes a "safe-state" check to test for possible deadlock conditions for all other pending activities, before deciding whether allocation should be allowed to continue.The algorithm was developed in the design process for the operating system and originally described (in Dutch) . T he name is by analogy with the way that bankers account for liquidity constraints.

ALGORITHMThe Banker's algorithm is run by the operating system whenever a process requests resources. The algorithm prevents deadlock by denying or postponing the request if it determines that accepting the request could put the system in an unsafe state When a new process enters a system, it must declare the maximum number of instances of each resource type that may not exceed the total number of resources in the system.

ALLOWS mutual exclusion, wait and hold, no preemption. PREVENTS circular wait

PRODUCER CONSUMER PROBLEMThe producer-consumer problem also known as the bounded-buffer problem is a classical example of a multi-process synchronization problem.. At the same time the consumer is consuming the data (i.e. removing it from the buffer) one piece at a time. The problem is to make sure that the producer won't try to add data into the buffer if it's full and that the consumer won't try to remove data from an empty buffer. The solution for the producer is to either go to sleep or discard data if the buffer is full. The next time the consumer removes an item from the buffer, it notifies the producer who starts to fill the buffer again. In the same way, the consumer can go to sleep if it finds the buffer to be empty. The next time the producer puts data into the buffer, it wakes up the sleeping consumer. The solution can be reached by means of inter-process communication, typically using semaphores. An inadequate solution could result in a deadlock where both processes are waiting to be awakened. The problem can also be generalized to have multiple producers and consumers.

Flow chart

While(true) { While(counter==BUFFER-SIZZE); /*produce an item in next Produced*/ Buffer[in]=nextProduced; In=(in+1)%BUFFER_SIZE; COUNTER++; } Fig The code for the producer process.

While(true) { While(counter==BUFFER-SIZZE); NextConsumed= Buffer[out]; out=(out+1)%BUFFER_SIZE; COUNTER--; } Fig The code for the consumer process

SLEEPING BARBER PROBLEMThe sleeping barber problem is a classic inter-process communication and synchronization problem between multiple operating system processes. The problem is analogous to that of keeping a barber working when there are customers, resting when there are none and doing so in an orderly manner. The barber and his customers represent aforementioned processes. The analogy is based upon a hypothetical barber shop with one barber. The barber has one barber chair and a waiting room with a number of chairs in it. When the barber finishes cutting a customer's hair, he dismisses the customer and then goes to the waiting room to see if there are other customers waiting. If there are, he brings one of them back to the chair and cuts his or her hair. If there are no other customers waiting, he returns to his chair and sleeps in it. Each customer, when he arrives, looks to see what the barber is doing. If the barber is sleeping, then he wakes him up and sits in the chair. If the barber is cutting hair, then he goes to the waiting room. If there is a free chair in the waiting room, he sits in it and waits his turn. If there is no free chair, then the customer leaves. On a naive analysis, the above description should ensure that the shop functions correctly, with the barber cutting hair of anyone who arrives until there are no more customers, and then sleeping until the next customer arrives. In practice there are a number of problems that can occur, which are illustrative of general scheduling problems.

The problems are all related to the fact that the actions by both the barber and the customer (checking the waiting room, entering the shop, taking a waiting room chair etc.) all take an unknown amount of time. The problems are all related to the fact that the actions by both the barber and the customer (checking the waiting room, entering the shop, taking a waiting room chair etc.) all take an unknown amount of time. For example, a customer may arrive and observe that the barber is cutting hair, so he goes to the waiting room. While he is on his way, the barber finishes the haircut he is doing and goes to check the waiting room. Since there is no-one there, (the customer hasn't arrived yet) he goes back to his chair and sleeps. The barber is now waiting for a customer and the customer is waiting for the barber. In another example, two customers may arrive at the same time, observe that the barber is cutting hair and there is a single seat in the waiting room, and go to the waiting room. They will both then attempt to occupy the single chair. The Sleeping Barber Problem is often attributed to Edsger Dijkstra (1965), one of the pioneers in fundamental programming

SOLUTIONFlow chart Many example solutions are available. The key element of all is a mutex, which ensures that only one of the participants can change state at once. The barber must acquire this mutex before checking for customers (releasing it when he either begins to sleep or begins to cut hair), and a customer must acquire it before entering the shop (releasing it when he has sat in either a waiting room chair or the barber chair). This eliminates both of the problems mentioned above. A number of semaphores are also necessary to indicate the state of the system; for example, storing the number of people in the waiting room and the number of people the barber is cutting the hair off.

THE READERS-WRITERS PROBLEMThe simplest one requires that no reader will be kept waiting unless a writer has already obtained permission to use the shared object. IN other words, no reader should wait for other readers to finish simply because a writer is waiting. The second requires that, one a writer is ready, that writer performs its write as soon as possible. In other words, if a writer is waiting to access the object, no new readers may start reading do { Wait(wrt); .. // writing is performed .. Signal(wrt); } While (TRUE); Fig The structure of a writer process do { wait (mutex); readcount++; if(readcount==1) wait(wrt); signal(mutex); // reading is performed Wait(mutex); Readcount--; if(readcount==0) signal(wrt); signal(mutex); } While(TRUE); Fig The structure of a reader process.

The Cigarette Smokers ProblemThis is a concurrency problem described by S. S. Patil in 1971. Suppose a cigarette requires three ingredients, tobacco, paper and match. There are three chain smokers. Each of them has only one ingredient with infinite supply. There is an agent who has infinite supply of all three ingredients. To make a cigarette, the smoker has tobacco must have the other two ingredients paper and match. The agent and smokers share a table. The agent randomly generates two ingredients and notifies the smoker who needs these two ingredients. Once the ingredients are taken from the table, the agent supplies another two. On the other hand, each smoker waits for the agent's notification. Once it is notified, the smoker picks up the ingredients, makes a cigarette, smokes for a while, and goes back to the table waiting for his next ingredients.

SolutionThe cigarette smokers problem becomes solvable using binary semaphores, or mutexes. Let us define an array of binary semaphores A, one for each smoker; and a binary semaphore for the table, T. Initialize the smokers' semaphores to zero and the table's semaphore to 1. The code is:

while true { wait(T); choose smokers i and j non deterministically, making the third smoker k; signal(A[k]); } and the code for smoker i is while true { wait (A[i]); make a cigarette signal (T); smoke the cigarette; }

AnalysisBelow is the diagram that details all activities of the agent and a smoker. The red squares and green circles are used to represent semaphore waits and signals respectively. The table is a shared object, because the agent puts ingredients on the table and smokers take ingredients from the table. Therefore, some protection is necessary to avoid race condition. A mutex lock simply does not work, because with a lock the owner must unlock the lock which is not the case here. The agent waits for the table to become available, and then puts ingredients on the table. If we use a mutex lock, the agent must unlock the table, and if the agent is a fast runner he may come back and lock the table again to make another set of ingredient before the previous ones are taken. Thus, we have a race condition. Thus, we use a semaphore with which the thread that executes a wait to lock the semaphore and the thread that executes a signal to unlock the semaphore do not have to be the same.

Flow chart When the table is available, the agent puts ingredient on the table. Of course, the agent knows what ingredients are on the table, and, hence, signals the smoker that needs this set of ingredients. On the other hand, a smoker cannot continue if he has no ingredients. To this end, we need another semaphore to block a smoker. In fact, we need three semaphores, one for each smoker. For example, if the agent puts paper and match on the table, he must inform the smoker who needs paper and match to continue. Therefore, the smoker who needs paper and match must wait on this semaphore. The meaning of the above diagram is clear. The agent prepares for the ingredients, waits on the table and makes the ingredients available on the table when it becomes available, signals the proper smoker to take the ingredient, and then goes back for another round. For a smoker, he waits for the ingredients he needs, takes them when they are available, informs the agent that the table is free, makes a cigarette and smokes, and goes back for another round. Here the table is not protected with a lock. Instead, it is protected through notification.

PROGRAM DINING PHILOSOPHERS PROBLEM#include #include #include #include #include #include "msecond.h" #include "random_int.h" #define NUM_PHILOSOPHERS 5 #define MEAN_THINK_TIME #define MEAN_EAT_TIME float total_time_spent_waiting = 0.0; int total_number_of_meals = 0; #define semaphore_create(s,v) sem_init( &s, 0, v ) #define semaphore_wait(s) sem_wait( &s ) #define semaphore_signal(s) sem_post( &s ) #define semaphore_release(s)sem_destroy( &s ) typedef sem_t semaphore; semaphore chopstick[NUM_PHILOSOPHERS]; semaphore screen; semaphore mutex; int screen_row[NUM_PHILOSOPHERS] = { 6, 2, 2, 6, 10 }; int screen_col[NUM_PHILOSOPHERS] = { 31, 36, 44, 49, 40 }; int chopstick_row[5] = { 9, 4, 3, 4, 9 }; int chopstick_col[5] = { 35, 33, 40, 47, 45 }; char chopstick_sym[5] = { '/', '\\', '|', '/', '\\' }; #define cls() printf( "\033[H\033[J" ) #define position(row,col) printf( "\033[%d;%dH", (row), (col) ) #define position_flush(row,col) printf( "\033[%d;%dH\n", (row), (col) ) void init_screen( void ) { int i; cls(); position( 6, 37 ); printf( "\\ /" ); position( 7, 38 ); printf( "\\___/" ); for ( i = 0; i < NUM_PHILOSOPHERS; i++ ) { position( screen_row[i], screen_col[i] ); printf( "%d", i ); position( screen_row[i] + 1, screen_col[i] - 1 );

printf( "(%d)", 0 ); position( chopstick_row[i], chopstick_col[i] ); printf( "%c", chopstick_sym[i] ); } position_flush( 13, 1 ); } void draw_thinking( int n ) { semaphore_wait( screen ); position( screen_row[n], screen_col[n] ); printf( "\033[33mT\033[0m" ); position_flush( 13, 1 ); semaphore_signal( screen ); } void draw_hungry( int n ) semaphore_wait( screen ); position( screen_row[n], screen_col[n] ); printf( "\033[34mH\033[0m" ); position_flush( 13, 1 ); semaphore_signal( screen ); } void draw_eating( int n, int eat_count ) { semaphore_wait( screen ); position( screen_row[n], screen_col[n] ); printf( "\033[31mE\033[0m" ); position( screen_row[n] + 1, screen_col[n] - 1 ); printf( "(%d)", eat_count ); position_flush( 13, 1 ); semaphore_signal( screen ); } void draw_chopstick_up( int n ) { semaphore_wait( screen ); position( chopstick_row[n], chopstick_col[n] ); printf( "%c", ' ' ); position_flush( 13, 1 ); semaphore_signal( screen ); } void draw_chopstick_down( int n ) { semaphore_wait( screen ); position( chopstick_row[n], chopstick_col[n] ); printf( "\033[32m%c\033[0m", chopstick_sym[n] ); position_flush( 13, 1 ); semaphore_signal( screen );

} void draw_done( int n ) { semaphore_wait( screen ); position( screen_row[n], screen_col[n] ); printf( "D" ); position_flush( 13, 1 ); semaphore_signal( screen ); } void obtain_chopsticks( int n ) { if ( n % 2 == 0 ) { /* Even number: Left, then right */ semaphore_wait( chopstick[(n+1) % NUM_PHILOSOPHERS] ); draw_chopstick_up( (n+1) % NUM_PHILOSOPHERS ); semaphore_wait( chopstick[n] ); draw_chopstick_up( n ); } else { /* Odd number: Right, then left */ semaphore_wait( chopstick[n] ); draw_chopstick_up( n ); semaphore_wait( chopstick[(n+1) % NUM_PHILOSOPHERS] ); draw_chopstick_up( (n+1) % NUM_PHILOSOPHERS ); } } void release_chopsticks( int n ) { draw_chopstick_down( n ); semaphore_signal( chopstick[n] ); draw_chopstick_down( (n+1) % NUM_PHILOSOPHERS ); semaphore_signal( chopstick[(n+1) % NUM_PHILOSOPHERS] ); } void philosopher( int *philosopher_data ) { int start_time; int eat_count = 0; int total_hungry_time = 0; int became_hungry_time; int n = philosopher_data[0]; int duration = philosopher_data[1]; start_time = msecond(); while( msecond() - start_time < duration * 1000 ) { became_hungry_time = msecond(); draw_hungry( n ); obtain_chopsticks( n );

total_hungry_time += ( msecond() - became_hungry_time ); eat_count++; draw_eating( n, eat_count ); usleep( 1000L * random_int( MEAN_EAT_TIME ) ); /* microseconds */ release_chopsticks( n ); draw_thinking( n ); usleep( 1000L * random_int( MEAN_THINK_TIME ) );/* microseconds */ } draw_done( n ); semaphore_wait( mutex ); total_number_of_meals += eat_count; total_time_spent_waiting += ( total_hungry_time / 1000.0 ); semaphore_signal( mutex ); pthread_exit( NULL ); } int main( int argc, char *argv[] ) { pthread_t phil[NUM_PHILOSOPHERS]; int philosopher_data[NUM_PHILOSOPHERS][2]; int duration; int i; duration = ( argc > 1 ? atoi( argv[1] ) : 10 ); for ( i = 0; i < NUM_PHILOSOPHERS; i++ ) { if ( semaphore_create( chopstick[i], 1 ) < 0 ) { fprintf( stderr, "cannot create chopstick semaphore\n" ); exit( 1 ); } } init_screen(); for ( i = 0; i < NUM_PHILOSOPHERS; i++ ) { philosopher_data[i][0] = i; philosopher_data[i][1] = duration; if ( pthread_create( &phil[i], NULL, (void *(*)(void *)) &philosopher, &philosopher_data[i] ) != 0 ) { fprintf( stderr, "cannot create thread for philosopher %d\n", i ); exit( 1 ); } } for ( i = 0; i < NUM_PHILOSOPHERS; i++ ) { pthread_join( phil[i], NULL ); } for ( i = 0; i < NUM_PHILOSOPHERS; i++ )

{ semaphore_release( chopstick[i] ); } semaphore_release( screen ); semaphore_release( mutex ); position( 13, 1 ); printf( "Total meals served = %d\n", total_number_of_meals ); printf( "Average hungry time = %f\n", total_time_spent_waiting / total_number_of_meals ); return 0; }

OUTPUT:

PRODUCER CONSUMER PROBLEM#include #include #include #include #define RAND_DIVISOR 100000000 #define TRUE 1 #define BUFFER_SIZE 5 typedef int buffer_item; pthread_mutex_t mutex; sem_t full, empty; buffer_item buffer[BUFFER_SIZE]; int counter; pthread_t tid; pthread_attr_t attr; void *producer(void *param); void *consumer(void *param); void initializeData() { pthread_mutex_init(&mutex, NULL); sem_init(&full, 0, 0); sem_init(&empty, 0, BUFFER_SIZE); pthread_attr_init(&attr); counter = 0; } void *producer(void *param) { buffer_item item; while(TRUE) { int rNum = rand() / RAND_DIVISOR; sleep(rNum); item = rand(); sem_wait(&empty); pthread_mutex_lock(&mutex); if(insert_item(item)) { fprintf(stderr, " Producer report error condition\n"); } else { printf("producer produced %d\n", item); } pthread_mutex_unlock(&mutex); sem_post(&full); } } void *consumer(void *param) { buffer_item item;

while(TRUE) { int rNum = rand() / RAND_DIVISOR; sleep(rNum); sem_wait(&full); pthread_mutex_lock(&mutex); if(remove_item(&item)) { fprintf(stderr, "Consumer report error condition\n"); } } } int insert_item(buffer_item item) { if(counter < BUFFER_SIZE) { buffer[counter] = item; counter++; return 0; } else { return -1; } } int remove_item(buffer_item *item) { if(counter > 0) { *item = buffer[(counter-1)]; counter--; return 0; } else { return -1; } } int main(int argc, char *argv[]) { int i, mainSleepTime, numProd, numCons; if ( argc != 4 ) { mainSleepTime = 10; numProd = 10; numCons = 10; } else { mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */ numProd = atoi(argv[2]); /* Number of producer threads */ numCons = atoi(argv[3]); /* Number of consumer threads */ } initializeData();

for(i = 0; i < numProd; i++) { pthread_create(&tid,&attr,producer,NULL); } for(i = 0; i < numCons; i++) { pthread_create(&tid,&attr,consumer,NULL); } sleep(mainSleepTime); printf("Exit the program\n"); exit(0); } /* msecond.h */ #ifndef __MSECOND_H__ #define __MSECOND_H__ #ifdef __cplusplus extern "C" { #endif int msecond( void ); #ifdef __cplusplus } #endif #endif /* msecond.c */ #include #include #include int msecond( void ) { static clock_t start = (clock_t) 0; struct tms buf; if ( start == (clock_t) 0 ) { start = times( &buf ); /* First time */ return 0; } else { return (int) ( ( 1000 / HZ ) * ( times( &buf ) - start ) ); } } /* random_int.c */ { if ( seed < 0 ) { seed = (int) time( (time_t *) 0 ); } srandom( seed );

initialized++; int random_int( int mean ) { double u; int value; if ( !initialized ) { init_random_int( -1 ); } value = (int) ( 0.5 - mean * log( u ) ); if ( value == 0 ) { value = 1; } else if ( value > 5 * mean ) { value = 5 * mean; } return value; } /*random_int.h */ #ifndef __RANDOM_INT_H__ #define __RANDOM_INT_H__ #ifdef __cplusplus extern "C" { #endif void init_random_int( int seed ); int random_int( int mean ); #ifdef __cplusplus } #endif #endif

CIGARETTE SMOKERS PROBLEM#include #include #include enum Ingredients { None, Paper, Tobacco, Matches }; typedef struct smoker { char SmokerID[25]; int Item; } SMOKER; typedef struct agent { char AgentID[25]; int Item1; int Item2; } AGENT; char* GetIngredientName(int Item) { if (Item == Paper) return "Paper"; else if(Item == Tobacco) return "Tobacco"; else if(Item == Matches) return "Matches"; } void GetAgentIngredients(AGENT* agent) { agent->Item1=random()%3+1; while(1) { agent->Item2=random()%3+1; if (agent->Item1 != agent->Item2) break; }

printf("\nAgent Provides Ingredients- %s,%s\n\n:", GetIngredientName(agent->Item1), GetIngredientName(agent->Item2)); } void GiveIngredientToSmoker(AGENT*agent,SMOKER* smoker) { int index=0; while(smoker[index].Item !=NULL) { if((smoker[index].Item !=agent->Item1)&&(smoker[index].Item != agent>Item2)) { printf("\nSmoker - \%s\"-is smoking his cigarette\n\n", smoker[index].SmokerID); agent->Item1=None; agent->Item2=None; break; } index++; } } int main() { AGENT agent; SMOKER smoker[4] = {{"SmokerWithPaper",Paper}, {"SmokerWithTobacco",Tobacco}, {"SmokerWithMatches",Matches},{"\0",None}}; int userChoice=0; strcpy(agent.AgentID,"Agent"); agent.Item1=None; agent.Item2=None; while(1) { GetAgentIngredients(&agent); GiveIngredientToSmoker(&agent,smoker); printf("Press ESC to exit or any key to continue\n\n"); userChoice=getchar(); if (userChoice ==27) break; } return 0; }

OUTPUT:

SLEEPING BARBERS PROBLEM

#include #include #include #include #include #include #include #define N 6 time_t end_time;/*end time*/ sem_t mutex,customers,barbers;/*Three semaphors*/ int count=0; void barber(void *arg); void customer(void *arg); int main(int argc,char *argv[]) { pthread_t id1,id2; int status=0; end_time=time(NULL)+20; printf("**** Shop Open ****\n"); sem_init(&mutex,0,1); sem_init(&customers,0,0); sem_init(&barbers,0,1); status=pthread_create(&id1,NULL,(void *(*)(void*))barber,NULL); if (status!=0) perror("create barbers is failure!\n"); status=pthread_create(&id2,NULL,(void *(*)(void*))customer,NULL); if(status!=0) perror("create customers is failure!\n"); pthread_join(id2,NULL); pthread_join(id1,NULL); printf("\n**** SHOP CLOSED ****\n"); exit(0); } void barber(void *arg)/*Barber Process*/ { while(time(NULL)0) { sem_wait(&customers); sem_wait(&mutex); count --; printf("Barber cuts hair, total customers: %d\n", count); (!count) printf("No customers in shop, Barber is sleeping.\n\n"); sem_post(&mutex); sem_post(&barbers); sleep(3); }

if

} void customer(void *arg) { while(time(NULL)


Recommended