spinlock_t的结构体分3层,arch_spinlock_t为最底层跟架构相关。
typedef struct spinlock {
union {
struct raw_spinlock rlock;
。。。
};
} spinlock_t;
typedef struct raw_spinlock {
arch_spinlock_t raw_lock;
。。。
} raw_spinlock_t;
typedef struct {
union {
u32 slock;
struct __raw_tickets {
#ifdef __ARMEB__ /* 大端 */
u16 next;
u16 owner;
#else
u16 owner;
u16 next;
#endif
} tickets;
};
} arch_spinlock_t;
spinlock的原理就是比较next和owner。目的是保证唤醒的公平性,先到先唤醒,后到后唤醒。过程类似银行取号办业务,第一个客户从next变量中取一个号码,他的next==0,他会一直保存该号码牌直到业务办理完成;无论该客户是否能立马办理业务,都会将next加1,即其他客户取的号码只能排在他后面,所以如果有多个客户,他们获取到的编号依次为0,1,2,3,…;工作人员办理业务首先呼叫0号,对应号码的客户办理业务;办理完成后工作人员再呼叫2号,依次类推…。
-
CPU0 获取lock
1.1.保存当前的next和owner到局部变量
1.2.将全局next加1.
1.3.比较旧的next和owner,如果相等,表示获取lock成功,继续执行。 -
CPU1 获取lock
2.1.保存当前参数:next=1,owner=0
2.2.将全局变量next加1.
2.3.比较保存的next和owner,因为不等,所以执行wfe指令进入低功耗
2.4.如何被其他cpu唤醒了,会再次将保存的next和全局的owner做比较:
2.4.1.如果相等,则继续往下执行
2.4.2.如果不等,则再次执行WFE进入低功耗等带自己的叫号。 -
CPU0 释放lock
3.1.将全局变量lock.tickets.owner加1(叫号下一个).
3.2.执行sev指令,唤醒所有进入低功耗的CPU对onwer和next的操作采用独占指令,并且获取spinlock前会关闭抢占功能,释放spinlock执行使能抢占功能
调用spin_lock函数最后会调用arch_spin_lock函数:
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;
u32 newval;
arch_spinlock_t lockval;
prefetchw(&lock->slock);
__asm__ __volatile__(
"1: ldrex %0, [%3]\n" /* 保存lock->slock也就是lock->tickets.owner 和lock->tickets.next */
" add %1, %0, %4\n" /* 高16位加一 */
" strex %2, %1, [%3]\n" /* 回写到lock->slock */
" teq %2, #0\n" /* 保证strex指令成功 */
" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
: "cc");
/* 通过while循环来检查是否轮到该cpu获得lock */
while (lockval.tickets.next != lockval.tickets.owner) {
wfe();
lockval.tickets.owner = READ_ONCE(lock->tickets.owner); /* 每次从低功耗醒来获取最新的owner值 */
}
smp_mb();
}
arch_spin_lock函数在多CPU模式下主要做两件事:
1.获取保存lock->tickets.next
2.lock->tickets.next加1
3.判断更新前的next和owner
4.如果不等,则调用wfe指令进入低功耗
5.如果相等,则执行smp_mb
释放lock的底层函数:
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
smp_mb();
lock->tickets.owner++;
dsb_sev();
}
lock->tickets.owner++;语句用于叫号下一个进程或者cpu
dsb_sev函数会执行sev指令,唤醒所有低功耗的cpu