Semaphore

     

Semaphore

A semaphore is basically a counter indicating the number of resources available. Depending upon number of the resources available, it may allow more than one processes to enter in critical section. In Linux, semaphores are represented by a structure struct semaphorewhich is defined in include/asm/semaphore.h. The structure contains a pointer to a wait queue and a usage count. The wait queue is a list of processes blocking on the semaphore. The usage count is the number of concurrently allowed holders. If it is zero, then no task is allowed to execute in the critical section. The absolute value of the usage count is the number of processes blocked on the wait queue. The usage count is initialized at runtime via sema_init().
Linux provides following APIs to work with semaphores:

Declaration:
struct semaphore test_sema;  


Initialization:

Every semaphore object need to be initialized using API sema_init(). Behavior of an uninitialized semaphore object is undefined.

sema_init (struct semaphore *sem, int val)
It returns void.


Parameters:

sem: pointer of semaphore object to be initialized
val: Number of resources available i.e. number of tasks allowed to execute inside critical section.


Locking:

void down(struct semaphore *sem)


Locks the semaphore. If use count of semaphore is greater than zero this function decrements the usage count of the semaphore and allowed to lock the semaphore. If use count is zero, the calling process is added to the wait queue and blocked in other words we can say if no more tasks are allowed to lock the semaphore, calling this function will put the task to sleep until the semaphore is released.  Use of this function is deprecated, please use down_interruptible() or other methods given below.

int down_interruptible(struct semaphore *sem)

Acquire the semaphore unless interrupted.  If no more tasks are allowed to lock the semaphore, calling this function will put the task to sleep. If the sleep is interrupted by a signal, this function will return -EINTR. If the semaphore is successfully locked, this function returns 0.  It is widely used to lock a semaphore.

int down_killable(struct semaphore *sem)

Locks the semaphore unless killed. Attempts to lock the semaphore.  If no more tasks are allowed to lock the semaphore, calling this function will put the task to sleep. If the sleep is interrupted by a fatal signal, this function will return -EINTR.  If the semaphore is successfully locked, this function returns 0.

int down_trylock(struct semaphore *sem)


Tries to lock the semaphore, without waiting. Returns 0 if the mutex has been locked successfully or 1 if it it cannot be locked.


NOTE: 

This return value is inverted from both spin_trylock and mutex_trylock!  Be careful about this when converting code. Unlike mutex_trylock, this function can be used from interrupt context, and the semaphore can be released by any task or interrupt.
int down_timeout(struct semaphore *sem, long jiffies)


Lock the semaphore within a specified time. If no more tasks are allowed to lock the semaphore, calling this function will put the task to sleep. If the semaphore is not released within the specified number of jiffies, this function returns -ETIME.  It returns 0 if the semaphore was locked.


Unlocking:
up(struct semaphore *sem)


Release the semaphore. Increaments use count if there is no task in wait queue.  Unlike mutexes, up() may be called from any context and even by tasks which have never called down().


Important:  

A semaphore can be unlocked even if it has not been locked. In this case it will increment use count thus number of tasks allowed inside critical section will be increased irrespective of what value it was initialized.


Example code:


/* header inclusion */
#include<linux/semaphore.h>

/* Declaration */
struct semaphore  test_sem;

/* initialization */
sem_init(&test_sem, 2);

/* usage */
if(down_interruptible(&test_sem))
{
      printk(“failed to lock semaphore”);
      return ;
}

/* critical section */
..
up(&test_sem);




Previous(Kernel Locking)                                                                                                Next(Mutex)

No comments:

Simple theme. Powered by Blogger.