免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4085 | 回复: 13
打印 上一主题 下一主题

[内核同步] 感觉wait_event这里还是会有race condition [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-21 21:52 |只看该作者 |倒序浏览
  1. #define __wait_event(wq, condition)                     \                       
  2. do {                                    \                                       
  3.     DEFINE_WAIT(__wait);                        \                              
  4.                                     \                                          
  5.     for (;;) {                          \                                       
  6.         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \                                                                                                                                            
  7.         if (condition)                      \                                   
  8.             break;                      \                                       
  9.         schedule();                     \                                       
  10.     }                               \                                          
  11.     finish_wait(&wq, &__wait);                  \                              
  12. } while (0)
复制代码
上面是__wait_event代码,假如A进程准备进入for循环时,B进程使条件成立了,并且唤醒了一下这个wait queue,
但是A还没有加到wait queue上,因此A不知请,会继续执行prepqre_to_wait。
假设A刚执行完prepare_to_wait之后还没来得及再次检查condition就被抢占了,那A岂不是永远回不来了?
除非其他进程再次唤醒?

不知道我哪里理解的有问题,请各位大侠指点迷津!
谢谢!

论坛徽章:
0
2 [报告]
发表于 2012-05-21 22:15 |只看该作者
假设A刚执行完prepare_to_wait之后还没来得及再次检查condition就被抢占了,那A岂不是永远回不来了?
  1. void fastcall
  2. prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
  3. {
  4.     unsigned long flags;
  5.     wait->flags &= ~WQ_FLAG_EXCLUSIVE;
  6.     spin_lock_irqsave(&q->lock, flags);
  7.     if (list_empty(&wait->task_list))
  8.         __add_wait_queue(q, wait);
  9.     if (is_sync_wait(wait))
  10.         set_current_state(state);
  11.     spin_unlock_irqrestore(&q->lock, flags);
  12. }
复制代码
把进程设置成了不可中断了。我觉得它会或者条件成立,或者被schedule()

论坛徽章:
0
3 [报告]
发表于 2012-05-21 22:21 |只看该作者
回复 2# 怪怪虎


    楼上意思是当进程状态为TASK_UNINTERRUPTABLE时,不会被抢占?

论坛徽章:
0
4 [报告]
发表于 2012-05-21 22:43 |只看该作者
回复 1# skyrim


    看看PREEMPT_ACTIVE是怎么用的。你说的这种情况下即便被抢占,它也不会因此被踢出运行队列的,也就是说还是会自动被调度回来的。

论坛徽章:
0
5 [报告]
发表于 2012-05-21 23:02 |只看该作者
回复 1# skyrim

刚执行完prepare_to_wait然后发生抢占,跟自己主动调schedule()效果是一样的啊。自己调schedule()怎么回来的,被抢占之后就是怎么回来的。
TASK_UNINTERRUPTIBLE状态下schedule()会被从rq里面remove掉,只能是被wake_up重新加入rq的。
   

论坛徽章:
0
6 [报告]
发表于 2012-05-21 23:04 |只看该作者
本帖最后由 honkiko 于 2012-05-21 23:09 编辑

回复 4# 灌水菜鸟


current->state不为零(TASK_RUNNING)的情况下,schedule()中切换到其他进程之后,本进程应该会被踢出运行队列的(deactivate_task)。

论坛徽章:
0
7 [报告]
发表于 2012-05-22 00:12 |只看该作者
回复 4# 灌水菜鸟


    哦,有点印象了,记得以前看过Robert love讲这个PREEMPT_ACTIVE的作用的,再找找去

论坛徽章:
0
8 [报告]
发表于 2012-05-22 00:16 |只看该作者
找着了,分享下。
确实,当进程状态在TASK_INTERRUTPABLE等状态时如果被抢占不会被踢出调度队列。

On Thu, 2004-03-18 at 14:51, Julien.Soula@lifl.fr wrote:
> the PREEMPT_ACTIVE flag set by preempt_schedule() or during return of
> interrupt / exception / syscall. And it's tested in schedule() to
> avoid some operations like deactivate_task().
>
> Our purpose is to force deactivation of the task. So we planned to set
> task state to TASK_INTERRUPTIBLE value and then to call
> schedule(). However the PREEMPT_ACTIVE flag can prevent it.
>
> So what is the significance of the PREEMPT_ACTIVE flag and the test in
> schedule() ?
It lets a task be preempted when state != TASK_RUNNING. By preventing
the task from being deactivated, it can be rescheduled correctly.
Otherwise, a task that was, say, TASK_INTERRUPTIBLE could be preempted
before it put itself on a wait queue.
Marking the task that is preempted is a simple solution to the race.
If you want to force the deactivation of the task, there is really no
difference. Set it to TASK_INTERRUPTIBLE, do whatever you need to do,
and call schedule().
PREEMPT_ACTIVE is unrelated to what you want to do.
        Robert Love

论坛徽章:
0
9 [报告]
发表于 2012-05-22 09:14 |只看该作者
Set it to TASK_INTERRUPTIBLE, do whatever you need to do, and call schedule().
>>>貌似设置成TASK_INTERRUPTIBLE后,它 和 schedule()之间的code,不会被抢占。 真是这样吗?

论坛徽章:
0
10 [报告]
发表于 2012-05-22 10:02 |只看该作者
回复 8# skyrim


    个人建议:能用汉语尽量用汉语,用大家的母语进行交流是对大家的一种尊重。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP