- 论坛徽章:
- 2
|
本帖最后由 OwnWaterloo 于 2010-08-01 04:16 编辑
列出一些ref供参考……
首先是趴出的linux的源代码:
- /* arch/x86/include/asm/alternative.h */
- #ifdef CONFIG_SMP
- #define LOCK_PREFIX_HERE \
- ".section .smp_locks,\"a\"\n" \
- ".balign 4\n" \
- ".long 671f - .\n" /* offset */ \
- ".previous\n" \
- "671:"
- #define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; "
- #else /* ! CONFIG_SMP */
- #define LOCK_PREFIX_HERE ""
- #define LOCK_PREFIX ""
- #endif
- /* arch/x86/include/asm/spinlock_types.h */
- typedef struct arch_spinlock {
- unsigned int slock;
- } arch_spinlock_t;
- /* arch/x86/include/asm/spinlock.h */
- #ifdef CONFIG_X86_32
- # define LOCK_PTR_REG "a"
- # define REG_PTR_MODE "k"
- #else
- # define LOCK_PTR_REG "D"
- # define REG_PTR_MODE "q"
- #endif
- #if defined(CONFIG_X86_32) && \
- (defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE))
- /*
- * On PPro SMP or if we are using OOSTORE, we use a locked operation to unlock
- * (PPro errata 66, 92)
- */
- # define UNLOCK_LOCK_PREFIX LOCK_PREFIX
- #else
- # define UNLOCK_LOCK_PREFIX
- #endif
- #define __always_inline
- #define static
- static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
- {
- short inc = 0x0100;
- asm volatile (
- LOCK_PREFIX "xaddw %w0, %1\n"
- "1:\t"
- "cmpb %h0, %b0\n\t"
- "je 2f\n\t"
- "rep ; nop\n\t"
- "movb %1, %b0\n\t"
- /* don't need lfence here, because loads are in-order */
- "jmp 1b\n"
- "2:"
- : "+Q" (inc), "+m" (lock->slock)
- :
- : "memory", "cc");
- }
- static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
- {
- int tmp, new;
- asm volatile("movzwl %2, %0\n\t"
- "cmpb %h0,%b0\n\t"
- "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
- "jne 1f\n\t"
- LOCK_PREFIX "cmpxchgw %w1,%2\n\t"
- "1:"
- "sete %b1\n\t"
- "movzbl %b1,%0\n\t"
- : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
- :
- : "memory", "cc");
- return tmp;
- }
- static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
- {
- asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
- : "+m" (lock->slock)
- :
- : "memory", "cc");
- }
复制代码 编译后的汇编代码:
- 00000000 <___ticket_spin_lock>:
- 0: 8b 54 24 04 mov edx,DWORD PTR [esp+0x4]
- 4: b8 00 01 00 00 mov eax,0x100
- 9: 66 0f c1 02 xadd WORD PTR [edx],ax
- d: 38 e0 cmp al,ah
- f: 74 06 je 17 <___ticket_spin_lock+0x17>
- 11: f3 90 pause
- 13: 8a 02 mov al,BYTE PTR [edx]
- 15: eb f6 jmp d <___ticket_spin_lock+0xd>
- 17: c3 ret
- 00000018 <___ticket_spin_trylock>:
- 18: 8b 54 24 04 mov edx,DWORD PTR [esp+0x4]
- 1c: 0f b7 02 movzx eax,WORD PTR [edx]
- 1f: 38 e0 cmp al,ah
- 21: 8d 88 00 01 00 00 lea ecx,[eax+0x100]
- 27: 75 04 jne 2d <___ticket_spin_trylock+0x15>
- 29: 66 0f b1 0a cmpxchg WORD PTR [edx],cx
- 2d: 0f 94 c1 sete cl
- 30: 0f b6 c1 movzx eax,cl
- 33: c3 ret
- 00000034 <___ticket_spin_unlock>:
- 34: 8b 44 24 04 mov eax,DWORD PTR [esp+0x4]
- 38: fe 00 inc BYTE PTR [eax]
- 3a: c3 ret
- 3b: 90 nop
复制代码 可以看出, trylock还是使用了cmpxchg , 也就是InterlockedCompareExchange。
最后是xadd 和cmpxchg |
|