Sunday, May 29, 2011

Semaphors


Hi guys,
Today I’ll be talking about Semaphores and their usage in the kernel.
As you recall two weeks ago I have posted a post about spin lock,
Semaphore is a different type of story and today I’ll make it clear for those of you aren’t sure.
Semaphore in Linux is a type of sleeping lock, it means that a task which missed acquiring the semaphore would be put in a wait queue and will go into a sleep mode.
Meanwhile the processor would do all the other tasks, and eventually when the semaphore would be available the tasks on the waiting queue would execute by FIFO order.
The semaphore approach is different than the spinlock method, semaphore provides better processor utilization than spin locks because there is no time spent busy looping, but semaphores have much greater overhead than spin locks.

So probably you are now asking, when should I use semaphore rather than spinlocks?

I’ll try to set it clear for you:

Usually you should use semaphore if you know the lock is held for long periods, those tasks which are waiting for the lock are getting some sleep till the lock would be available.
So it’s no optimal situation for semaphores to hold the locks for short time because the overhead of sleeping, maintaining the wait queue, and waking back up can easily affect the CPU utilization.
Of course the since the nature of spin locks and semaphore are different you can’t hold the two during the same time (Getting some sleep in the queue and doing busy waiting work well together).
Your actual decision should be based on lock hold time.
Important point is unlike spin-locks, semaphores do not disable kernel preemption, so code holding a semaphore can be preempted. This approach is much safer for making sure it won’t take longer time than expected in refer to scheduling latency.

I assume you heard the term “Counting semaphore” before, the idea is pretty simple, when you declare a semaphore you should initialize its count, which means how many lock holders can enter the critical region during the same time. Whereas spin locks permit at most one task to enter the critical section.
In case the count of a semaphore is set to one, it’s called Binary Semaphore. Each time a task is acquiring a lock and enters the critical region is should use the method down() which decreases the counter.
Of course when a task releases the lock the method up() is used for increasing the counter value.
// First we define and declare a semaphore, named my_sem, 
// with count of one
static DECLARE_MUTEX(my_sem);
     
if (down_intteruptible(&my_sem))
{
 //signal received, semaphore not acquired 
}

//Entering into the critical section

up(&my_sem); //release the semaphore you hold

You can see semaphores methods in the semaphore.h file, I encourage you to explore:

extern void down(struct semaphore *sem);

extern int __must_check down_interruptible(struct semaphore *sem);

extern int __must_check down_trylock(struct semaphore *sem);

extern int __must_check down_timeout(struct semaphore *sem, long jiffies);

extern void up(struct semaphore *sem);

No comments:

Post a Comment

About