semaphore
来源:互联网 发布:mdb数据库 编辑:程序博客网 时间:2024/06/05 05:11
1 数据结构
struct semaphore {raw_spinlock_tlock;unsigned intcount;struct list_headwait_list;};
typedef struct raw_spinlock {arch_spinlock_t raw_lock;#ifdef CONFIG_GENERIC_LOCKBREAKunsigned int break_lock;#endif#ifdef CONFIG_DEBUG_SPINLOCKunsigned int magic, owner_cpu;void *owner;#endif#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_map dep_map;#endif} raw_spinlock_t;
2 初始化
2.1 动态
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);//初始化一个lock的实例lock-class映射信息}
#define __SEMAPHORE_INITIALIZER(name, n)\{\.lock= __RAW_SPIN_LOCK_UNLOCKED((name).lock),\.count= n,\.wait_list= LIST_HEAD_INIT((name).wait_list),\}如果n为0,表示该信号量不可用;如果n>0,表示信号量可用。
#define __RAW_SPIN_LOCK_UNLOCKED(lockname)\(raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
#define __RAW_SPIN_LOCK_INITIALIZER(lockname)\{\.raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,\SPIN_DEBUG_INIT(lockname)\SPIN_DEP_MAP_INIT(lockname) }也是将next和owner字段初始化为0。
CONFIG_LOCKDEP是一个打开lock debug的宏。
arch/arm/Kconfig
config LOCKDEP_SUPPORT
bool
default y
lib/Kconfig.debug
config LOCKDEP
bool
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
select STACKTRACE
select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 && !MICROBLAZE
select KALLSYMS
select KALLSYMS_ALL
2.2 静态
#define DEFINE_SEMAPHORE(name)\struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
3 请求信号量
3.1 down()
不可被中断的请求。void down(struct semaphore *sem){unsigned long flags;raw_spin_lock_irqsave(&sem->lock, flags);if (likely(sem->count > 0))sem->count--;else__down(sem);raw_spin_unlock_irqrestore(&sem->lock, flags);}信号量依赖于自旋锁。count>0说明信号量可用;否则,TASK_UNINTERRUPTIBLE的schedule()。
__down(sem)->__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)->
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);//加入sem的等待wait_list,sem up的时候,会遍历wait_listwaiter.task = task;waiter.up = false;for (;;) {//如果是可被中断的可能会goto interrupted,否则会schedule,直到waiter.up为true。if (signal_pending_state(state, task))goto interrupted;if (unlikely(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;//可被中断的请求信号量,被信号中断后返回-EINTR interrupted:list_del(&waiter.list);return -EINTR;}
static inline int signal_pending_state(long state, struct task_struct *p){//不可被中断或者未设置TASK_WAKEKILL(可被致命信号kill)if (!(state & (TASK_INTERRUPTIBLE | TASK_WAKEKILL)))return 0;//没有待处理的信号。TIF_SIGPENDING置位,表示该进程有信号需要处理if (!signal_pending(p))return 0;/*设置了TASK_INTERRUPTIBLE,或者设置TASK_WAKEKILL,并且有待处理的信号就走到了这里。TASK_INTERRUPTIBLE表示可以被信号中断,设置了它,这里会返回非0值;只设置了TASK_WAKEKILL,如果检测到SIGKILL信号也会返回非0值。*/return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);}
3.2 down_interruptible()
可被中断的请求。int down_interruptible(struct semaphore *sem){unsigned long flags;int result = 0;raw_spin_lock_irqsave(&sem->lock, flags);if (likely(sem->count > 0))sem->count--;elseresult = __down_interruptible(sem);raw_spin_unlock_irqrestore(&sem->lock, flags);return result;}__down_interruptible()-> __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)
请求成功返回0,如果没有信号将其中断,会schedule(),一直睡眠下去;如果睡眠被信号中断,会返回-EINTR。
3.3 down_killable()
可被kill的请求。int down_killable(struct semaphore *sem){unsigned long flags;int result = 0;raw_spin_lock_irqsave(&sem->lock, flags);if (likely(sem->count > 0))sem->count--;elseresult = __down_killable(sem);raw_spin_unlock_irqrestore(&sem->lock, flags);return result;}
static noinline int __sched __down_killable(struct semaphore *sem){return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);}task标志为
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
不可被中断的请求,并且可被致命信号kill。请求成功返回0;睡眠被致命信号中断,返回-EINTR。
3.4 down_trylock()
尝试原子的请求信号量。int down_trylock(struct semaphore *sem){unsigned long flags;int count;raw_spin_lock_irqsave(&sem->lock, flags);count = sem->count - 1;if (likely(count >= 0))sem->count = count;raw_spin_unlock_irqrestore(&sem->lock, flags);return (count < 0);}如果请求成功返回0,不能请求到返回1。请求过程不会睡眠。
注意:spin_trylock and mutex_trylock的返回值是反转的。
mutex_trylock可以用于中断上下文,semaphore可用于任何进程和中断中。
3.5 down_timeout()
超时请求。int down_timeout(struct semaphore *sem, long jiffies){unsigned long flags;int result = 0;raw_spin_lock_irqsave(&sem->lock, flags);if (likely(sem->count > 0))sem->count--;elseresult = __down_timeout(sem, jiffies);raw_spin_unlock_irqrestore(&sem->lock, flags);return result;}
int down_timeout(struct semaphore *sem, long jiffies){unsigned long flags;int result = 0;raw_spin_lock_irqsave(&sem->lock, flags);if (likely(sem->count > 0))sem->count--;elseresult = __down_timeout(sem, jiffies);raw_spin_unlock_irqrestore(&sem->lock, flags);return result;}
static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies){return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);}之前的几种请求,如果不填这个超时时间,都是用MAX_SCHEDULE_TIMEOUT。该时间指定了请求信号量的超时时间。请求成功返回0,如超时未获取信号量,返回-ETIME。
4 释放信号量
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);}如果wait_list为NULL,count++释放信号量;否则,不必释放信号量,直接移交给其他的task;需要处理wait_list。
static noinline void __sched __up(struct semaphore *sem){struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,struct semaphore_waiter, list); //找到第一个waiterlist_del(&waiter->list);waiter->up = true;wake_up_process(waiter->task);}
0 0
- Semaphore
- semaphore
- semaphore
- Semaphore
- Semaphore
- semaphore
- Semaphore
- semaphore
- Semaphore
- Semaphore
- Semaphore
- semaphore
- Semaphore
- Semaphore
- semaphore
- Semaphore
- semaphore
- Semaphore
- 动态链表初试(错误)
- Python 的 import 机制 《Python源码剖析》笔记
- ArchLinux安装VMware Tools
- c++ STL之map的个性(权哥)
- hdu2087剪花布条(kmp)
- semaphore
- 键盘按键对应的ASCII码值
- 动态规划入门之嵌套矩形
- SVM理论部分介绍
- linux文件操作--函数分类
- Canvas API初步学习
- 神经网络概述
- matlab中的imshow函数使用
- python 数据库