How semaphores work

Source: Internet
Author: User
Tags semaphore

First, the kernel-related files are include/linux/semaphore.h and kernel/semaphore.c

Second, the main structural body:

struct semaphore {raw_spinlock_tlock;unsigned intcount;struct list_headwait_list;};

Structure member variable interpretation:

1, lock is mainly used to protect the count and wait_list linked list access;

2, Count records the semaphore wait process count;

3, Wait_list used to record the process of waiting for the semaphore, strung into a chain list to unified management;

Third, related interface

1. Initialize the interface

static inline void Sema_init (struct semaphore *sem, int val) {static struct Lock_class_key __key;*sem = (struct semaphore) __semaphore_initializer (*sem, Val); Lockdep_init_map (&sem->lock.dep_map, "Semaphore->lock", &__key, 0 );}

The interface mainly completes the mutual exclusion lock, the initial value of the semaphore count, and the initial operation of the node of the chain header;

2, down signal volume interface

There are a total of five to get the semaphore interface:

extern void down (struct semaphore *sem), extern int __must_check down_interruptible (struct semaphore *sem); extern int __mu St_check down_killable (struct semaphore *sem); extern int __must_check down_trylock (struct semaphore *sem); extern int __ Must_check down_timeout (struct semaphore *sem, long jiffies);

1) down interface core is not recommended, according to the development trend of the kernel, will gradually cancel out this interface;

2) down signal interface, it is generally recommended to use down_interruptible, this interface will be the current task status set to Task_interruptible, meaning that once the condition is met, the task will be dispatched before the set timeout time arrives;

3) Down_killable: Can be killed to obtain the amount of signal. If sleep is interrupted by a fatal signal, return error-eintr;

4) Down_trylock: This interface comes up to get the semaphore, does not set the timeout time, does not do any wait, obtains to return 0, obtains not to return 1;

5) Down_timeout: If the semaphore is fetched up, it is returned directly, and the timeout time of the sleep wait setting is not obtained;

These five interfaces, in addition to the Down_trylock, eventually call the __down_common interface, but the parameters passed in are different.

static noinline void __sched __down (struct semaphore *sem) {__down_common (SEM, task_uninterruptible, Max_schedule_ TIMEOUT);} static noinline int __sched __down_interruptible (struct semaphore *sem) {return __down_common (SEM, task_interruptible, Max_schedule_timeout);} static noinline int __sched __down_killable (struct semaphore *sem) {return __down_common (SEM, task_killable, Max_ Schedule_timeout);} static noinline int __sched __down_timeout (struct semaphore *sem, long jiffies) {return __down_common (SEM, task_ uninterruptible, jiffies);}

We can take a look at __down_common this interface: First, the current process will be attached to the semaphore wait_list linked list, and then the other process through schedule_timeout scheduling, the current task hangs;

struct Semaphore_waiter {struct List_head list;struct task_struct *task;int up;};
static inline int __sched __down_common (struct semaphore *sem, long state,long timeout) {struct Task_struct *task = current ; struct Semaphore_waiter waiter;list_add_tail (&waiter.list, &sem->wait_list); waiter.task = task; Waiter.up = 0;for (;;) {if (Signal_pending_state (State, Task)) Goto interrupted;if (Timeout <= 0) Goto timed_out;__set_task_state (Task, State); Raw_spin_unlock_irq (&sem->lock); timeout = schedule_timeout (timeout); RAW_SPIN_LOCK_IRQ (&sem- >lock); if (waiter.up) return 0;} Timed_out:list_del (&waiter.list); return-etime; Interrupted:list_del (&waiter.list); return-eintr;}


3, the release of the signal interface: this interface mainly to do the following work, first determine whether the current semaphore wait_list is empty, if it is empty, that is, there is no process to wait for this semaphore, then direct sem->count++, otherwise, the first node in the wait_list removed, The wake_up_process is placed in the activation task queue and waits for execution.

extern void up (struct semaphore *sem), void up (struct semaphore *sem) {unsigned long flags;raw_spin_lock_irqsave (& Sem->lock, Flags), if (Likely (List_empty (&sem->wait_list))) SEM->COUNT++;ELSE__UP (SEM); raw_spin_ Unlock_irqrestore (&sem->lock, flags);} static noinline void __sched __up (struct semaphore *sem) {struct Semaphore_waiter *waiter = list_first_entry (&sem- >wait_list,struct semaphore_waiter, list); List_del (&waiter->list); waiter->up = 1;wake_up_process ( Waiter->task);}



How semaphores work

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.