Introduce riscv osqlock. (WIP)
riscv function
先看会被osq_lock使用到的riscv的函数。
__xchg
__xchg
函数在 arch/riscv/include/asm/cmpxchg.h
中。
1 | #define __xchg(ptr, new, size) \ |
使用amo指令完成。
__cmpxchg_release
__cmpxchg_release
函数在 arch/riscv/include/asm/cmpxchg.h
中。
1 | #define __cmpxchg_release(ptr, old, new, size) \ |
使用lrsc指令完成,代码逻辑是:
- 从ptr地址中lr 一个值到__ret中
- 判断是否与old相等
- 如果与old值不等,则跳到1f,退出函数,并返回__ret
- 如果与old值相等,则执行sc,把new写进ptr
- 如果sc返回值不等于0,也就是sc失败,跳回0,重试lr
- 如果sc返回值等于0,也就是sc成功,退出函数,返回__ret
osq_lock
osq_lock的代码在kernel的源码如下位置
1 | kernel/locking/osq_lock.c |
1 | /* |
osq_lock使用两个数据结构维护:
optimistic_spin_queue
,里面就一个变量:- tail,用来指示最后一个cpu是谁。0表示没有cpu,1表示cpu0
optimistic_spin_node
,里面是:- 一个双向链表,用来维护所有申请锁的cpu node
- locked,1表示占住了锁,0表示未占住锁
- cpu,cpu的id。0表示没有cpu,1表示cpu0.
1 | bool osq_lock(struct optimistic_spin_queue *lock) |
1 | void osq_unlock(struct optimistic_spin_queue *lock) |
1 | /* |
总结来看,当只有一个cpu来抢锁时,只用optimistic_spin_queue
来维护,它保存了cpuid;当多个cpu抢锁时,就需要用optimistic_spin_queue
和optimistic_spin_node
配合维护,tail中保存最后一个申请锁的cpu,node用链表将所有申请的cpu链接起来。