信号量在Linux中的实现
来源:互联网 发布:预测炒股票软件哪家好 编辑:程序博客网 时间:2024/06/06 21:02
在Linux 3.13中,普通信号量的定义如下
/* 2 * Copyright (c) 2008 Intel Corporation 3 * Author: Matthew Wilcox <willy@linux.intel.com> 4 * 5 * Distributed under the terms of the GNU GPL, version 2 6 * 7 * Please see kernel/semaphore.c for documentation of these functions 8 */ 9 #ifndef __LINUX_SEMAPHORE_H 10 #define __LINUX_SEMAPHORE_H 11 12 #include <linux/list.h> 13 #include <linux/spinlock.h> 14 15 /* Please don't access any members of this structure directly */ 16 struct semaphore { 17 raw_spinlock_t lock; 18 unsigned int count; 19 struct list_head wait_list; 20 }; 21 22 #define __SEMAPHORE_INITIALIZER(name, n) \ 23 { \ 24 .lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock), \ 25 .count = n, \ 26 .wait_list = LIST_HEAD_INIT((name).wait_list), \ 27 } 28 29 #define DEFINE_SEMAPHORE(name) \ 30 struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1) 31 32 static inline void sema_init(struct semaphore *sem, int val) 33 { 34 static struct lock_class_key __key; 35 *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val); 36 lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0); 37 } 38 39 extern void down(struct semaphore *sem); 40 extern int __must_check down_interruptible(struct semaphore *sem); 41 extern int __must_check down_killable(struct semaphore *sem); 42 extern int __must_check down_trylock(struct semaphore *sem); 43 extern int __must_check down_timeout(struct semaphore *sem, long jiffies); 44 extern void up(struct semaphore *sem); 45 46 #endif /* __LINUX_SEMAPHORE_H */
count<0, 其绝对值表示在等待队列中的进程个数;count>0,表示可以同时进入临界区域的进程个数。down操作对count减1,如果count<0,则进程进入等待队列;up操作对count加1,如果count>=0,这唤醒一个等待队列上的进程。
sleepers 对当前临界资源的进程个数的辅助计数。
在linux中对信号量的操作有up(),down()和down_interuptible()。down()和down_interuptible唯一的区别,在等待过程中,down_interuptible()可以被其他信号中断,而down()不可以。
up函数的调用次序是:先调用up_wakeup(),在调用__up()。而down()函数的次序是:先调用down_failed(),再调用__down().
函数实现
/** 43 * down - acquire the semaphore 44 * @sem: the semaphore to be acquired 45 * 46 * Acquires the semaphore. If no more tasks are allowed to acquire the 47 * semaphore, calling this function will put the task to sleep until the 48 * semaphore is released. 49 * 50 * Use of this function is deprecated, please use down_interruptible() or 51 * down_killable() instead. 52 */ 53 void down(struct semaphore *sem) 54 { 55 unsigned long flags; 56 57 raw_spin_lock_irqsave(&sem->lock, flags); 58 if (likely(sem->count > 0)) 59 sem->count--; 60 else 61 __down(sem); 62 raw_spin_unlock_irqrestore(&sem->lock, flags); 63 } 64 EXPORT_SYMBOL(down); 65 66 /** 67 * down_interruptible - acquire the semaphore unless interrupted 68 * @sem: the semaphore to be acquired 69 * 70 * Attempts to acquire the semaphore. If no more tasks are allowed to 71 * acquire the semaphore, calling this function will put the task to sleep. 72 * If the sleep is interrupted by a signal, this function will return -EINTR. 73 * If the semaphore is successfully acquired, this function returns 0. 74 */ 75 int down_interruptible(struct semaphore *sem) 76 { 77 unsigned long flags; 78 int result = 0; 79 80 raw_spin_lock_irqsave(&sem->lock, flags); 81 if (likely(sem->count > 0)) 82 sem->count--; 83 else 84 result = __down_interruptible(sem); 85 raw_spin_unlock_irqrestore(&sem->lock, flags); 86 87 return result; 88 } 89 EXPORT_SYMBOL(down_interruptible); 90 91 /** 92 * down_killable - acquire the semaphore unless killed 93 * @sem: the semaphore to be acquired 94 * 95 * Attempts to acquire the semaphore. If no more tasks are allowed to 96 * acquire the semaphore, calling this function will put the task to sleep. 97 * If the sleep is interrupted by a fatal signal, this function will return 98 * -EINTR. If the semaphore is successfully acquired, this function returns 99 * 0.100 */101 int down_killable(struct semaphore *sem)102 {103 unsigned long flags;104 int result = 0;105 106 raw_spin_lock_irqsave(&sem->lock, flags);107 if (likely(sem->count > 0))108 sem->count--;109 else110 result = __down_killable(sem);111 raw_spin_unlock_irqrestore(&sem->lock, flags);112 113 return result;114 }115 EXPORT_SYMBOL(down_killable);116 117 /**118 * down_trylock - try to acquire the semaphore, without waiting119 * @sem: the semaphore to be acquired120 *121 * Try to acquire the semaphore atomically. Returns 0 if the semaphore has122 * been acquired successfully or 1 if it it cannot be acquired.123 *124 * NOTE: This return value is inverted from both spin_trylock and125 * mutex_trylock! Be careful about this when converting code.126 *127 * Unlike mutex_trylock, this function can be used from interrupt context,128 * and the semaphore can be released by any task or interrupt.129 */130 int down_trylock(struct semaphore *sem)131 {132 unsigned long flags;133 int count;134 135 raw_spin_lock_irqsave(&sem->lock, flags);136 count = sem->count - 1;137 if (likely(count >= 0))138 sem->count = count;139 raw_spin_unlock_irqrestore(&sem->lock, flags);140 141 return (count < 0);142 }143 EXPORT_SYMBOL(down_trylock);144 145 /**146 * down_timeout - acquire the semaphore within a specified time147 * @sem: the semaphore to be acquired148 * @jiffies: how long to wait before failing149 *150 * Attempts to acquire the semaphore. If no more tasks are allowed to151 * acquire the semaphore, calling this function will put the task to sleep.152 * If the semaphore is not released within the specified number of jiffies,153 * this function returns -ETIME. It returns 0 if the semaphore was acquired.154 */155 int down_timeout(struct semaphore *sem, long jiffies)156 {157 unsigned long flags;158 int result = 0;159 160 raw_spin_lock_irqsave(&sem->lock, flags);161 if (likely(sem->count > 0))162 sem->count--;163 else164 result = __down_timeout(sem, jiffies);165 raw_spin_unlock_irqrestore(&sem->lock, flags);166 167 return result;168 }169 EXPORT_SYMBOL(down_timeout);170 171 /**172 * up - release the semaphore173 * @sem: the semaphore to release174 *175 * Release the semaphore. Unlike mutexes, up() may be called from any176 * context and even by tasks which have never called down().177 */178 void up(struct semaphore *sem)179 {180 unsigned long flags;181 182 raw_spin_lock_irqsave(&sem->lock, flags);183 if (likely(list_empty(&sem->wait_list)))184 sem->count++;185 else186 __up(sem);187 raw_spin_unlock_irqrestore(&sem->lock, flags);188 }189 EXPORT_SYMBOL(up);190 191 /* Functions for the contended case */192 193 struct semaphore_waiter {194 struct list_head list;195 struct task_struct *task;196 bool up;197 };198 199 /*200 * Because this function is inlined, the 'state' parameter will be201 * constant, and thus optimised away by the compiler. Likewise the202 * 'timeout' parameter for the cases without timeouts.203 */204 static inline int __sched __down_common(struct semaphore *sem, long state,205 long timeout)206 {207 struct task_struct *task = current;208 struct semaphore_waiter waiter;209 210 list_add_tail(&waiter.list, &sem->wait_list);211 waiter.task = task;212 waiter.up = false;213 214 for (;;) {215 if (signal_pending_state(state, task))216 goto interrupted;217 if (unlikely(timeout <= 0))218 goto timed_out;219 __set_task_state(task, state);220 raw_spin_unlock_irq(&sem->lock);221 timeout = schedule_timeout(timeout);222 raw_spin_lock_irq(&sem->lock);223 if (waiter.up)224 return 0;225 }226 227 timed_out:228 list_del(&waiter.list);229 return -ETIME;230 231 interrupted:232 list_del(&waiter.list);233 return -EINTR;234 }235 236 static noinline void __sched __down(struct semaphore *sem)237 {238 __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);239 }240 241 static noinline int __sched __down_interruptible(struct semaphore *sem)242 {243 return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);244 }245 246 static noinline int __sched __down_killable(struct semaphore *sem)247 {248 return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);249 }250 251 static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies)252 {253 return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);254 }255 256 static noinline void __sched __up(struct semaphore *sem)257 {258 struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,259 struct semaphore_waiter, list);260 list_del(&waiter->list);261 waiter->up = true;262 wake_up_process(waiter->task);
文山 www.wenshan.me
0 0
- 信号量在Linux中的实现
- linux中的信号量详解
- linux中的信号量机制
- linux中的信号量操作
- linux中的信号量
- Linux中的信号量
- Linux内核中的信号量
- Linux信号量的实现
- Linux中的信号量(上)
- [转]linux信号量的实现
- Linux内核读写信号量实现
- linux下信号量实现通信
- 信号量在linux0.11下的实现及其在生产者,消费者应用中的体现
- VLAN在linux中的实现
- 线程在Linux中的实现
- java中的SecureRandom在linux中的实现
- java中的SecureRandom在linux中的实现
- java中的SecureRandom在linux中的实现
- C语言中最常用标准库函数
- 线段树Codeforces Beta Round #99 (Div. 1)C
- GWT 批量上传
- HDU 1069 Monkey and Banana 动态规划
- windows下expect使用小结
- 信号量在Linux中的实现
- http://www.cnblogs.com/xia520pi/
- shader复习与深入:Normal Map(法线贴图)Ⅱ(转)
- ping 出现destination host unreachable的问题
- PKU A Simple Problem with Integers (线段树区间更新求和)
- Flex web视频监控浏览端
- ACM 矩阵乘法模板(T_T)+快速幂
- CentOS7 win7 双系统安装
- [Unity-3] iTween动画插件