信号量semaphore的相关函数

申请信号量的函数有

1.void down(struct semaphore *sem)

2.int down_interruptible(struct semaphore *sem)

3.int down_killable(struct semaphore *sem)

4.int down_trylock(struct semaphore *sem)

5.int down_timeout(struct semaphore *sem, long timeout)

先跟第一个函数down()

code:

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);
}
EXPORT_SYMBOL(down);

这里主要看下raw_spin_lock_irqsave 和down函数

static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
    unsigned long flags;

    local_irq_save(flags);
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    /*  
     * On lockdep we dont want the hand-coded irq-enable of
     * do_raw_spin_lock_flags() code, because lockdep assumes
     * that interrupts are not re-enabled during lock-acquire:
     */
#ifdef CONFIG_LOCKDEP
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
#else
    do_raw_spin_lock_flags(lock, &flags);
#endif
    return flags;                                                                                                                              
}

这里主要干了3个事,一个是保存中断状态 一个是禁止内核抢占,再一个就是获取锁

看到网上说这个函数也会关闭中断,但是没看到相应的关中断的操作,这个有点不明白,不知道是不是关中断的操作再local_irq_save()里已经做了,这是个疑问,也就是说raw_spin_lock_irqsave: 保存进入临界区前的中断状态,关闭本地中断,获取锁。

再继续看do_raw_spin_lock_flags这个函数

252 void do_raw_spin_lock(raw_spinlock_t *lock)                                                                                                
253 {
254     debug_spin_lock_before(lock);
255     if (unlikely(!))
256         __spin_lock_debug(lock);
257     debug_spin_lock_after(lock);
258 } 

最终跑到了这里arch_spin_trylock(&lock->raw_lock)

再回头看看 __down(sem);

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 = false;

    for (;;) {
        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;

 interrupted:
    list_del(&waiter.list);
    return -EINTR;
}

 

 

 加粗的地方,设置当前线程状态为TASK_UNINTERRUPTIBLE,然后释放锁,因为后面试图获取信号量的进程申请不到的时候,会进入休眠,所以再这里休眠之前要释放之前这里申请的锁  raw_spin_lock_irqsave(&sem->lock, flags);最后执行schedule_timeout()进行进入等待信号量,重新得到执行时会  从新获取锁raw_spin_lock_irq,主要是接着raw_spin_lock_irqrestore().

对于信号量中锁的操作,在raw_spin_lock_irqsave 和   raw_spin_unlock_irq 最后都是条用到arch_spin_lock  arch_spin_unlock,也就是说再休眠等待之前,把之前的锁要给释放。

有些地方不是很明白,先记录下。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值