- 论坛徽章:
- 0
|
本帖最后由 wenlujon 于 2012-06-15 16:53 编辑
将"next"字段增加1.
080 static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
081 {
082 int tmp, new;
083
084 asm volatile("movzwl %2, %0\n\t" // 将lock->slock放到本地变量tmp中
085 "cmpb %h0,%b0\n\t" // 比较tmp的高8位和低8位,也就是"next"字段和"owner"字段,如果相等,ZF设置为1,否则ZF被设为0
086 "leal 0x100(%" REG_PTR_MODE "0), %1\n\t" // 将tmp得高8位或上0x100,其实就是将其高8位加1的值放到本地变量new中
087 "jne 1f\n\t" // 判断ZF标志位,如果0(就是说85行的结果是不相等),跳到89行,否则执行下一句
088 LOCK_PREFIX "cmpxchgw %w1,%2\n\t" // 尝试去获取锁。比较lock->slock和eax是否相等(其实就是tmp,因为tmp是放到eax里面的),但是84行不是已经将lock->slock放到tmp里面了吗?为何这里还需要再次比较? 原因是从84行到这行的这段时间,这个lock->slock可能被其他的processor修改。如果相等了,将new(注意new的高8位在86行相对其原来的值已经增加1了)放到lock->slock,说白了,就是原子性的将lock->slock的高8位加1,这个时候,锁被获取到。同时设置ZF为1;如果不相等的话,说明锁被其他processor获取了,ZF被设置为0,lock->slock的值放到EAX。
089 "1:" //
090 "sete %b1\n\t" // 如果ZF为1,也就是说锁被获取了,将new的低8位设置为1;如果ZF为0,表明不能获取锁,将new的低8位设置为0
091 "movzbl %b1,%0\n\t" // 将new的低8位放置在tmp,以返回给调用者
092 : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
093 :
094 : "memory", "cc");
095
096 return tmp;
097 }
碰到这种汇编,一个好的办法就是自己写一段程序,然后用GDB跟一下,看一下每个寄存器的变化,以及内存的变化。当然,ticket spinlock的原理也要比较清楚。。。。。。
|
|