FreeBSDの割り込み周りに足りないと思う機能
ぼくは10GbEの割り込み周り(MSI-Xによりコア毎に独立したIRQを持つ)とかに興味を持っていたので、以前からこれがかなり気になってたんだが、まずはこれを見て欲しい。
Linux
IRQ毎に各CPUの割り込み回数が取れるよね。
$ cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 0: 55 0 0 0 IO-APIC-edge timer 1: 92 0 0 0 IO-APIC-edge i8042 5: 0 0 0 0 IO-APIC-edge parport0 6: 2 0 0 0 IO-APIC-edge floppy 8: 1 0 0 0 IO-APIC-edge rtc0 9: 0 0 0 0 IO-APIC-fasteoi acpi 12: 149 0 0 0 IO-APIC-edge i8042 14: 0 0 0 0 IO-APIC-edge ata_piix 15: 192 0 0 0 IO-APIC-edge ata_piix 16: 0 0 0 0 IO-APIC-fasteoi vmwgfx, snd_ens1371 17: 5088 0 0 50 IO-APIC-fasteoi ehci_hcd:usb1, ioc0 18: 149 0 0 0 IO-APIC-fasteoi uhci_hcd:usb2 19: 195 0 0 0 IO-APIC-fasteoi eth0 40: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 41: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 42: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 43: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 44: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 45: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 46: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 47: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 48: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 49: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 50: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 51: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 52: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 53: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 54: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 55: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 56: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 57: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 58: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 59: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 60: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 61: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 62: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 63: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 64: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 65: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 66: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 67: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 68: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 69: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 70: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 71: 0 0 0 0 PCI-MSI-edge PCIe PME, pciehp 72: 0 0 0 0 PCI-MSI-edge vmci 73: 0 0 0 0 PCI-MSI-edge vmci NMI: 0 0 0 0 Non-maskable interrupts LOC: 3328 3158 2543 3122 Local timer interrupts SPU: 0 0 0 0 Spurious interrupts PMI: 0 0 0 0 Performance monitoring interrupts IWI: 0 0 0 0 IRQ work interrupts RTR: 0 0 0 0 APIC ICR read retries RES: 1626 2065 1404 1944 Rescheduling interrupts CAL: 457 2074 600 1412 Function call interrupts TLB: 471 521 388 505 TLB shootdowns TRM: 0 0 0 0 Thermal event interrupts THR: 0 0 0 0 Threshold APIC interrupts MCE: 0 0 0 0 Machine check exceptions MCP: 1 1 1 1 Machine check polls ERR: 0 MIS: 0
IRQ毎の割り込み先CPUを設定出来るよね(この場合はIRQ72の設定を表示していて、0x4=cpu2に割り込み、と設定されてる。irqbalanceの仕業でしょうね。)。
$ sudo cat /proc/irq/72/smp_affinity 00000000,00000004
デフォルトで全CPUに公平に割り込みをまくようになっていて(値が0xffとかになってる)、CPU間の不公平がないようにしてあるし、irqbalanceってデーモンがCPU負荷を見ながらこの値をうまく調整してくれる。
10GbEのMSI-XみたいにCPUごとにIRQを持つ場合は、そのNICのIRQだけ特別扱いして、それぞれのIRQに割り込み先を設定出来るようになってる。
この辺は幾度と無く解説してるはずだから、皆もう知ってるよね。
参考資料
FreeBSD
IRQ毎の割り込み回数になっちゃってるよね。
どのCPUなのか、わかんないよねこれ。
$ sudo vmstat -i interrupt total rate irq1: atkbd0 56 0 irq6: fdc0 95 0 irq14: ata0 704289 3 irq15: ata1 491895 2 irq16: uhci0 400566 1 irq17: mpt0 ehci0 16 0 irq18: em0 22122134 96 cpu0:timer 11350955 49 cpu1:timer 5166995 22 Total 40237001 175
割り込み先CPUの設定はどうすんねん、って思って調べた所、cpuset(1)でIRQとCPUを指定すれば出来そうである。
On-line Manual of "cpuset"
が…カーネル側のコードを良く見てみよう。
fxr.watson.org: sys/kern/kern_cpuset.c
CPU_LEVEL_ROOT(全CPU指定)・CPU_LEVEL_CPUSET(複数CPU指定)の時はEINVALである(このへん)。もうこの時点でアウツなんだが…
気を取り直してCPU_LEVEL_WITCH(1CPU指定)の場合をみてみる。
fxr.watson.org: sys/kern/kern_intr.c
あ〜…うん…これ…割り込み先CPUの設定じゃなくて、割り込みスレッドの実行先CPUの設定だね。似ているようで全然違うね。
つまり、割り込まれた後に起動するスレッドの実行先CPUは選べても、割り込み先CPUを変える術は用意されてないよね、これ。
あかんがな(完)