atomic_add实现分析(mips架构)


点击(此处)折叠或打开

  1. /*
  2.  * atomic_add - add integer to atomic variable
  3.  * @i: integer value to add
  4.  * @v: pointer of type atomic_t
  5.  *
  6.  * Atomically adds @i to @v.
  7.  */
  8. static __inline__ void atomic_add(int i, atomic_t * v)
  9. {
  10.     if (cpu_has_llsc && R10000_LLSC_WAR) {
  11.         int temp;

  12.         __asm__ __volatile__(
  13.         "    .set    mips3                    \n"
  14.         "1:    ll    %0, %1        # atomic_add        \n"
  15.         "    addu    %0, %2                    \n"
  16.         "    sc    %0, %1                    \n"
  17.         "    beqzl    %0, 1b                    \n"
  18.         "    .set    mips0                    \n"
  19.         : "=&r" (temp), "=m" (v->counter)
  20.         : "Ir" (i), "m" (v->counter));
  21.     } else if (cpu_has_llsc) {
  22.         int temp;

  23.         __asm__ __volatile__(
  24.         "    .set    mips3                    \n"
  25.         "1:    ll    %0, %1        # atomic_add        \n"
  26.         "    addu    %0, %2                    \n"
  27.         "    sc    %0, %1                    \n"
  28.         "    beqz    %0, 2f                    \n"
  29.         "    .subsection 2                    \n"
  30.         "2:    b    1b                    \n"
  31.         "    .previous                    \n"
  32.         "    .set    mips0                    \n"
  33.         : "=&r" (temp), "=m" (v->counter)
  34.         : "Ir" (i), "m" (v->counter));
  35.     } else {
  36.         unsigned long flags;

  37.         raw_local_irq_save(flags);
  38.         v->counter += i;
  39.         raw_local_irq_restore(flags);
  40.     }
  41. }

在我的系统上,使用的是中间那段代码,看懂这段代码需要了解如下3个方面的知识:
  1. mips架构下C语言内嵌汇编语言的格式;
  2. mips下ll和sc指令的用法;
  3. .subsection和.previous指令的用法。


下面分别介绍相关的知识:
  • mips架构下C语言内嵌汇编语言的格式
asm (     
        "assembly code" 
        : output_operand               /* 输出参数列表 */ 
        : input_operand                   /* 输入参数列表 */ 
        : clobbered_operand               /* 被改变的操作对象列表 */ 
    );
    gcc内嵌汇编扩展格式如上所示,依次分别为汇编代码,输出参数列表,输入参数列表,被改变的操作列表。所有项目都是可选的(汇编代码为空的例子:barrier指令),atomic_add函数没有最后一项,最后一项的意思是告诉gcc,在汇编代码中除了可能会修改输入和输出参数,还会修改其他参数,以免gcc误判。
    汇编代码中的%0,%1,%2表示从输出参数开始,按顺序给所有参数的标号,这里temp就是%0, v->counter为%1, i为%2。另外还有很多符号,r表示寄存器(temp经过r修饰,存入寄存器中),m表示内存,=,&等在 http://wenku.baidu.com/view/c395bcec172ded630b1cb65c.html都有描述。

  • mips下ll和sc指令的用法
    这2条指令的用法在see mips run中的8.5.2节有详细描述,需要注意的是,如果能保证原子操作,那么sc指令成功,%0被置为1,如果不能,则sc指令执行失败,%0被转为0,所以代码中通过判断%0是否为0来决定是否需要跳转到2f处进而跳转到1b处重复atomic_add操作。

  • .subsection和.previous指令的用法
    个人理解,.subsection和.previous是成对出现的,两者中间的代码会被存放到另外的代码段中,也就是说, beqz %0, 2f不跳转到2时,它的后一条指令不是2: b 1b,而是直接返回。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值