Pergunta

Eu preciso para resolver um problema de bloqueio para este cenário:

  1. Um sistema multi CPU.
  2. Todos da CPU usar um recurso comum (software).
  3. Leia apenas o acesso ao recurso é muito comum. (O processamento de pacotes de rede de entrada)
  4. acesso de escrita é muito menos frequente. (Praticamente configuração altera apenas).

Atualmente eu uso o mecanismo (spinlocks) read_lock_bh write_lock_bh. O problema é que quanto mais da CPU, mais eu recebo travamentos macios em um contexto escritor.

Eu li o capítulo simultaneidade em este livro , Mas não conseguia entender se o leitor ou o escritor terá prioridade quando usando bloqueios de rotação.

Assim, as perguntas são:

  1. Será que o Linux spinlock prioridade mecanismo de dar ao leitor / escritor / nenhum deles?
  2. Existe um mecanismo melhor que eu posso usar, a fim de evitar os travamentos macios no meu cenário, ou talvez uma maneira para eu dar prioridade ao escritor sempre que ele tenta obter o bloqueio, enquanto estiver usando minha solução atual?

Obrigado, Nir

Foi útil?

Solução

Aqui está uma citação direta de Drivers de dispositivos essenciais do Linux que pode ser o que você está procurando. Parece que a parte lidar com RCU no final pode ser o que você está em interessado.

Leitor-Writer Locks

Outro mecanismo de regulação de concorrência especializado é uma variante leitor-gravador de spinlocks. Se o uso de um seção crítica é tal que segmentos separados quer ler ou escrever para uma estrutura de dados compartilhada, mas não faça tanto, esses bloqueios são uma escolha natural. Vários segmentos de leitor são permitidos dentro de uma região crítica simultaneamente. spinlocks Reader são definidos da seguinte forma:

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

read_lock(&myrwlock);             /* Acquire reader lock */
/* ... Critical Region ... */
read_unlock(&myrwlock);           /* Release lock */

No entanto, se um fio escritor entra em uma seção crítica, outros segmentos leitor ou gravador não são permitidos dentro. Usar spinlocks escritor, você escreveria o seguinte:

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

write_lock(&myrwlock);            /* Acquire writer lock */
/* ... Critical Region ... */
write_unlock(&myrwlock); /* Release lock */

Olhe para o IPX roteamento código presente em net/ipx/ipx_route.c para um exemplo da vida real de um spinlock leitor-gravador. UMA bloqueio de leitor-escritor chamado ipx_routes_lock protege IPX roteamento tabela do acesso simultâneo a. Tópicos essa necessidade de olhar para cima da tabela de roteamento para encaminhar pacotes solicitar bloqueios de leitor. Tópicos que precisam adicionar ou entradas Excluir no roteamento fechaduras escritor mesa adquirir. Isso melhora o desempenho porque há normalmente muito mais instâncias de roteamento pesquisas de tabela de roteamento atualizações da tabela.

Como spinlocks regulares, bloqueios de leitor-escritor também correspondente IRQ variantes, ou seja, read_lock_irqsave(), read_lock_irqrestore(), write_lock_irqsave() e write_lock_irqrestore(). A semântica destes funções são semelhantes aos de spinlocks regulares.

fechaduras seqüência ou seqlocks, introduzido no kernel 2.6, são bloqueios de leitor-escritor onde os escritores são favorecidos sobre leitores. Isto é útil se as operações de escrita em uma variável superam em muito ler acessos. Um exemplo é a variável jiffies_64 discutido anteriormente neste capítulo. tópicos escritor não espere para os leitores que possam estar dentro uma secção crítica. Devido a isso, tópicos leitor pode descobrir que a sua entrada dentro de uma seção crítica falhou e pode precisar de repetir:

u64 get_jiffies_64(void) /* Defined in kernel/time.c */
{
   unsigned long seq;
   u64 ret;
   do {
      seq = read_seqbegin(&xtime_lock);
      ret = jiffies_64;
   } while (read_seqretry(&xtime_lock, seq));
   return ret;
}

Writers proteger regiões críticas usando write_seqlock() e write_sequnlock().

O kernel 2.6 introduziu um outro mecanismo chamado Leia-Copy Update (RCU) , que o rendimento melhorou desempenho quando os leitores escritores superam em muito . A idéia básica é que tópicos leitor pode executar sem de bloqueio. tópicos escritor são mais complexas. Eles executam operações de atualização em uma cópia da estrutura de dados e substituir o ponteiro que os leitores vêem. A cópia original é mantida até que a mudança de contexto próxima em todas as CPUs para garantir a conclusão de todas as operações de leitura em curso. Esteja ciente de que o uso de RCU é mais envolvido do que usando o primitivas discutido até agora e deve ser usado somente se tiver certeza de que é a ferramenta certa para o trabalho. dados RCU estruturas e funções de interface são definidos em include/linux/rcupdate.h. Há ampla documentação em Documentation/RCU/*.

Para um exemplo de uso RCU , olhada fs/dcache.c. No Linux, cada arquivo está associada a entrada de diretório dados de informação (armazenado em uma estrutura chamada dentry), informações de metadados (armazenado em um inodo), e reais (Armazenados nos blocos de dados). Cada vez que você operar em um arquivo, os componentes no caminho do arquivo são analisados, eo dentries correspondentes são obtidos. Os dentries são mantidos em cache em uma estrutura de dados chamada dcache, a acelerar as operações futuras. A qualquer momento, o número de dcache pesquisas é muito mais do que dcache atualizações, então referências ao dcache são protegidos utilizando primitivas RCU.

Outras dicas

Não é este o tipo de caso de uso RCU é projetado para lidar? Consulte http://lwn.net/Articles/262464/ para uma boa escrever em cima dele de uso .

Se o trabalho que você faz, mantendo o bloqueio é pequeno você pode tentar um mutex normal, não leitor-gravador. É mais eficiente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top