Download presentation
Presentation is loading. Please wait.
Published byShana Hubbard Modified over 9 years ago
1
2.3 interprocess communcation (IPC) (especially via shared memory & controlling access to it)
2
Race conditions ► An error where one process may wait forever or other inconsistencies may result ► Occurs when two or more processes are reading or writing some shared data ► Applies to threads as well ► The final result depends on who runs precisely when ► Difficult to debug and reproduce
3
Critical region/section ► Part of program where shared memory is accessed Must be identified ► mutual exclusion – method to exclude other processes from using a shared variable until our process is finished with it
4
Process cooperation rules: 1. No two processes can be in their critical sections at the same time. 2. Make no timing assumptions. ► My code is faster/shorter; my processor is faster. ► My priority is higher. ► The probability is small for us both processes to do this at the same time. 3. A process should not be blocked from entering a critical region if all other processes are outside the critical region. 4. No process should have to wait forever to get into its critical region.
5
Mutual exclusion w/ busy waiting Methods to implement mutex: 1.Disable interrupts 2.Lock variables 3.Strict alternation 4.Peterson’s solution 5.TSL instruction
6
Mutex method: disable interrupts ► OK for (and used by) OS Consideration with MP systems ► NOT OK for apps
7
Mutex method: lock vars ► Software method ► Single, shared lock variable initially = 0 ► Busy wait spin lock shared int x=0; //wait for lock while (x!=0) ; // note the empty statement x=1; //get lock //critical section … //end critical section x=0; //release lock ► Doesn’t work (w/out hardware support).
8
Mutex method: strict alternation
9
► Software ► Problem: Violates #3. A process can be blocked from entering its C.S. by a process NOT in its C.S. ► In general, a process can’t be in it’s C.S. 2x in a row. ► The 2 processes must be running at about the same speed.
10
Mutex method: Peterson’s soln. (software)
11
Mutex method: TSL instruction ► TSL RX, LOCK RX = register; LOCK = memory location Step 1: read contents of lock into RX Step 2: sets LOCK to 1 Indivisible instruction (non interruptible) Memory, not cache Locks memory bus (so other processors can access/change LOCK) ► IA32 xchg and lock instructions
12
Mutex method: TSL instruction
13
Priority inversion problem ► Unexpected consequence of busy wait ► Given H (a high priority job) and L (low priority job) ► Scheduling: whenever H is ready to run, L is preempted and H is run.
14
Priority inversion problem H runs… H blocks on I/O I/O completes H runs… H attempts to enter C.S. H busy waits forever L is ready to run L runs… L enters C.S…. … L is preempted
15
Using mutex (provided by OS) ► Simpler than semaphore ► Two states: locked or unlocked ► Functions: Declare mutex variable Initialize mutex variable (just once) Lock, C.S., unlock
16
#include #include … pthread_mutex_t mutex; //declare global … //perform this one-time initialization (usually in main) int ret = pthread_mutex_init( &::mutex, NULL ); if (ret) { perror( "main: mutex init error" ); exit(-1); } … //lock in thread code ret = pthread_mutex_lock( &::mutex ); if (ret) { printf( "%d: mutex lock error \n", tp->whoAmI ); } //critical section here //critical section here //unlock in thread code pthread_mutex_unlock( &::mutex );
17
Problem: ► Modify filter program to also determine overall min and max of input data. ► Why do we need a mutex do to this (correctly in a multithreaded app)?
18
(Bounded) producer- consumer problem
19
(Bounded) Producer-consumer problem problems ► Buffer is empty ► Consumer checks count. It’s 0. ► Scheduler interrupts consumer (puts comsumer on ready queue). ► Producer runs. Insert data into buffer. Count is 1 so producer wakes up consumer. But consumer is not asleep (yet)! Producer keeps inserting data into buffer until it’s full. Then producer goes to sleep! ► Scheduler runs consumer. Consumer thinks count=0 so it goes to sleep! ► Both sleep forever!
20
Semaphores ► Types: POSIX ► Shared only among threads only. System V ► Can be shared according to user-group-other. Two basic operations: ► Up – increment the value of the semaphore ► Down – decrement the value of the semaphore
21
Binary semaphores (mutex) ► Create semaphore and initialize it to 1 ► Then down c.s. up
22
POSIX Semaphores #include #include int sem_init ( sem_t *sem, int pshared, unsigned int value ); int sem_wait ( sem_t * sem ); int sem_trywait ( sem_t * sem ); int sem_post ( sem_t * sem ); int sem_getvalue ( sem_t * sem, int * sval ); int sem_destroy ( sem_t * sem );
23
System V Semaphores ► #include ► #include ► int semget ( key_t key, int nsems, int semflg ); create/access existing ► int semctl ( int semid, int semnum, int cmd,... ); delete from system ► int semop ( int semid, struct sembuf *sops, unsigned nsops ); used for up and down
24
Create/access existing //using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) { perror( "semget: " ); perror( "semget: " ); exit( -1 ); exit( -1 );} printf( "sem id=%d \n", sid ); create if necessary system-wide permissions system-wide unique number
25
Access and delete //using the key, get the semaphore id const int sid = semget( mySemKey, 1, 0700 ); if (sid==-1) { perror( "semget: " ); perror( "semget: " ); exit( -1 ); exit( -1 );} printf( "sem id=%d \n", sid ); //delete the semaphore semctl(sid, 0, IPC_RMID, 0);
26
Down function static void down ( const int whichSid ) { struct sembuf sem_lock; struct sembuf sem_lock; sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_flg = 0; //operation flags sem_lock.sem_flg = 0; //operation flags if (semop(whichSid, &sem_lock, 1) == -1) { if (semop(whichSid, &sem_lock, 1) == -1) { perror("semop"); perror("semop"); exit(-1); exit(-1); }}
27
Up function static void up ( const int whichSid ) { struct sembuf sem_unlock; struct sembuf sem_unlock; sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_flg = 0; //operation flags sem_unlock.sem_flg = 0; //operation flags if (semop(whichSid, &sem_unlock, 1) == -1) { if (semop(whichSid, &sem_unlock, 1) == -1) { perror("semop"); perror("semop"); exit(-1); exit(-1); }}
28
Solution to (bounded) producer-consumer problem using semaphores.
29
Shared memory, pipes, and named pipes ► Shared memory shmget shmop shmctl shmat shmdt ► Pipes pipe popen ► Named pipes Mkfifo ► Message queues
30
Other IPC mechanisms: ► Monitors ► Message passing (MPI) ► Barriers
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.