📘 MAC0470/5856 - Desenvolvimento de Software Livre (2026)

Contribuindo para o Kernel Linux: A Saga do Patch com guard(mutex) e a Dor de Cabeça do IWYU

Capa do post

Introdução

Depois de configurar meu ambiente de desenvolvimento remoto na Keter e seguir os tutoriais, tivemos que contribuir de verdade para o kernel Linux. Não apenas seguir tutoriais, mas enviar um patch para a comunidade, passar pelo crivo dos mantenedores e, quem sabe, ver meu código aceito na mainline.

Junto com meu colega Rafael B Sales, escolhemos trabalhar no subsistema IIO (Industrial I/O), mais especificamente no driver ltr501.c, que controla um sensor de luz ambiente e proximidade. Nossa missão parecia simples: modernizar o código substituindo os pares mutex_lock()/mutex_unlock() pelas novas macros guard(mutex) e scoped_guard(mutex), introduzidas no kernel para reduzir código repetitivo e evitar erros de unlock esquecido.

O que parecia uma alteração trivial se transformou em uma aula sobre processos de revisão do kernel, boas práticas de código e a minha dor de cabeça com IWYU (Include What You Use).

O Patch V1

A macro guard(mutex) automaticamente libera o mutex quando a variável sai de escopo. Para casos onde o escopo precisa ser explicitamente delimitado, usaríamos scoped_guard(mutex, &lock) { ... }. O código fica mais limpo e menos propenso a erros. Enviamos o patch V1 para a lista de discussão linux-iio, com os devidos Signed-off-by meus e do Rafa. Em poucos dias, recebemos a primeira resposta — e ela veio carregada de instruções do que fazer.

Feedback

O mantenedor respondeu apontando alguns problemas:

  1. Estilo de referência a funções: devemos escrever mutex_lock(), não `mutex_lock`.
  2. IWYU nos headers: O driver não seguia o princípio Include What You Use. Ele pediu um patch separado para ordenar e limpar os includes.
  3. Simplificaçõess: Em funções como ltr501_als_write_samp_freq(), poderíamos retornar diretamente o resultado de regmap_field_write(), sem variável intermediária.
  4. Alteração indevida de escopo crítico: Em ltr501_write_intr_prst(), havíamos colocado a atualização de data->als_period dentro da seção protegida pelo mutex, o que não era necessário e poderia introduzir contenção desnecessária.
  5. Uso de guard() em switch case: Em funções como ltr501_read_info_raw(), usamos guard() dentro de um case. O mantenedor alertou que isso pode não ser seguro, pois a expansão da macro cria um bloco que pode atrapalhar o fluxo do switch. Recomendou verificar se compilava e funcionava corretamente (spoiler: não funcionava bem)

A minha dor de cabeça com o IWYU

O mantenedor pediu um patch adicional para adequar o ltr501.c ao IWYU. O princípio é simples: cada arquivo .c deve incluir exatamente os headers que usa. Isso reduz dependências ocultas, acelera compilações e evita que alterações em headers quebrem drivers indiretamente.

Parece fácil? Não é. O kernel tem uma teia de dependências implícitas. Por exemplo, incluir linux/bitops.h já garante linux/bits.h. Incluir linux/interrupt.h já provê linux/irqreturn.h. Decidir o que é realmente necessário exige conhecimento profundo do código (o que eu ainda não tenho).

O Patch V2

Criamos um patch V2 do IWYU adicionando 27 headers e removendo 9. Usamos ferramentas como iwyu (a ferramenta original) e verificamos manualmente cada símbolo.

Nossos guard(mutex) foram ajustados conforme o pedido:

  • Funções como ltr501_als_write_samp_freq() agora têm um guard(mutex) seguido de return regmap_field_write(...) direto, sem variável ret intermediária.
  • Em ltr501_write_intr_prst(), voltamos a usar scoped_guard() apenas em torno da escrita no registrador, deixando a atualização de data->als_period fora da seção crítica.
  • Dentro dos case, usamos scoped_guard(mutex, &lock) { ... } para delimitar explicitamente a seção crítica, evitando problemas de fluxo.

O Estado Atual e Próximos Passos

Atualmente, estamos digerindo o feedback da V2 e preparando uma V3 que incorpore as sugestões dos mantenedores.