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

Lab 10 PDF

This document discusses semaphores and how they can be used to synchronize processes that access shared memory. It describes how race conditions can occur when processes manipulate shared data concurrently. Semaphores provide a way to establish ordering between events and mutually exclusive access to resources. The key system calls for initializing, locking, unlocking and destroying unnamed POSIX semaphores placed in shared memory are sem_init(), sem_wait(), sem_post() and sem_destroy(). An example is provided of using a semaphore to synchronize a parent and child process accessing shared data.

Uploaded by

Muddassir Ahmed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
108 views

Lab 10 PDF

This document discusses semaphores and how they can be used to synchronize processes that access shared memory. It describes how race conditions can occur when processes manipulate shared data concurrently. Semaphores provide a way to establish ordering between events and mutually exclusive access to resources. The key system calls for initializing, locking, unlocking and destroying unnamed POSIX semaphores placed in shared memory are sem_init(), sem_wait(), sem_post() and sem_destroy(). An example is provided of using a semaphore to synchronize a parent and child process accessing shared data.

Uploaded by

Muddassir Ahmed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

EXPERIMENT 10

Semaphores using Shared Memory


Race Condition:
A situation that several tasks access and manipulate the same data concurrently and the outcome
of the execution depends on the particular order in which the access take place.
 Example:
 Suppose that the value of the variable counter = 5.
 Process 1 and process 2 execute the statements “counter++” and “counter--”
concurrently.
 Following the execution of these two statements, the value of the variable counter
may be 4, 5, or 6!

Shared memory synchronization:


 There are two essential needs for synchronization between multiple processes executing
on shared memory
 Establishing an order between two events
 E.g. in the server and client case, we want to make sure the server finishes writing
before the client reads
 Mutually exclusive access to a certain resource
 Such as a data structure, a file, etc
E.g. Two people deposit to the same account “deposit +=100”. We want to make
sure that the increment happens one at a time. Why? (Let us look draw a time line
showing possible interleaving of events)
 A semaphore can be used for both purposes
 An ordinary while loop (busy wait loop) is not safe for ensuring mutual exclusion
 Two processes may both think they have successfully set the lock and, so, have the
exclusive access
 Again, we can draw a time line showing possible interleaving of events that may
lead to failed mutual exclusion
 A semaphore is guaranteed to be able to have the correct view of the locking status

The concept of semaphores:


 Semaphores may be binary (0/10), or counting
 Every semaphore variable, s, it is initialized to some positive value
 1 for a binary semaphore
 N > 1for a counting semaphore

Binary semaphore:
 A binary semaphore, s, is used for mutual exclusion and wake up sync
1== unlocked
0==locked
 s, is associated with two operations:
 P(s)
– Tests s; if positive, resets s to 0 and proceed; otherwise, put the executing process
to the back of a waiting queue for s
 V(s)
– Set s to 1 and wake up a process in the waiting queue for s

Counting Semaphore:
 A counting semaphore, s, is used for producer/consumer sync
n== the count of available resources
0==no resource (locking consumers out)
 s, is associated with two operations:
 P(s)
– Tests s; if positive, decrements s and proceed
– otherwise, put the executing process to the back of a waiting queue for s
 V(s)
– Increments s; wakes up a process, if any, in the waiting queue for s
Critical Sections:
 We like to think of locking a concurrent data structure
 In current practice, however, locks (incl. binary semaphores) are typically used to lock a
segment of program statements (or instructions)
 Such a program segment is called a critical section
 A critical section is a program segment that may modify shared data structures
 It should be executed by one process at any given time
 With a binary semaphore
 If multiple processes are locked out of a critical section
 As soon as the critical section is unlocked, only one process is allowed in
 The other processes remain locked out
 Implementation of semaphores is fair to processes
 A first‐come‐first‐serve queue

Unix Semaphores:
 There are actually at least two implementations
 UNIX System V has an old implementation
 Analogous to shared memory system calls
 Calls to semget(), semat(), semctl(), etc
 Not as easy to use as POSIX implementation
 We will use POSIX implementation in this course

POSIX Semaphore System Calls:


 #include <semaphore.h>
 POSIX semaphores come in two forms: named semaphores and unnamed semaphores.
Using Unnamed Semaphore:
 Unnamed semaphores are also called memory‐ based semaphores
 Named semaphores are “file‐based”
 An unnamed semaphore does not have a name
 It is placed in a region of memory that is shared between multiple threads (a thread‐
shared semaphore) or processes (a process‐shared semaphore).
 A process‐shared semaphore must be placed in a shared memory region

System Calls:
 Before being used, an unnamed semaphore must be initialized using sem_init(3). It can
then be operated on using sem_post(3) and sem_wait(3)
 When the semaphore is no longer required, and before the memory in which it is located
is deallocated, the semaphore should be destroyed using sem_destroy(3)
 Compile using ‐lrt

Recall that shared memory segments must be removed before program exits
 “An unnamed semaphore should be destroyed with sem_destroy() before the memory in
which it is located is deallocated.”
 “Failure to do this can result in resource leaks on some implementations.”

int sem_init(sem_t *sem, int pshared, unsigned int value);


 #include <semaphore.h>
 sem_init() initializes the unnamed semaphore at the address pointed to by sem. The value
argument specifies the initial value for the semaphore.
 If pshared has the value 0, then the semaphore is shared between the threads of a process.
 If pshared is nonzero, then the semaphore is shared between processes, and should be
located in a region of shared memory.

int sem_wait(sem_t *sem);


 sem_wait() decrements (locks) the semaphore pointed to by sem
 If the semaphore's value is greater than zero, then the decrement proceeds, and the
function returns, immediately.
 If the semaphore currently has the value zero, then the call blocks until either it becomes
possible to perform the decrement (i.e., the semaphore value rises above zero), or a signal
handler interrupts the call.

int sem_post(sem_t *sem);


 sem_post() increments (unlocks) the semaphore pointed to by sem.
 If the semaphore's value consequently becomes greater than zero, then another process or
thread blocked in a sem_wait(3) call will be woken up

int sem_destroy(sem_t *sem);


 Destroys the unnamed semaphore at the address pointed to by sem. Only a semaphore
that has been initialized by sem_init(3) should be destroyed using sem_destroy().
 Destroying a semaphore that other processes or threads are currently blocked on (in
sem_wait(3) produces undefined behavior.
 Using a semaphore that has been destroyed produces undefined results, until the
semaphore has been reinitialized using sem_init(3).

Examples:
 We look at an example:
 We want to let parent process print its entire data first
 So we let child process wait for the process to give it a go‐ ahead
 Initialize the mutex variable to 0 and wait for the parent process to change it to 1.
 But we didn’t put the mutex variable in the shared memory
 The child process never wakes up!
 We need to manually kill the child process and free the shared memory

 Now we will correct the errors by placing the semaphore in the shared memory
 We also need to remember to destroy the unnamed semaphore before removing the
shared memory segment.
 Be careful with the timing for destroying the semaphore
 Make sure there should not be waiting processes

You might also like