ThreadX内核源码分析(SMP) - 核间通信(arm)

1、ThreadX核间通信介绍

        多核情况下,一个核可能改变另外一个核的执行状态,例如一个核挂起另外一个核正在执行的线程,如果没有机制通知另外一个核该线程被挂起的话,那么被挂起的线程就感知不到自己被挂起了;ThreadX内核使用SGI中断,从一个核发送一个中断信号到目的核上去,从而使另外一个核产生中断,另外一个核就会去检查状态变化,例如是否要重新调度(别的核改变了该核需要执行的线程)。

2、发生SGI中断

        参考《ARMv8-A_Architecture_Reference_Manual_(Issue_A.a).pdf》"D8.6.28 ICC_SGI1R_EL1, Interrupt Controller Software Generated Interrupt group 1 Register
"。

        ICC_SGI1R_EL1寄存器如下,24~27位为中断ID(SGIID),0~15位为目标cpu,每一位代表一个cpu:

 ThreadX内核使用0号中断进行核间通信,发送核间中断函数为"void _tx_thread_smp_core_preempt(UINT core)",参数core即为目标cpu id,_tx_thread_smp_core_preempt只给一个核发送中断,实现代码如下:

    .global  _tx_thread_smp_core_preempt
    .type    _tx_thread_smp_core_preempt, @function
_tx_thread_smp_core_preempt:
    DSB ISH
#ifdef TX_ARMV8_2
    MOV x2, #0x1                                // Build the target list field
    LSL x3, x0, #16                             // Build the affinity1 field
    ORR x2, x2, x3                              // Combine the fields
#else
    MOV x2, #0x1                                //
    LSL x2, x2, x0                              // Shift by the core ID // x2 = 1 << core
#endif
    MSR ICC_SGI1R_EL1, x2                       // Issue inter-core interrupt
    RET

简化成c代码就是“ICC_SGI1R_EL1 = 1 << core”,只设置了target list,因为_tx_thread_smp_core_preempt发送的是0号中断,因此SGIID默认0即可。

下图所示为从核2发送中断到核3,左上角窗口的"ARM_Cortex-A72_2 #2 stoped on stepi"为当前调试的核,也就是单步执行指令的核,右上角窗口显示的是当前核的寄存器列表,x0也就是_tx_thread_smp_core_preempt的参数0(core),core就是3,也就是要从核2发送中断到核3:

3、IRQ中断处理

        ThreadX的中断处理函数为irqHandler,ThreadX官网提供的样例只处理了核间中断和定时器中断,有这两个中断就可以让ThreadX内核正常运行起来。irqHandler主要就是读取中断号,找到对应的中断处理函数并调用中断处理函数,中断响应,代码如下:

void irqHandler(void)
{
  unsigned int ID;

  ID = getICC_IAR1(); // readIntAck();

  // Check for reserved IDs
  if ((1020 <= ID) && (ID <= 1023))
  {
      //printf("irqHandler() - Reserved INTID %d\n\n", ID);
      return;
  }

  switch(ID)
  {
    case 34: // 定时器中断(34),线程时间片以及应用程序定时器需要用到
      // Dual-Timer 0 (SP804)
      //printf("irqHandler() - External timer interrupt\n\n");
      nudge_leds();
      clearTimerIrq(); // 清除中断

      /* Call ThreadX timer interrupt processing.  */
      _tx_timer_interrupt(); // 定时器中断处理函数

      break;

    default: // 其他中断不处理(返回)
      // Unexpected ID value
      //printf("irqHandler() - Unexpected INTID %d\n\n", ID);
      break;
  }

  // Write the End of Interrupt register to tell the GIC
  // we've finished handling the interrupt
  setICC_EOIR1(ID); // writeAliasedEOI(ID); // 中断结束
}

        核间中断走的是default分支,没有对应的处理函数,真正起作用的是在中断返回的时候检查是否需要重新调度,发送核间中断的作用基本就是为了让目标cpu重新调度;在整个代码中可以看到,在调用_tx_thread_smp_core_preempt函数之前,基本都是改变了_tx_thread_execute_ptr[i],i为目标cpu,_tx_thread_smp_core_preempt及发送到id为i的cpu上面去。

        如下图所示,_tx_thread_current_ptr[3]为核3上面正在运行的线程(核2挂起的线程,核2只是把该线程的状态等改变了,但是并没有让该线程退出执行),_tx_thread_execute_ptr[3]为下一个要执行的线程(核2挂起核3上正在执行的线程,选择核3上下一个需要调度的线程,并设置_tx_thread_execute_ptr[3]),在SGI中断退出的时候,检查到_tx_thread_execute_ptr[3]与_tx_thread_current_ptr[3]不相等,就会保存_tx_thread_current_ptr[3]的上下文,也就是将_tx_thread_current_ptr[3]换出cpu,从而真正将线程_tx_thread_current_ptr[3]挂起。

 4、中断恢复

        不管是SGI还是普通中断,中断退出时都会检查是否需要重新调度线程,SGI一般都是为了重新调度,普通中断也可能触发重新调度,所以中断退出都要检查一下是否需要重新调度,主要实现如下图,x8是cpu ID(当前是3),x0是核上当前执行的线程,x2是当前核下一个需要调度的线程,也就是上一小结的_tx_thread_execute_ptr[3]、_tx_thread_current_ptr[3],如果不相等就要进行线程切换,需要调度_tx_thread_execute_ptr[3]。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux SMP(Symmetric Multi-Processing)是一种在多处理器系统中运行的操作系统。该操作系统支持多个处理器心之间的并行处理,能够更高效地利用系统资源,提升整体性能。 Linux SMP源码分析是对Linux SMP操作系统的内部实现进行深入研究和解析。其目的是理解和掌握Linux SMP操作系统的工作原理与心机制,以便于进行系统调优和性能优化。 进行Linux SMP源码分析的过程中,首先要了解Linux SMP操作系统的基本结构和组成部分。这包括内核、进程调度器、内存管理器、文件系统等模块。然后,通过阅读和分析内核源代码,深入了解每个模块的实现细节和相互之间的关联关系。 在分析Linux SMP源代码的过程中,需要关注以下几个关键点: 1. 处理器调度:了解Linux SMP是如何进行多个处理器心之间的任务调度和负载均衡的。需要分析调度算法和策略,以及与进程管理器的交互过程。 2. 内存管理:分析内核是如何进行多心的内存管理和共享内存的管理。需要了解页面置换算法、缓存一致性和锁机制等相关知识。 3. 进程间通信:探究Linux SMP是如何实现多心之间的进程间通信。需要研究信号量、互斥锁、条件变量等IPC机制的实现细节。 4. 文件系统:深入研究Linux SMP对文件系统的支持。了解多心环境下的文件并发访问和文件系统缓存等相关内容。 通过对Linux SMP源码的详细分析,可以更好地理解和掌握操作系统的工作原理和机制,提高系统的性能和稳定性。此外,深入研究Linux SMP源码还可以为开发者提供更大的灵活性和自定义能力,实现定制化的功能和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值