Online Labs

Semaphore

Semaphores are a programming construct designed by E. W. Dijkstra in the late 1960s. Dijkstra’s model was the operation of railroads: consider a stretch of railroad in which there is a single track over which only one train at a time is allowed. Guarding this track is a semaphore. A train must wait before entering the single track until the semaphore is in a state that permits travel. When the train enters the track, the semaphore changes state to prevent other trains from entering the track. A train that is leaving this section of track must again change the state of the semaphore to allow another train to enter. In the computer version, a semaphore appears to be a simple integer. A process (or a thread) waits for permission to proceed by waiting for the integer to become 0. The signal if it proceeds signals that this by performing incrementing the integer by 1. When it is finished, the process changes the semaphore’s value by subtracting one from it.

Semaphore is a variable that can take only the values 0 and 1, binary semaphore. This is the most common form. Semaphore that can take many positive values are called general semaphores.

The definition of  P and V are surprisingly simple. Suppose we have semaphore variable sv. The two operations are defined as follows:

P(sv) – If sv is greater than zero, decrement sv, if sv is zero, suspend execution of this process.

V(sv) – If some other process has been suspend waiting for sv, make it resume execution. If no process is suspended waiting for sv, Increment sv.

Semaphores let processes query or alter status information. They are often used to monitor and control the availability of system resources such as shared memory segments.

POSIX semaphores are much lighter weight than are System V semaphores. A POSIX semaphore structure defines a single semaphore, not an array of up to twenty five semaphores. The POSIX semaphore functions are:

sem_open() — Connects to, and optionally creates, a named semaphore

sem_init() — Initializes a semaphore structure (internal to the calling program, so not a named semaphore).

sem_close() — Ends the connection to an open semaphore.

sem_unlink() — Ends the connection to an open semaphore and causes the semaphore to be removed when the last process closes it.

sem_destroy() — Initializes a semaphore structure (internal to the calling program, so not a named semaphore).

sem_getvalue() — Copies the value of the semaphore into the specified integer.

sem_wait(), sem_trywait() — Blocks while the semaphore is held by other processes or returns an error if the semaphore is held by another process.

sem_post() — Increments the count of the semaphore.

All POSIX semaphore functions and types are prototyped or defined in semaphore.h. To define a semaphore object, use

     sem_t sem_name;

To initialize a semaphore, use sem_init():

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

  • sem points to a semaphore object to initialize
  • pshared is a flag indicating whether or not the semaphore should be shared with fork()ed processes. LinuxThreads does not currently support shared semaphores
  • value is an initial value to set the semaphore to

 

Example of use:        

      sem_init(&sem_name, 0, 10);


To wait on a semaphore, use sem_wait:

      int sem_wait(sem_t *sem);

Example of use:

      sem_wait(&sem_name);

  • If the value of the semaphore is negative, the calling process blocks; one of the blocked processes wakes up when another process calls sem_post.


To increment the value of a semaphore, use sem_post:

      int sem_post(sem_t *sem);

Example of use:

      sem_post(&sem_name);

  • It increments the value of the semaphore and wakes up a blocked process waiting on the semaphore, if any.


To find out the value of a semaphore, use

      int sem_getvalue(sem_t *sem, int *valp);

  • gets the current value of sem and places it in the location pointed to by valp

Example of use:

      int value;

      sem_getvalue(&sem_name, &value);

      printf("The value of the semaphors is %d\n", value);


To destroy a semaphore, use

      int sem_destroy(sem_t *sem);

  • destroys the semaphore; no threads should be waiting on the semaphore if its destruction is to succeed.

Example of use:

     sem_destroy(&sem_name);


Using semaphores – a short example

 

Consider the problem we had before and now let us use semaphores:

        Declare the semaphore global (outside of any funcion):               sem_t mutex;         Initialize the semaphore in the main function:                  sem_init(&mutex, 0, 1);  

Thread 1

Thread 2

data

sem_wait (&mutex);

---

0

---

sem_wait (&mutex);

0

a = data;

/* blocked */

0

a = a+1;

/* blocked */

0

data = a;

/* blocked */

1

sem_post (&mutex);

/* blocked */

1

