Locking 检测程序代码何时尝试获取自旋锁的方法

Locking 检测程序代码何时尝试获取自旋锁的方法,locking,scheduling,deadlock,atomic,Locking,Scheduling,Deadlock,Atomic,优先级反转是一个常见且有点陈旧的问题。那些处理操作系统进程调度的人,特别是在有实时需求的情况下,都很熟悉它。对于这个问题,很少有著名的解决方案,每种解决方案都有其优缺点: 禁用所有中断以保护关键部分 优先权上限 优先继承 随机增压 选择哪种方法来处理优先级反转并不重要;考虑到应用程序使用定义良好的接口来同步共享资源,所有这些都相对容易在操作系统内核中实现。例如,如果进程使用锁定互斥锁,那么操作系统很清楚这一事实,因为该函数在深层次上执行系统调用(即在Linux上)。当内核服务于这个请求时,它

优先级反转是一个常见且有点陈旧的问题。那些处理操作系统进程调度的人,特别是在有实时需求的情况下,都很熟悉它。对于这个问题,很少有著名的解决方案,每种解决方案都有其优缺点:

  • 禁用所有中断以保护关键部分
  • 优先权上限
  • 优先继承
  • 随机增压
选择哪种方法来处理优先级反转并不重要;考虑到应用程序使用定义良好的接口来同步共享资源,所有这些都相对容易在操作系统内核中实现。例如,如果进程使用锁定互斥锁,那么操作系统很清楚这一事实,因为该函数在深层次上执行系统调用(即在Linux上)。当内核服务于这个请求时,它完全清楚地知道谁在等待什么,并且可以决定如何最好地处理优先级反转

现在,假设内核不知道进程何时锁定/解锁互斥锁。例如,如果使用原子CPU指令实现互斥锁(如“无锁”算法),就可能发生这种情况。然后,低优先级进程就有可能获取锁,并由于高优先级任务而暂停执行。然后,当一个更高优先级的任务被调度时,它只会烧掉试图锁定“旋转锁”的CPU。那样的僵局会使整个系统毫无用处

考虑到上述场景以及我们无法将程序更改为不使用原子操作来同步对共享资源的访问这一事实,问题归结为检测代码何时尝试这样做

我有一些模糊的启发性想法,既难以实现,又可能产生误报。这是:

  • 每隔一段时间查看一次寄存器,并尝试检测代码是否只是在一个紧密的循环中烧坏了CPU。如果代码在该位置被发现N次,则暂停该进程,让其他优先级较低的进程有机会运行并解锁互斥锁。这种方法离理想太远,并且会产生太多的误报
  • 对进程可以运行的时间有严格限制。这会立即降低调度器的硬实时功能,但它可以工作。然而,问题是,在“死锁”情况下,高优先级进程将浪费其所有时间窗口来获取繁忙的资源
  • 我不知道这是否可能,但另一个想法是拦截/插入原子CPU指令,让调度器知道锁定/解锁尝试。换句话说,本质上是将原子CPU操作转换为某种系统调用。其机制与MMU发出页面错误信号时如何创建虚拟页面映射有几分相似

  • 你对上述想法有何看法?你还能想到其他什么方法来检测这样的代码呢?

    虽然我仍然对你的设置提出疑问(见评论),但我认为你的第三种方法最有希望,因为它提供了最精确的信息。 我可以找出遵循主要思想的两种机制:

  • 假设:你知道锁的地址。您可以通过检查二进制文件在系统中的典型自旋锁模式来找到它们,例如,
    循环:CMPXCHG,JRZ循环

    然后,将
    标记为“缺失”或“不可访问”,并挂接MMU服务例程
  • 假设:您还可以更改二进制文件的文本段。
    然后,您可以通过调用常规互斥锁或一些自己的簿记例程(实际锁定除外)来交换关键自旋锁
  • 作为策略,您应该选择优先级上限而不是优先级继承,因为它避免了死锁作为副作用。您可以应用它,因为您知道线程的(潜在)锁

    对于更详细的解决方案,需要更多关于硬件、操作系统和工具链的信息


    此外,请注意,使用atomar用户级自旋锁的基本方法可能不适用于当今的几种内存一致性模型。

    我认为您的选项1可能比您认为的更有价值。我假设您有几个可能需要监视的进程,并且您不知道自旋锁的目标地址

    与随机外部采样相比,您可能会发现挂接调度器入口点并在此时收集统计信息更容易,优势在于您位于进程地址空间中,并且缓存很热。我对linux调度器了解不多,但过去在OpenVMS上做过类似的事情。调度程序通常有两个入口点,一个是自愿的(等待IO等),另一个是非自愿的,自旋锁问题几乎总是非自愿的,所以这应该会降低您的工作效率

    显然,现在你有了中断的PC,但似乎Intel芯片也有一些可以使用的性能监控计数器,BTS(分支跟踪存储)和PEB,但这些在性能方面可能是“非免费”的。诸如分支跟踪之类的信息将很快显示紧密循环,然后您可以使用这些信息来检查导致循环的实际指令(同样,已经在缓存中),并查看它是条件原子指令还是“正常”工作,例如对数组求和

    如果您没有编写代码,那么非联锁指令也可能以某种方式被使用,希望不是这样

    虽然我认为一些芯片上的监控功能在这方面确实有帮助,但你也可以简单地检查pc在上个M计划周期结束时是否大致相同,并强制它跳过一个周期,非常简单,但没有针对性

    虽然您可以将所有这些作为第二个进程查看,但它可能没有基于调度器的方法响应快,尽管可能