Chinaunix首页 | 论坛 | 博客
  • 博客访问: 241240
  • 博文数量: 30
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 300
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-26 17:22
个人简介

linux初学者~

文章分类

全部博文(30)

文章存档

2017年(9)

2016年(6)

2015年(6)

2014年(9)

我的朋友

分类: LINUX

2014-02-27 19:17:46


点击(此处)折叠或打开

  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表示内存,=,&等在都有描述。

  • 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,而是直接返回。
阅读(3355) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:ubuntu IPv4 pppoe服务器搭建

给主人留下些什么吧!~~