wait queue 2
2017-01-14 17:40
281 查看
除了使用DEFINE_WAIT 来定义wait queue后,还可以使用init_waitqueue_entry 来初始化wait queue
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
q->flags = 0;
q->private = p;
q->func = default_wake_function;
}
这两者的却别是DEFINE_WAIT 的回调函数是
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
int ret = default_wake_function(wait, mode, sync, key);
if (ret)
list_del_init(&wait->task_list);
return ret;
}
这个函数除了调用default_wake_function外,还会调用list_del_init来将wait->task_list 的所有list删掉,并重新初始化.
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
还可以调用init_wait_entry 来初始化,这个就和DEFINE_WAIT一模一样了.
void init_wait_entry(wait_queue_t *wait, int flags)
{
wait->flags = flags;
wait->private = current;
wait->func = autoremove_wake_function;
INIT_LIST_HEAD(&wait->task_list);
}
如果wakeup 后的task还要满足某个条件才能执行的话,就不能直接调用prepare_to_wait 。而应调用wait_event
#define wait_event(wq, condition) \
do { \
might_sleep(); \
if (condition) \
break; \
__wait_event(wq, condition); \
} while (0)
我们再来看看__wait_event的实现
#define __wait_event(wq, condition) \
(void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0, \
schedule())
#define ___wait_event(wq, condition, state, exclusive, ret, cmd) \
({ \
__label__ __out; \
wait_queue_t __wait; \
long __ret = ret; /* explicit shadow */ \
\
init_wait_entry(&__wait, exclusive ? WQ_FLAG_EXCLUSIVE : 0); \
for (;;) { \
long __int = prepare_to_wait_event(&wq, &__wait, state);\
\
if (condition) \
break; \
\
if (___wait_is_interruptible(state) && __int) { \
__ret = __int; \
goto __out; \
} \
\
cmd; \
} \
finish_wait(&wq, &__wait); \
__out: __ret; \
})
注意cmd就是schedule()
这个___wait_event 首先调用init_wait_entry 来初始化wait queu,也就是说使用wait_event的话,前面调用wait queue的初始化过程都可以省了.
由于这个条件可能wakup好多次只有才能满足,因此这里用了for的死循环。
然后会调用prepare_to_wait_event 将wait queue加入到wait_queue_head_t 中
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
unsigned long flags;
long ret = 0;
spin_lock_irqsave(&q->lock, flags);
if (unlikely(signal_pending_state(state, current))) {
/*
* Exclusive waiter must not fail if it was selected by wakeup,
* it should "consume" the condition we were waiting for.
*
* The caller will recheck the condition and return success if
* we were already woken up, we can not miss the event because
* wakeup locks/unlocks the same q->lock.
*
* But we need to ensure that set-condition + wakeup after that
* can't see us, it should wake up another exclusive waiter if
* we fail.
*/
list_del_init(&wait->task_list);
ret = -ERESTARTSYS;
} else {
if (list_empty(&wait->task_list)) {
if (wait->flags & WQ_FLAG_EXCLUSIVE)
__add_wait_queue_tail(q, wait);
else
__add_wait_queue(q, wait);
}
set_current_state(state);
}
spin_unlock_irqrestore(&q->lock, flags);
return ret;
}
从prepare_to_wait_event 这个函数可知原来WQ_FLAG_EXCLUSIVE 是的作用是将wait queue降到到wait_queue_head_t的最后呀
其次调用
#define ___wait_is_interruptible(state) \
(!__builtin_constant_p(state) || \
state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \
来判断当前task的状态不能为TASK_RUNNING和TASK_INTERRUPTIBLE和 TASK_KILLABLE。如果已经是这三个state中的一个,且__int不为NULL,也就是
long __int = prepare_to_wait_event(&wq, &__wait, state) 执行成功了。就直接返回,这个时候就说明在在prepare_to_wait_event
中调用set_current_state(state);来设置task的状态failed了,这个时候就只有报错返回了.
如果前面执行顺利,就调用cmd也就是就是schedule()让出当前cpu,因为当前task的state已经不是running状态了,肯定要让出cpu.
如果wakeup后且条件满足,也即执行下面的code
if (condition) \
break; \
返回,最后调用finish_wait。
如果条件不满足,继续从for循环开始执行,过程和上面的类似.也就是prepare_to_wait_event 会被执行多次,所以才会调用init_wait_entry,让autoremove_wake_function没执行一次,就删除一次wait->task_list
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
q->flags = 0;
q->private = p;
q->func = default_wake_function;
}
这两者的却别是DEFINE_WAIT 的回调函数是
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
int ret = default_wake_function(wait, mode, sync, key);
if (ret)
list_del_init(&wait->task_list);
return ret;
}
这个函数除了调用default_wake_function外,还会调用list_del_init来将wait->task_list 的所有list删掉,并重新初始化.
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
还可以调用init_wait_entry 来初始化,这个就和DEFINE_WAIT一模一样了.
void init_wait_entry(wait_queue_t *wait, int flags)
{
wait->flags = flags;
wait->private = current;
wait->func = autoremove_wake_function;
INIT_LIST_HEAD(&wait->task_list);
}
如果wakeup 后的task还要满足某个条件才能执行的话,就不能直接调用prepare_to_wait 。而应调用wait_event
#define wait_event(wq, condition) \
do { \
might_sleep(); \
if (condition) \
break; \
__wait_event(wq, condition); \
} while (0)
我们再来看看__wait_event的实现
#define __wait_event(wq, condition) \
(void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0, \
schedule())
#define ___wait_event(wq, condition, state, exclusive, ret, cmd) \
({ \
__label__ __out; \
wait_queue_t __wait; \
long __ret = ret; /* explicit shadow */ \
\
init_wait_entry(&__wait, exclusive ? WQ_FLAG_EXCLUSIVE : 0); \
for (;;) { \
long __int = prepare_to_wait_event(&wq, &__wait, state);\
\
if (condition) \
break; \
\
if (___wait_is_interruptible(state) && __int) { \
__ret = __int; \
goto __out; \
} \
\
cmd; \
} \
finish_wait(&wq, &__wait); \
__out: __ret; \
})
注意cmd就是schedule()
这个___wait_event 首先调用init_wait_entry 来初始化wait queu,也就是说使用wait_event的话,前面调用wait queue的初始化过程都可以省了.
由于这个条件可能wakup好多次只有才能满足,因此这里用了for的死循环。
然后会调用prepare_to_wait_event 将wait queue加入到wait_queue_head_t 中
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
unsigned long flags;
long ret = 0;
spin_lock_irqsave(&q->lock, flags);
if (unlikely(signal_pending_state(state, current))) {
/*
* Exclusive waiter must not fail if it was selected by wakeup,
* it should "consume" the condition we were waiting for.
*
* The caller will recheck the condition and return success if
* we were already woken up, we can not miss the event because
* wakeup locks/unlocks the same q->lock.
*
* But we need to ensure that set-condition + wakeup after that
* can't see us, it should wake up another exclusive waiter if
* we fail.
*/
list_del_init(&wait->task_list);
ret = -ERESTARTSYS;
} else {
if (list_empty(&wait->task_list)) {
if (wait->flags & WQ_FLAG_EXCLUSIVE)
__add_wait_queue_tail(q, wait);
else
__add_wait_queue(q, wait);
}
set_current_state(state);
}
spin_unlock_irqrestore(&q->lock, flags);
return ret;
}
从prepare_to_wait_event 这个函数可知原来WQ_FLAG_EXCLUSIVE 是的作用是将wait queue降到到wait_queue_head_t的最后呀
其次调用
#define ___wait_is_interruptible(state) \
(!__builtin_constant_p(state) || \
state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \
来判断当前task的状态不能为TASK_RUNNING和TASK_INTERRUPTIBLE和 TASK_KILLABLE。如果已经是这三个state中的一个,且__int不为NULL,也就是
long __int = prepare_to_wait_event(&wq, &__wait, state) 执行成功了。就直接返回,这个时候就说明在在prepare_to_wait_event
中调用set_current_state(state);来设置task的状态failed了,这个时候就只有报错返回了.
如果前面执行顺利,就调用cmd也就是就是schedule()让出当前cpu,因为当前task的state已经不是running状态了,肯定要让出cpu.
如果wakeup后且条件满足,也即执行下面的code
if (condition) \
break; \
返回,最后调用finish_wait。
如果条件不满足,继续从for循环开始执行,过程和上面的类似.也就是prepare_to_wait_event 会被执行多次,所以才会调用init_wait_entry,让autoremove_wake_function没执行一次,就删除一次wait->task_list
相关文章推荐
- 模拟Vue之数据驱动2
- easyui-datagrid获取行和列数据
- restful Api 风格契约设计器:Swagger-editor和swagger-ui的应用
- SQL Server ->> SQL Server 2016新特性之 --- Query Store
- 1056. Mice and Rice (25)-PAT甲级真题(queue的用法)
- wait queue 1
- 第一个Hello Vue!
- Android开发基础知识整理之UI与Fragment
- AndroidStudio导入项目一直卡在Building gradle project info最快速解决方案
- 使用SoapUI快速创建mock
- Reclerview下拉刷新,上拉加载更多
- HDU 1242 Rescue(BFS优先队列)
- IOS动画和各种监听总结UIGestureRecognizer
- ios UIImageView处理图片大小问题
- vue-cli
- vue里面v-bind和Props 利用props绑定动态数据
- 免费ARP(Gratuitous ARP)的介绍
- uefi bds boot flow
- ZOJ 2587 && ACdream1235 Unique Attack(判断最小割是否唯一)
- 洛谷 P1373 小a和uim之大逃离