Estamos executando um processo em tempo real em um kernel que não é em tempo real (CentOS 6) e isso provavelmente não vai mudar.
Temos um aplicativo de streaming de vídeo que requer cerca de 500 MB/s de tráfego PCIe de um FPGA personalizado continuamente por 1,5 horas por vez. O aplicativo funciona muito bem – na maioria das vezes. No entanto, tivemos situações em que parece que o kernel simplesmente para de responder ao serviço de PCIe ou solicitações de memória por até 500 milissegundos por vez. Isso parece acontecer durante a E/S de arquivo em rajadas de outro thread. Achei impossível tentar replicar esse problema apenas executando muitos arquivos IO fictícios do espaço do usuário enquanto o aplicativo principal está em execução.
Existe uma maneira de forçar (simular) um "congelamento" global do kernel Linux (em particular, interrompendo o PCIe ou todos os acessos à memória DDR3 ou algo parecido) para que possamos reproduzir este problema?
Temos buffer de até 10 milissegundos implementado agora na memória interna do FPGA, mas isso não é suficiente. Podemos armazenar em buffer no FPGA DDR3 e depois despejar no host, mas precisamos de um método para testar esse novo recurso sob pressão.
Não queremos que o kernel congele ou trave permanentemente. Gostaríamos de poder definir o intervalo de tempo.
Estou procurando algo como escrever valores mágicos /proc/sys/vm
temporariamente que faça o sistema praticamente rastejar e depois reverter depois de algumas centenas de milissegundos, mas olhar para o número de maneiras possíveis de quebrá-lo não é para um novato como eu (https://www.kernel.org/doc/Documentation/sysctl/vm.txt). Talvez um pouco de numactl
magia?
Responder1
Uma opção para fazer um teste rápido poderia ser usar um kernel habilitado para KGDB e parar o kernel manualmente e testar,veja este link.
Por outro lado, lembro-me de coisas que podem causar suas pausas:
- cpufreq,
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latency
, o valor está em ns (4000 no meu processador AMD FX(tm)-8120 Eight-Core) não deve ser um problema, mas verifique - Estrangulamento térmico da própria CPU ou do módulo regulador de tensão.
- NAPI e/ou tráfego de rede pesado
- ASPM PCIe (
cat /sys/module/pcie_aspm/parameters/policy
) - Contenção nos buffers do seu dispositivo de destino (disco rígido, nic...)
- Bug no firmware de algum dispositivo no barramento PCIe (mesmo que você não esteja usando), você pode tentar desligá-los com
/sys/bus/pci/devices/$DEVICE/power/control
Responder2
Podemos ter mais detalhes sobre como sua aplicação está se comunicando com o FPGA? É o aplicativo que lê o buffer do FPGA ou o FPGA que envia interrupção ao kernel (como placas de rede)?
Espero que ele abra um bloco/char em/dev e depois se comunique com ele. Isso significa que ele usa um driver para fazer a comunicação entre a aplicação e o arquivo /dev/XXX.
Eu gostaria de ter a saída de :
cat /proc/interrupts
; lsmod
;ls -al /dev/yourmod
Aqui estão as ideias:
- Se for acionado por interrupção, você pode configurar o PIC da CPU para desabilitar o IRQ correspondente e reativá-lo. Isso fará com que todas as solicitações do cartão sejam ignoradas (sem que o cartão perceba).
- se for como uma leitura de buffer, você pode:
- Coloque seu aplicativo em estado de suspensão, para que os dados do FPGA não sejam lidos e seu buffer seja preenchido, então ative seu aplicativo e continue a leitura.
- Use "crash" ou "kgdb" para alterar o valor "read" para "noop" por alguns segundos e, em seguida, defina-o novamente para a função padrão.
Forneça todas as informações que você possa achar úteis.
Responder3
Não tenho certeza se isso ajuda. Mas se você puder escrever um módulo do kernel que chame a suspend
função do módulo do kernel de outro dispositivo, isso poderá servir.
Cada dispositivo PCI pode ser suspenso de acordo com o arquivo de cabeçalhohttp://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479
Por exemplo, aqui está a função de suspensão da NIC Intel e1000http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643
Pelo que me lembro, esta função era usada principalmente quando o sistema entrava em hibernação, o driver do dispositivo precisava salvar o status de execução atual e desligar-se.
Responder4
Acho que você está pensando da maneira errada. Seu objetivo é claro.
O caminho não é parar o resto dos processos, mas dar aos seus processos principais prioridade de agendamento quase em tempo real. Usarlegalpara seus processos importantes do espaço do usuário para isso.
O problema mais difícil é o tratamento de interrupções PCIe, que reside no espaço do kernel.
Como o hardware está envolvido, você deve começar a examinar mais de perto a pista PCIe envolvida em sua placa-mãe e como ela está possivelmente conectada a um soquete de CPU específico.
equilíbrio irqnormalmente faz um bom trabalho aqui, mas você pode configurar seu comportamento para atender às suas necessidades.