Comment forcer le kernel Linux à "figer" (ou presque figer) pendant quelques centaines de millisecondes

Nous exécutons un process en time réel sur un kernel non time réel (CentOS 6), et cela ne va probablement pas changer.

Nous avons une application de video en streaming qui nécessite environ 500 Mo / s de trafic PCIe à partir d'un FPGA personnalisé en continu pendant 1,5 heure à la fois. L'application fonctionne plutôt bien – la plupart du time. Cependant, nous avons eu des situations où il semble que le kernel ne répond plus à la maintenance des requests PCIe ou memory jusqu'à 500 millisecondes à la fois. Cela semble se produire pendant l'E / S bursty d'un autre thread. J'ai trouvé impossible d'essayer de reproduire ce problème en faisant juste beaucoup d'E / S fictives depuis l'espace user pendant que l'application principale est en cours d'exécution.

Existe-t-il un moyen de forcer (simuler) un «gel» global du kernel Linux (en particulier, arrêter PCIe ou tous les access memory DDR3 ou quelque chose comme ça) pour que nous puissions reproduire ce problème?

Nous avons mis en memory tampon jusqu'à 10 millisecondes dans la memory FPGA interne, mais cela ne suffit pas. Nous pouvons tamponner à FPGA DDR3 et puis vider à l'hôte, mais nous avons besoin d'une méthode pour tester cette nouvelle fonctionnalité sous la contrainte.

Nous ne voulons pas que le kernel gèle ou se verrouille définitivement. Nous aimerions pouvoir définir l'intervalle de time.

Sentez-vous libre d'expliquer la solution comme je suis un novice quand il s'agit de quelque chose de Linux lié au kernel.

Je suis à la search de quelque chose comme écrire temporairement des valeurs magiques dans /proc/sys/vm qui ramènerait le système virtuellement, puis revenir après quelques centaines de millisecondes, mais regarder le nombre de façons possibles de le briser n'est pas pour un débutant comme moi ( https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Peut-être une numactl magie numactl ?

Une option pour faire un test rapide pourrait être d'utiliser un kernel activé KGDB et d'arrêter le kernel manuellement et de tester, voir ce lien .

Sur une autre note, les choses dont je me souviens pourraient causer vos pauses:

  • cpufreq cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latency , la valeur est en ns (4000 dans mon processeur AMD FX ™ -8120 Eight-Core) ne devrait pas être un problème, mais vérifier
  • L'étranglement thermique soit le cpu lui-même ou le module de régulateur de tension.
  • NAPI et / ou trafic réseau lourd
  • PCIe ASPM ( cat /sys/module/pcie_aspm/parameters/policy )
  • Contention dans les tampons de votre périphérique de destination (disque dur, nic …)
  • Bug dans le firmware de certains périphériques du bus PCIe (même si vous ne l'utilisez pas), vous pouvez essayer de les éteindre avec /sys/bus/pci/devices/$DEVICE/power/control

Pouvons-nous avoir plus de détails sur la façon dont votre application communique avec le FPGA? Est-ce l'application qui lit le tampon du FPGA, ou le FPGA qui envoie l'interruption au kernel (comme les maps réseau)?

Je m'attends à ce qu'il ouvre un bloc / char dans / dev, puis communique avec lui. Cela signifie qu'il utilise un pilote pour faire la communication entre l'application et le file / dev / XXX.

J'aimerais avoir la sortie de: cat /proc/interrupts ; lsmod ; ls -al /dev/yourmod

Voici les idées:

  • S'il est déclenché par une interruption, vous pouvez définir le PIC des CPU pour désactiver l'IRQ correspondante, puis le réactiver. Cela entraînera l'ignorance de chaque requête de la carte (sans que la carte en soit consciente).
  • si c'est comme une lecture de tampon, vous pouvez:
    • Mettez votre application en état de veille, de sorte que datatables du FPGA ne seront pas lues, et votre tampon se remplira, puis réveillerez votre application et continuerez la lecture.
    • Utilisez "crash" ou "kgdb" pour changer la valeur "read" en "noop" pendant quelques secondes, puis rétablissez la fonction par défaut.

Veuillez fournir toutes les informations que vous pourriez find utiles.

Pas sûr que cela aide. Mais si vous pouvez écrire un module du kernel qui appelle la fonction de suspend du module du kernel d'un autre périphérique, cela peut l'être.

Chaque périphérique PCI peut être suspendu conformément au file d'en-tête http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Par exemple, voici la fonction de suspension de la carte réseau Intel e1000 http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

De ce que je peux callbacker, cette fonction a été principalement utilisée lorsque le système passe en hibernation, le pilote de périphérique doit save le statut courant et se désactiver.

Je pense que vous pensez dans la mauvaise direction. Votre objective est clair.

Le moyen n'est pas d'arrêter le rest des process, mais de donner la priorité à vos process principaux en time réel. Utilisez bien pour vos process user-espace importants pour cela.

Le problème le plus difficile est la gestion des interruptions PCIe, qui réside dans l'espace kernel.

Étant donné que le matériel est impliqué, vous devriez commencer à regarder de plus près la voie PCIe impliquée sur votre carte mère et comment cela est peut-être connecté à un socket CPU spécifique.

irqbalance fait normalement un bon travail ici, mais vous pouvez configurer son comportement selon vos besoins.