现在的车载控制器,多核的MCU用的是越来越多了,对于不同核之间的共享数据保护,也是必须的,其中Spinlock就是常用的一种。
01.
Spinlock介绍
Spinlock也即自旋锁,是一种轻量级的多核间的数据同步机制。一个任务想要访问被Spinlock保护的共享资源,必须先得到锁,在访问完共享资源后释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有持有者, 那么需要自旋等待该锁的保持者释放了锁。
在ETAS的AUTOSAR中,实现Spinlock的两个基本操作获取锁xx_GetLockInternal()和释放锁xx_ReleaseLockInternal()。
对于获取锁接口,其内部的实现原理如下:
第一步先判断是哪个核上的任务正在使用xx_GetLockInternal();
判断锁是否已经被同当前核获取过但没有释放,如果是的话,就进行锁嵌套累加, 继续执行代码,如果没有被当前核获取过再进行下一步判断;
挂起正在使用xx_GetLockInternal()的当前核的中断,确保当前任务不被切换,也就是说不被高优先级任务或者中断任务打断;
测试锁的状态,该才做必须以原子操作访问Spinlock的锁标志。
如果锁状态被本核占用则进行锁嵌套,如果是其他核占用则首先释放该核中断, 然后重复执行上面两步测试锁的状态,直到其他核释放了锁。如果锁状态为空闲, 则设置其为占用状态,这就成功地抢占了锁。
对于释放锁接口,其内部的实现原理如下:
首先判断是哪个核上的线程正在使用xx_ReleaseLockInternal();
判断当前锁是否被该核占用,如果不是说明接口调用不匹配则复位,如果是则进行 下一步的判断;
判断锁是否被本核嵌套, 如果是则嵌套次数减减, 如果没有则清除锁的状态;
释放该核的中断。
02.
Spinlock使用原则
所有临界区代码都需要加锁保护,否则就达不到保护效果。也就是,访问共享资源的多个任务需要协同工作共同加锁才能保证不出错。在实际写代码时,有时会忘掉这个,导致出现各种稀奇古怪的问题,并且很难排查。
Spinlock保护的代码执行时间要尽量短, 因为临界区太大,持有时间太长,其他任务可能面临长时间等待,降低了系统性能。
Spinlock 所保护的代码在执行过程中不能睡眠, 任务在持有自旋锁时如果进入 Sleep状态,则可能导致死锁。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !