内核同步机制API之__down_common

__down_common这个函数主要处理上一节博客中讲述的API中对sem->count 小于零的case的处理.
可以看到下面这些函数都调用了__down_common,只是第二个和第三个形参有所不同
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 timeout)
{
	return __down_common(sem, TASK_UNINTERRUPTIBLE, timeout);
}
其源码分析如下:
static inline int __sched __down_common(struct semaphore *sem, long state,
								long timeout)
{
	struct semaphore_waiter waiter;
	#定义一个semaphore_waiter,并将这个waiter添加到sem中的wait_list这个链表中
	list_add_tail(&waiter.list, &sem->wait_list);
	#对waiter赋值,这里为啥不先赋值然后在添加到sem的wait_list中呢?

	waiter.task = current;
	waiter.up = false;

	for (;;) {
	#监视是否有形参指定的信号量在pending,有的话就删除waiter.list 然后返回被中断
		if (signal_pending_state(state, current))
			goto interrupted;
	#超时时间小于零,说明已经超时了,同样删除waiter.list后,返回超时时间导致函数退出
		if (unlikely(timeout <= 0))
			goto timed_out;
	#设置当前task为形参指定的状态,例如TASK_UNINTERRUPTIBLE/TASK_INTERRUPTIBLE/TASK_KILLABLE
		__set_current_state(state);
		raw_spin_unlock_irq(&sem->lock);
		#在timeout这段时间内让出当前cpu 
		timeout = schedule_timeout(timeout);
		raw_spin_lock_irq(&sem->lock);
		#正常的退出出口在这里面。当waiter.up为true时,正确退出.
		if (waiter.up)
			return 0;
	}

 timed_out:
	list_del(&waiter.list);
	return -ETIME;

 interrupted:
	list_del(&waiter.list);
	return -EINTR;
}
可以看到不同的down_xx 函数区别在于是否会被信号量中断,是否超时等。默认down这个函数在sem->count小于零时调用的是
static noinline void __sched __down(struct semaphore *sem)
{
	__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}
可以看到在无法获取信号量时。系统会一直让出cpu,且当前task无法timeout,无法被signal 唤醒,因此正常情况下一般不适用down这个函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值