你知道底层自旋锁是如何实现的吗



我们在开发中,经常会用到自旋锁,对于使用接口来讲,仿照例子谁都会用,但是你知道其是如何实现自旋的吗?今天我们就来讨论一下其实现原理。

1、首先,我们需要实现一个结构体用于自旋锁的使用

     typedef struct spinlock{

                volatile unsigned int slock;

     }spinlock_t;

      接下来我们就要定义接口了;


2、接口实现

    (1)初始化接口

             #define  spin_lock_init(lock)   \

                 do{  \

                     ((spinlock_t *)lock)->slock = 0x0;   \      /*相当于赋初值*/

                }while(0)

      (2)上锁接口

               static  inline void spin_lock(spinlock_t *lock)

              {

                       raw_spin_lock(&lock->slock);

              }

         (3)释放锁

               static inline spin_unlock(spinlock_t *lock)

               {

                      raw_spin_unlock(&lock->slock);

               }


3、更底层汇编实现

       大家可以看到上边上锁和解锁都调用了另外两个函数,这两个函数才是自旋锁的精华所在,下边我们来具体讨论一下


        raw_spin_lock:

                  mov  r1,#1         @1-->r1

                  DSB

               take_again:

                  LDREX     r2,[r0]            @把r0的内容赋给r2,同时置全局标志exclusive

                  STREX     r3,r1,[r0]        @尝试将r1写入到锁里边,首先检查exclusive是否存在,如果存在则将r1-->r0,r3 = 0,并清除exclusive标志,否则1--->r3,结束

                  TEQ         r3,#0

                  BNE       take_again

                  TEQ        r2,#0

                  BNE       take_again

                  MOV       pc,lr                @返回


         raw_spin_unlock:

                DSB

                MOV r1,#0

                STR  r1,[r0,#0]                  @为0,标示锁已释放

                DSB

                MOV  pc,lr


         经过这两段代码,是不是对自旋锁的实现更加清晰明了了?


4、如果想在自旋锁的同时锁中断和开中断怎么办呢?只需要在获取锁和释放锁接口里加上类似于local_irq_save和local_irq_restore之类的中断控制函数即可

你可能感兴趣的:(android/linux内核,arm/汇编)