avatar

Catalog
ARM ASM code

ARM的spinlock

OS homework 4

c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
* ARMv6 ticket-based spin-locking.
*
* A memory barrier is required after we get a lock, and before we
* release it, because V6 CPUs are assumed to have weakly ordered
* memory.
*/
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"
" 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 = READ_ONCE(lock->tickets.owner);
}

smp_mb();
}

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
smp_mb();
lock->tickets.owner++;
dsb_sev();
}
  • prefetch: 该指令用于把将要使用到的数据从主存提前装入缓存中,以减少访问主存的指令执行时的延迟。arm64prefetch用于手工执行预抓取,其是通过gcc内置的函数, 通过汇编实现的,主要用于提升性能。prefetch定义在incude/linux/prefetch.h中。prefetch 用于读预取,prefetchw 用于写预取。

    参考:arm64的prefetch/prefetchw/spin_lock_prefetch

  • volatile__asm__ 用来声明一个内联汇编表达式, __volatile__ 则是向GCC 声明不允许对该内联汇编优化。内嵌汇编语法如下:__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)(破坏描述符用于通知编译器我们使用了哪些寄存器或内存)。

    参考:asm volatile内嵌汇编用法简述,也可见 [Arm instruction set reference guide](https://static.docs.arm.com/100076/0100/arm_instruction_set_ reference_guide_100076_0100_00_en.pdf)

  • smp_mb():即barrier(),在拿到锁之后和放掉锁之前添加barrier,是为了避免在拿到锁之前修改critical section里面的数据。也就是执行顺序必须是先拿锁 ,再执行critical section,最后放锁。

Author: Yiwen Zhang
Link: http://bessss-zyw.github.io/2021/04/24/about-asm-code/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