0% found this document useful (0 votes)
147 views5 pages

POSIX Semaphores A Variable of Type Sem - T

The document discusses POSIX semaphores and provides an example C program to illustrate their use. It defines a sem_t variable to represent a semaphore. Operations on semaphores like sem_init(), sem_wait(), sem_post() are used to initialize, wait on and signal the semaphore. The example program creates multiple threads that execute a critical section, using the semaphore to ensure only one thread accesses the critical section at a time.

Uploaded by

Carlos Castillo
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)
147 views5 pages

POSIX Semaphores A Variable of Type Sem - T

The document discusses POSIX semaphores and provides an example C program to illustrate their use. It defines a sem_t variable to represent a semaphore. Operations on semaphores like sem_init(), sem_wait(), sem_post() are used to initialize, wait on and signal the semaphore. The example program creates multiple threads that execute a critical section, using the semaphore to ensure only one thread accesses the critical section at a time.

Uploaded by

Carlos Castillo
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/ 5

Advanced Linux Programming M.

Barbeau

POSIX Semaphores

A variable of type sem_t

Example – Declaration of a semaphore

#include <semaphore.h>
sem_t sem;

Operations on semaphores (taken from the Linux man page)

#include <semaphore.h>
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);

sem_init initializes the semaphore object pointed to by sem. The count


associated with the semaphore is set initially to value. The pshared argument
indicates whether the semaphore is local to the current process (pshared is zero)
or is to be shared between several processes, e.g. a parent and its children processes
(pshared is not zero). Linux currently does not support process-shared
semaphores, thus sem_init always returns with error ENOSYS if pshared is
not zero.

sem_wait suspends the calling thread until the semaphore pointed to by sem has
non-zero count. It then atomically decreases the semaphore count.

sem_trywait is a non-blocking variant of sem_wait. If the semaphore pointed


to by sem has non-zero count, then the count is atomically decreased and
sem_trywait immediately returns 0. If the semaphore count is zero,
sem_trywait immediately returns with error EAGAIN.

sem_post atomically increases the count of the semaphore pointed to by sem.


This function never blocks and can safely be used in asynchronous signal handlers.

1
Advanced Linux Programming M. Barbeau

sem_getvalue stores in the location pointed to by sval the current count of the
semaphore sem.

sem_destroy destroys a semaphore object, freeing the resources it might hold.


No threads should be waiting on the semaphore at the time sem_destroy is
called. In the Linux implementation, no resources are associated with semaphore
objects, thus sem_destroy actually does nothing except checking that no thread
is waiting on the semaphore.

The sem_wait and sem_getvalue functions always return 0. All other


semaphore functions return 0 on success and -1 on error, in addition to writing an
error code in errno.

A program that illustrates POSIX semaphores and System V semaphores on


Linux.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>

#define POSIX_SEMAPHORE
/* #define SYSV_SEMAPHORE */

#ifdef POSIX_SEMAPHORE
#include <semaphore.h>
sem_t my_sem;
#define SEMINITVALUE 1
#endif
#ifdef SYSV_SEMAPHORE
#include <sys/ipc.h>
#include <sys/sem.h>
int my_sem, semop_ret;
#define PERMS S_IRUSR | S_IWUSR
#define SEM_SET_SIZE 1
struct sembuf semwait = { 0, -1, 0 };
struct sembuf semsignal = { 0, 1, 0 };
#endif

2
Advanced Linux Programming M. Barbeau

/* function prototypes */
void *critical_section(void *);

#define MAXTHREADS 100

/*
* Main program
*
*/
int main(int argc, char *argv[])
{
int n, i, error;
pthread_t threadid[MAXTHREADS];

/* check the number of arguments */


if ((argc != 2) || ((n = atoi(argv[1])) <= 0))
{
fprintf(stderr, "Usage: %s number_of_threads\n", argv[0]);
exit(1);
}

/* initialise the semaphore */


#ifdef POSIX_SEMAPHORE
if (sem_init(&my_sem, 0, SEMINITVALUE) < 0)
{
perror("Could not initialise semaphore");
exit(1);
}
#endif
#ifdef SYSV_SEMAPHORE
if ((my_sem = semget(IPC_PRIVATE, SEM_SET_SIZE, PERMS)) < 0)
{
perror("Could not initialise semaphore");
exit(1);
}
/* initialise the semaphore to one */
if (semop(my_sem, &semsignal, 1) == -1)
{
fprintf(stderr, "Semaphore increment dailed %s\n",
strerror(errno));
exit(1);
}
#endif

3
Advanced Linux Programming M. Barbeau

/* create the threads */


for (i = 0; i < n; ++i)
{
if (error=pthread_create(&threadid[i], NULL,
critical_section, (void *)i))
fprintf(stderr, "Cannot create thread %d: %s\n", i,
strerror(error));
}

/* wait for the threads to complete */


for (i = 0; i < n; ++i)
{
if (error=pthread_join(threadid[i], NULL))
fprintf(stderr, "No thread %d to join: %s\n", i,
strerror(error));
}

exit(0);
}

void *critical_section(void *arg)


{
int myindex, i, n;

/* extract the index of the thread */


myindex = (int)arg;

/* entry action */
#ifdef POSIX_SEMAPHORE
if (sem_wait(&my_sem) == 1)
{
perror("Invalid semaphore");
exit(1);
}
#endif
#ifdef SYSV_SEMAPHORE
while ((semop_ret=semop(my_sem, &semwait, 1)==-1) &&
(errno == EINTR));
if (semop_ret == -1)
{
fprintf(stderr, "Semaphore decrement failed: %s\n",
strerror(errno));
}
#endif

/* critical section */
for (i=1; i < 5; i++)

4
Advanced Linux Programming M. Barbeau

{
fprintf(stdout, "%d : %d\n", myindex, i);
/* sleep for one second */
if ((n=sleep(1)) != 0)
fprintf(stderr, "interrupted, no of secs left %d\n",
n);
}

/* exit action */
#ifdef POSIX_SEMAPHORE
if (sem_post(&my_sem) == -1)
{
perror("Invalid semaphore");
exit(1);
}
#endif
#ifdef SYSV_SEMAPHORE
while ((semop_ret=semop(my_sem, &semsignal, 1)==-1) &&
(errno == EINTR));
if (semop_ret == -1)
{
fprintf(stderr, "Semaphore increment failed: %s\n",
strerror(errno));
}
#endif

/* remainder */

pthread_exit(NULL);
}

You might also like