OS多核多线程锁记录笔记

自旋锁作用

      自旋锁的是为了保护两个核上的公共资源,也就是全局变量,只有在一方也就是一个核抢到了自选锁,才能对公共资源进行操作修改,当然还有其他形似的锁如互斥锁,这里不比较两者的区别,以前没有深入的去了解自旋锁的底层实现,只是简单调用。

自旋锁原理

     自旋锁的底层实现原理其实是用到了各个架构比较交换的汇编指令,英飞凌的TriCore架构为

CMPSWAP.W,ARM架构虽然没有比较交换指令,但是通过关闭preempt_disable禁止抢占来实现原子操作。

数据总线

      数据总线的一些基本概念这里就不提出来再讲了。有一个细节是在总线上同一时刻只能有一个主设备控制总线传输操作。而对于多核来说也是如此,他们需要互相争抢总线的使用权,而这一现象又能帮助我们实现一些原子操作。

总线操作

    使用总线对数据进行操作的时候并不是全部都能一次完成的,有时候可能需要多个操作才能实现我们编程中看似简单的操作,而在找个时候就不一定能满足我们的原子性了。

TriCore架构自旋锁实现

boolean IfxCpu_acquireMutex(IfxCpu_mutexLock *lock)
{
    boolean         retVal;
    volatile uint32 spinLockVal;

    retVal      = FALSE;

    spinLockVal = 1UL;
    spinLockVal =
        (uint32)__cmpAndSwap(((unsigned int *)lock), spinLockVal, 0);

    /* Check if the SpinLock WAS set before the attempt to acquire spinlock */
    if (spinLockVal == 0)
    {
        retVal = TRUE;
    }

    return retVal;
}

/** \brief This function is a implementation of a binary semaphore using compare and swap instruction
 * \param address address of resource.
 * \param value This variable is updated with status of address
 * \param condition if the value of address matches with the value of condition, then swap of value & address occurs.
 *
 */
IFX_INLINE unsigned int Ifx__cmpAndSwap (unsigned int volatile *address,
           unsigned int value, unsigned int condition)
{
  unsigned long long reg64
    = value | (unsigned long long) condition << 32;

  __asm__ __volatile__ ("cmpswap.w [%[addr]]0, %A[reg]"
                        : [reg] "+d" (reg64)
                        : [addr] "a" (address)
                        : "memory");
    return reg64;
}

   这段代码的逻辑及其简单,就是去查找我们lock变量的值是否为0,如果为0便把它赋值为1,并且返回成功抢到锁的信息。而有一个操作是值得关注的。__cmpAndSwap() 这一操作为什么能保证原子性并且能做到对变量进行加锁的呢?这里使用了汇编语言对芯片进行操作,而cmpswap.w操作正是我们在数据手册中找到的新指令。而正如注释说这一个指令能比较两个地址中的值是否相同,并完成交换。

   cmpswap.w等效如下代码:

tmp = *x;      //#tmp address的值
if(*x == z)       // # z为condition
{
    *x = y;    //#*address = values;
}
else
{
  *x = tmp;
}
return tmp

PowerPC架构自旋锁实现 

static inline uint32 aSpinlock_Hal_Swap(uint32 Addr, register uint32 Value)
{
	uint32 result;
	register uint32 temp1,temp2;
	__asm__ __volatile__
	(
	  /* prepare the decoration for the SWAP instruction */
	  "mr    %[temp11], %[Value]"        "\n"  /* load value in r6 */
	  "e_lis    %[temp22], 0x5000"    "\n"  /* r5 = 0x50000000 */
	  "se_or    %[temp11], %[temp22]"        "\n"  /* Value = Value | r5 */
	  /* lwdcbx -> Load Word Decorated with Cache Bypass */
	  "lwdcbx   %[result], %[temp11], %[Addr]"  "\n"  /* SWAP Addr with r3 */
	  : [result] "=r" (result)
	  : [Addr] "b" (Addr), [temp11]"r" (temp1), [temp22]"r" (temp2) , [Value]"r" (Value)
			: "cc"
		);
		return result;
}

     参考文档:

  Aurix/Tricore实验分享之103: 硬件mutex指令|英飞凌开发者技术社区

  TriCore架构多核多线程锁探究(TC264双核互斥锁)-CSDN博客

   https://www.cnblogs.com/DoOrDie/p/9265754.html

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水火汪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值