在内核中,常看到这样的代码: int locked;
locked = xchg(&kexec_lock, 1);
在 include/asm-i386/cmpxchg.h 中,有如下定义: #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
75 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
76 {
77 switch (size) {
78 case 1:
79 __asm__ __volatile__("xchgb %b0,%1"
80 :"=q" (x)
81 :"m" (*__xg(ptr)), "" (x)
82 :"memory");
83 break;
84 case 2:
85 __asm__ __volatile__("xchgw %w0,%1"
86 :"=r" (x)
87 :"m" (*__xg(ptr)), "" (x)
88 :"memory");
89 break;
90 case 4:
91 __asm__ __volatile__("xchgl %0,%1"
92 :"=r" (x)
93 :"m" (*__xg(ptr)), "" (x)
94 :"memory");
95 break;
96 }
97 return x;
98 }
先看看什么是__typeof__。__typeof__(x)返回x的类型,并在编译时用返回的类 型进行替换。看一个例子:int a;
__typeof__(a) b;
相当于int b;
由于具有这样的硬类型替换,因此被大量用到宏中。
接下来再看看xchg,xchg在i386中是被用来交换两个数据。来看以下下面的内联 汇编: __asm__ __volatile__("xchgl %0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "" (x)
:"memory");
想要看懂这样的汇编语句,需要知道一点AT&T的汇编语法和GCC的内联汇编语法。 "=r" (x)表明X将作为结果的输出。r和=都是操作限定符号。r表示可以使用任何 寄存器,而=表示这是一个输出操作,并且是只写的。
而这里的输入则是ptr和x,其中,%0指向x,而%1指向ptr. m是内存操作限定符 号,它表示跳过寄存器直接对内存操作。
最后一行的memory表示我们的操作是在一个不可预知的内存区域上进行的。
因此,上面的汇编语句就是输入两个数,然后交换这两个数,并把交换后的一个 写回变量中。
但是,仅仅交换两个数,就用汇编来实现,难道只是为了效率?