请教一下自旋锁实现的问题
不好意思,身上实在是没分了,以后再补吧体系结构arm,内核版本3.10.17,以下这段代码是arm中自旋锁的实现,网上资料太少了,实在没看懂这里是如何实现自旋锁的功能的
请懂的朋友帮帮忙,分确实少了,以后赚了分再给您,多谢
最好可以帮忙解释一下这段代码
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;
u32 newval;
arch_spinlock_t lockval;
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n"
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {/*目测这里是在自旋忙等,可是这里使用的判断条件和上面没有关系啊*/
wfe();
lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
}
smp_mb();
} 本帖最后由 arm-linux-gcc 于 2014-07-04 17:19 编辑
typedef struct {
union {
u32 slock;
struct __raw_tickets {
#ifdef __ARMEB__
u16 next;
u16 owner;
#else
u16 owner;
u16 next;
#endif
} tickets;
};
} arch_spinlock_t;
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;
u32 newval;
arch_spinlock_t lockval;
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n" 对next++
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {
wfe();
lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
}
smp_mb();
}
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
smp_mb();
lock->tickets.owner++; 对owner++
dsb_sev();
}
释放锁就会让owner++
持有锁就会让next++
用两个计数器分别来表示“释放次数”和“加锁次数”
当owner和next数量相等时,才说明当前线程成功的持有了锁
用两个计数器是出于性能考虑,这样就可以保证不同的cpu core不用竞争同一个地址,原因:
在arch_spin_lock里面使用了一个局部变量,于是不同执行流中的arch_spin_lock/arch_spin_unlock就不会写同一个cache line,
也就是不需要与别的core上的arch_spin_lock/arch_spin_unlock流程去竞争同一个cache line,
避免了两个core相互将对方的cache line write invalid的问题,于是就避免了cache miss的问题,从而保证了性能
回复 1# super皮波
请自行搜索ticket spinlocks @lwn.net 可用积分到底是用来干嘛的啊? 我感觉最大的用处就是可以参加竞拍
回复 4# arm-linux-gcc
兄弟,多谢了,按照你的回帖在网上找了下资料,弄明白了,再次感谢
回复 3# asuka2001
本帖最后由 asuka2001 于 2014-07-04 17:50 编辑
回复 2# arm-linux-gcc
两个计数器理解为:下一个人的“排队号”和当前的“呼叫号”更为确切些。
竞争锁就是去取这个排队号,然后把这个号原子性加1,防止其他人拿到和自己相同的排队号,然后坐等释放锁的人呼叫自己的排队号既可!
释放锁时将呼叫号加1,即当前持有锁的人已经服务完了,呼叫下一位排队等待的兄弟来拿锁!
页:
[1]