Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux PCIe驱动程序对MSI具有周期性的长延迟_Linux_Latency_Pci E_Irq_Isr - Fatal编程技术网

Linux PCIe驱动程序对MSI具有周期性的长延迟

Linux PCIe驱动程序对MSI具有周期性的长延迟,linux,latency,pci-e,irq,isr,Linux,Latency,Pci E,Irq,Isr,我已经为Linux v4.1.15(非抢占)创建了一个PCIe驱动程序,其中包含一个IRQ,该IRQ由FPGA的MSI生成。我的ISR是: static irq_handler int_handler(int irq, void* dev_id, struct pt_regs* regs) { spin_lock(&my_lock); msi_counter++; spin_unlock(&my_lock); return (irq_handle

我已经为Linux v4.1.15(非抢占)创建了一个PCIe驱动程序,其中包含一个IRQ,该IRQ由FPGA的MSI生成。我的ISR是:

static irq_handler int_handler(int irq, void* dev_id, struct pt_regs* regs)
{
    spin_lock(&my_lock);
    msi_counter++;
    spin_unlock(&my_lock);

    return (irq_handler_t) IRQ_HANDLED;
}
MSI从FPGA(Cyclone V)每隔300秒发送一次,我的ISR发射速度非常快,并且处理无误(延迟<5秒)。问题是,大约每3秒(抖动相对较小的3秒)我的ISR延迟就会跳到大约1.5毫秒到2毫秒;这是通过改变我的ISR将一个值写回FPGA并监视FPGA的一个引脚来测量的。
msi_计数器的
spin_lock
仅用于我的代码中的另一个位置,但仅用于以与我的ISR递增计数器相同的方式递减计数器。我使用的是1 GHz的iMX6四核CPU,系统使用的是裸体Yocto映像(核心映像最小),因此CPU上没有运行任何东西。CPU连接到的唯一其他硬件是以太网,但发送的数据很少,数据更新频率超过3秒

问题:
  • 我如何确定Linux为什么会周期性地增加 我的ISR
  • 我可以做些什么来减少延迟
其他资料:
  • 我已将传递到
    request\u irq()
    的标志更改为
    IRFQ\u NO\u SUSPEND
    |IRFQ_NO_THREAD
    ,以及其他值,似乎没有任何东西可以修复 这种周期性的延迟会增加

  • 另外,当我查看
    cat/proc/interrupts
    时,它显示只有核心0 (四个核心中的第一个)是运行ISR的唯一核心。我 我不知道这是否有任何意义,但我认为这是值得的 提到

  • 从FPGA到CPU的数据每MSI传输一次(每300 us传输一次),传输数据的时间为稳定的17 us。没有数据从CPU发送到FPGA
最终解决方案:
我创建了一个PREEMPT\u RT内核映像,并创建了我的ISR
request\u irq()
,带有标志
IRQF\u NO\u SUSPEND | IRQF\u NO\u THREAD | IRQF\u perpu
。我还将
spin\u lock
替换为
atomic\u t
,最大的改进来自PREEMPT\u RT。我现在的平均延迟约为12 us。

您可以在spin\u lock前后添加计时器。如果时间差超过某个阈值,则增加另一个时间。您可以计算由于自旋锁导致的延迟频率。如果它与您看到延迟的频率相匹配,那么您可以尝试找出另一个锁夹不释放它的原因。它在持有锁时会被抢占吗


另一件需要研究的事情是,自旋锁本身是否需要很长时间,概率很低,但不是零?

如果Inc和dec都是您所需要的,您可以使用
原子类型来避免自旋锁。还可以尝试移除自旋锁,以查看延迟是否存在,或者是否在等待运行的IRQ处理程序中。然后考虑使用F跟踪或LTTNG来查看IRQ处理之前运行的内容。@ TrTP-当我有机会的时候,我会给他们两个机会。你认为旋转锁真的是个问题吗?我认为
spin_lock
速度很快,从未导致ISR休眠。计时器的想法很有趣,但它不适用于我的应用程序,因为MSI在数据准备就绪时到达,所以当数据准备就绪时,我需要CPU和FPGA之间的某种“握手”。虽然我正在考虑用你的定时器想法来看看
spin\u lock
是否会被抢占。我对
spin_lock
了解不多,但我认为它不受抢占。我的意思是,持有锁的另一个线程可能在持有锁时被抢占。至于另一个建议,自旋锁平均来说是快的。但它有一个非零方差(因为它在旋转)。这意味着它有可能(以低概率)花费比你能容忍的时间更长的时间。