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
semaphore” which 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:
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:
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.
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);
No comments:
Post a Comment