/* blocked */

b = data;

1

/* blocked */

b = b + 1;

1

/* blocked */

data = b;

2

/* blocked */

sem_post (&mutex);

2

[data is fine. The data race is gone.]

 

 

The basic operation of these functions is essence the same as described above, except note there are more specialised functions, here.

Program

/* Program to demonstrate the usage of semaphore variable in controlling the access to 

    specific resources.

 

 * This program contains two functions which display their own messages.

 

 * The display is suitably controlled by the use of semaphore variable.

 

 

*  It is a program in which a semaphore variable is shared between the main function    

    and a thread function.

 

 * This module can be compiled using ‘cc semaphore1.c -lpthread’ and executed     ‘./a.out’

 

                              //inculsion part.            

#include<stdio.h>

#include<pthread.h>

#include<semaphore.h>

                                   

//function prototype for the thread function.

void * display_function();

 

                                    //global semaphore variable to be shared.

sem_t sem_var;

 

int main()

{

 pthread_t tid;

 pthread_attr_t attr;

 int i;

//initialising the semaphore variable with an initial value 0 (third arguement.)

 sem_init(&sem_var,0,0);

 

 pthread_attr_init(&attr);

 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

 

 pthread_create(&tid,&attr,display_function,NULL);

 

 for(i=0;i<5;i++)

 {

  printf(“\n Displaying from the main function:\t%d\n”,i+1);

                       

//waiting for the resources. 

  sem_wait(&sem_var); 

 }

                                    //destroying the semaphore variable.

 sem_destroy(&sem_var);

}

 

void * display_function()

{

 int i;

 for(i=0;i<5;i++)

 {

  printf(“\n***** Displaying from the thread function.:\t%d\n”,i+1);

                                    //releasing resources.

  sem_post(&sem_var);

  sleep(1);

 }

}

 

Output

15

SERIALISABILITY PROBLEM.

                                    (By using Semaphore Variable)

 

Program

 

 

* This program uses a variable ‘data’ whose value is used by two thread function.

* But the condition is that when a function uses it no other function should use it.

* This problem is tackled by definig two thread function and suitably making them access

   it by the use of semaphore variable.

* This module can be compiled using ‘cc semaphore2.c -lpthread’ and executed ‘./a.out’

 

                                    //inculsion part.

#include<stdio.h>

#include<pthread.h>

#include<semaphore.h>

                        //prototype for thread functions.

void * thread_function1();

void * thread_function2();

                        //global variables.

int data=0,end=0;

                        //global semaphore variables.

sem_t sem_var;

 

int main()

{

 pthread_t t1,t2;

 pthread_attr_t attr;

 

 pthread_attr_init(&attr);

 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

 

 sem_init(&sem_var,0,1);

 

 pthread_create(&t1,&attr,thread_function1,NULL);

 pthread_create(&t2,&attr,thread_function2,NULL);

 

 while(end!=2)

 {

 }

 

 printf(“\n\t****** The value of DATA is:\t%d ******\n”,data);

}

                        //definition of first thread function.

void * thread_function1()

{

 int a;

 

 printf(“\nEntered into thread function:1\n”);

 

 printf(“\nThread function:1 waiting to gain access\n”);

 

 sleep(1);

 

 sem_wait(&sem_var);

 printf(“\nAccess gained by thread function:1\n”);

 

 printf(“\nThread function:1 using the value of ‘DATA’ \n”);

 

 a=data;

 a=a+1;

 data=a;

 

 sem_post(&sem_var);

 printf(“\nResources released by thread function:1\n”);

 end++;

}

                        //definition of second thread function.

void * thread_function2()

{

 int b;

 

 printf(“\nEntered into thread function:2\n”);

 printf(“\nThread function:2 waiting to gain access\n”);

 

 sleep(1);

 

 sem_wait(&sem_var);

 printf(“\nAccess gained by thread function:2\n”);

 printf(“\nThread function:2 using the value of ‘DATA’ \n”);

 b=data;

 b=b+1;

 data=b;

 

 sem_post(&sem_var);

 printf(“\nResources released by thread function:2\n”);

 end++;

}

 

Output

 

24

 

 

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: