" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {------------(5)
wfe();-------------------------------(6)
lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);------(7)
}
smp_mb();------------------------------(8)
}
(1)和preloading cache相关的操作,主要是为了性能考虑
(2)将slock的值保存在lockval这个临时变量中
(3)将spin lock中的next加一
(4)判断是否有其他的thread插入。更具体的细节参考Linux内核同步机制之(一):原子操作中的描述
(5)判断当前spin lock的状态,如果是unlocked,那么直接获取到该锁
(6)如果当前spin lock的状态是locked,那么调用wfe进入等待状态。更具体的细节请参考ARM WFI和WFE指令中的描述。
(7)其他的CPU唤醒了本cpu的执行,说明owner发生了变化,该新的own赋给lockval,然后继续判断spin lock的状态,也就是回到step 5。
(8)memory barrier的操作,具体可以参考memory barrier中的描述。
arch_spin_lock函数ARM64的代码(来自4.1.10内核)如下:
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned int tmp;
arch_spinlock_t lockval, newval;
asm volatile(
/* Atomically increment the next ticket. */
" prfm pstl1strm, %3\n"
"1: ldaxr %w0, %3\n"-----(A)-----------lockval = lock
" add %w1, %w0, %w5\n"-------------newval = lockval + (1 << 16),相当于next++
" stxr %w2, %w1, %3\n"--------------lock = newval
" cbnz %w2, 1b\n"--------------是否有其他PE的执行流插入?有的话,重来。
/* Did we get the lock? */
" eor %w1, %w0, %w0, ror #16\n"--lockval中的next域就是自己的号码牌,判断是否等于owner
" cbz %w1, 3f\n"----------------如果等于,持锁进入临界区
/*
* No: spin on the owner. Send a local event to avoid missing an
* unlock before the exclusive load.
*/
" sevl\n"
"2: wfe\n"--------------------否则进入spin
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-77053-7.html
最贵的车由马云出品
全世界都知道美国是中东乱局始作俑者
还有哪个品牌在做这个芝麻糊不就知道了
男女比例失调正常因为重男轻女