免费注册 查看新帖 |

Chinaunix

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

请问一个驱动代码逻辑问题,高手请进 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-04 15:16 |只看该作者 |倒序浏览
/**
* srpt_set_cmd_state() - Set the state of a SCSI command.
* @new: New state to be set.
*
* Does not modify the state of aborted commands. Returns the previous command
* state.
*/
enum srpt_command_state srpt_set_cmd_state(struct srpt_ioctx *     ioctx,
                                                  enum srpt_command_state new)
{
    enum srpt_command_state previous;

    BUG_ON(!ioctx);
    WARN_ON(new == SRPT_STATE_NEW);

    do
    {
        previous = atomic_read(&ioctx->state);
    } while ((previous != SRPT_STATE_DONE)
             && atomic_cmpxchg(&ioctx->state, previous, new) != previous);

    return previous;
}
按正常说,这段代码执行应该没有什么问题,atomic_read和atomic_cmpxchg都能执行成功。
但是为什么要用do while语句来实现呢?说明确实存在循环的可能吗?会不会出现死循环呢?
因为我在中断上下文执行的时候,出了一次NMI的WATCHDOG复位,也就是在中断中执行时间太长了,
会不会是这里在某种情况下死循环呢?如果不是,为什么这里要写出do while呢,完全可以用if啊!
(当然也有可能是执行中断中的其他部分代码的时间太长导致NMI复位的)

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2012-06-04 15:26 |只看该作者
看不懂,但 cmpxchg 和 循环 是一对好基友,达到非锁原子操作

论坛徽章:
0
3 [报告]
发表于 2012-06-04 15:29 |只看该作者
谢谢楼上的回复,但是这里貌似已经调用的是atomic_cmpxchg啊!为什么还要循环呢,奇怪了

论坛徽章:
0
4 [报告]
发表于 2012-06-04 15:34 |只看该作者
(previous != SRPT_STATE_DONE)不用管它,这个表示如果读出来是处于done的状态的话,就直接退出了,不在去改变它的状态
那就相当于变成:
    do
    {
        previous = atomic_read(&ioctx->state);
    } while ( atomic_cmpxchg(&ioctx->state, previous, new) != previous);
先原子读该状态,然后传入atomic_cmpxchg函数,该函数会重新读ioctx->state得状态,然后和previous比较,如果相等,就修改
为新的状态new,并且返回旧有的状态(即previous)。
这样看起来两次都读的同一个变量,肯定相等了,然后肯定就会修改为new的状态,并返回previous的状态,应该是一次就可以执行成功啊
为什么需要do while的循环呢?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
5 [报告]
发表于 2012-06-04 15:46 |只看该作者
仔细看了一下
关于你的问题,这正是需要atomic的地方,因为可能多个进程在同时操作,atomic_read 和 atomic_cmpxchg 之间,可能被别的进程给 atomic_cmpxchg 了。

论坛徽章:
0
6 [报告]
发表于 2012-06-04 15:53 |只看该作者
回复 5# bruceteen


    谢谢,我看内核里面也有许多类似的应用
/**
*        sysfs_get_active - get an active reference to sysfs_dirent
*        @sd: sysfs_dirent to get an active reference to
*
*        Get an active reference of @sd.  This function is noop if @sd
*        is NULL.
*
*        RETURNS:
*        Pointer to @sd on success, NULL on failure.
*/
static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
{
        if (unlikely(!sd))
                return NULL;

        while (1) {
                int v, t;

                v = atomic_read(&sd->s_active);
                if (unlikely(v < 0))
                        return NULL;

                t = atomic_cmpxchg(&sd->s_active, v, v + 1);
                if (likely(t == v))
                        return sd;
                if (t < 0)
                        return NULL;

                cpu_relax();
        }
}
可以看到if (likely(t == v)),既然都likely了,说明一般情况下应该是都能成功的对吧!那应该是不会出现死循环的,即使有两个线程在操作这个原子变量,应该
不可能刚好大家都在死循环来修改这个值吧!

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
7 [报告]
发表于 2012-06-04 16:05 |只看该作者
不会死循环的,总会有一个进程通过
就像一群人不排队上厕所一样,马桶不可能空着,即需要上厕所的人数会一直减少,不会有人永远上不了厕所
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP