Eva*_*van 14 c real-time smp linux-kernel
我有一个小的Linux内核模块,它是用于尚不存在的硬件的设备驱动程序的原型.代码需要从开始到结束尽可能快地执行一小段计算,持续时间为几微秒.我试图用intel rdtscp指令测量是否可以使用ndelay()模拟计算的调用.我发现它有99.9%的时间按预期运行,但0.1%的时间它有一个非常大的延迟,好像其他东西正在抢占代码,尽管在一个应该禁用中断的自旋锁内运行.这是使用库存Ubuntu 64位内核(4.4.0-112)运行的,没有额外的实时或低延迟补丁.
下面是一些复制此行为的示例代码.这是作为/proc文件系统条目的处理程序编写的,以便于测试,但我只显示了实际计算延迟的函数:
#define ITERATIONS 50000
#define SKIPITER 10
DEFINE_SPINLOCK(timer_lock);
static int timing_test_show(struct seq_file *m, void *v)
{
uint64_t i;
uint64_t first, start, stop, delta, max=0, min=1000000;
uint64_t avg_ticks;
uint32_t a, d, c;
unsigned long flags;
int above30k=0;
__asm__ volatile ("rdtscp" : "=a" (a), "=d" (d) : : "rcx");
first = a | (((uint64_t)d)<<32);
for (i=0; i<ITERATIONS; i++) {
spin_lock_irqsave(&timer_lock, flags);
__asm__ volatile ("rdtscp" : "=a" (a), "=d" (d) : : "rcx");
start = a | (((uint64_t)d)<<32);
ndelay(1000);
__asm__ volatile ("rdtscp" : "=a" (a), "=d" (d) : : "rcx");
stop = a | (((uint64_t)d)<<32);
spin_unlock_irqrestore(&timer_lock, flags);
if (i < SKIPITER) continue;
delta = stop-start;
if (delta < min) min = delta;
if (delta > max) max = delta;
if (delta > 30000) above30k++;
}
seq_printf(m, "min: %llu max: %llu above30k: %d\n", min, max, above30k);
avg_ticks = (stop - first) / ITERATIONS;
seq_printf(m, "Average total ticks/iteration: %llu\n", avg_ticks);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我跑:
# cat /proc/timing_test
min: 4176 max: 58248 above30k: 56
Average total ticks/iteration: 4365
Run Code Online (Sandbox Code Playgroud)
这是在3.4 GHz沙桥生成Core i7上.TSC的~4200刻度大约适用于1微秒以上的延迟.大约0.1%的时间我看到延迟比预期长10倍,在某些情况下我看到的时间长达120,000个.
这些延迟似乎太长而不能成为单个高速缓存未命中,即使对于DRAM也是如此 所以我认为它要么是几个缓存未命中,要么是在我的关键部分中间抢占CPU的另一个任务.我想了解可能的原因,看看它们是否是我们可以消除的东西,或者我们是否必须转向自定义处理器/ FPGA解决方案.
我尝试过的事情:
rdmsron 读取SMI中断计数MSR_SMI_COUNT.我尝试在之前和之后添加,并且在我的代码执行时没有发生SMM中断.ndelay()考虑了可变时钟速度,但我认为CPU时钟只变化2倍,所以这不应该导致> 10倍的变化.您在极端情况下观察到的 120,000 个刻度听起来很像 SMM 处理程序。较小的值可能是由各种微体系结构事件引起的(顺便说一句,您检查了所有可用的性能计数器吗?),但这一定是由没有编写他的/的人编写的子例程引起的她的代码实现了最小延迟。
但是您声明您已检查没有观察到 SMI。这让我认为要么是内核设施有问题来计数/报告它们,要么是您的管理方法有问题。在没有硬件调试器的情况下寻找 SMI 可能是一项令人沮丧的工作。