Você está na página 1de 41

Introdução

Implementação

Sincronização no Kernel
Sistemas Operacionais

Andre Nathan
andrenth@cos.ufrj.br

Programa de Engenharia de Sistemas e Computação


COPPE/UFRJ

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Acesso concorrente

Condições em que ocorre:


Interrupções
Escalonamento
Sistemas com múltiplos processadores
Kernel preemptivo

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Acesso concorrente

Condições em que ocorre:


Interrupções
Escalonamento
Sistemas com múltiplos processadores
Kernel preemptivo

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Acesso concorrente

Condições em que ocorre:


Interrupções
Escalonamento
Sistemas com múltiplos processadores
Kernel preemptivo

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Acesso concorrente

Condições em que ocorre:


Interrupções
Escalonamento
Sistemas com múltiplos processadores
Kernel preemptivo

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Modelos de Sincronização

Baixa granularidade (Biglock )


Locks protegem todo o kernel (ou subsistemas inteiros)
NetBSD, OpenBSD
Alta granularidade
Locks protegem estruturas de dados específicas
Linux, FreeBSD

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Modelos de Sincronização

Baixa granularidade (Biglock )


Locks protegem todo o kernel (ou subsistemas inteiros)
NetBSD, OpenBSD
Alta granularidade
Locks protegem estruturas de dados específicas
Linux, FreeBSD

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Instruções Atômicas

Exemplo: condição de corrida: i++;


Thread 1 Thread 2
Lê i (7) Lê i (7)
Incrementa i (7 -> 8) -
- Incrementa i (7 -> 8)
Escreve i (8) -
- Escreve i (8)
O kernel fornece interfaces para instruções atômicas.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Locks

Exemplo: Acesso à lista encadeada


Thread 1 Thread 2
Tenta adquirir o lock Tenta adquirir o lock
Lock adquirido Falha: esperando
Acessa a lista Esperando
Libera o lock Esperando
... Lock adquirido
Acessa a lista
Libera o lock

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Locks – cont.

Mecanismo de proteção voluntário.


Podem ser implementados com espera ocupada ou
bloqueando o processo até que o lock esteja liberado.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Deadlocks

Um grupo de threads esperando por recursos que só podem


ser liberados por outros membros do grupo.
Auto-deadlock: um thread tenta adquirir um lock que ele já
possui.
Locks recursivos.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Deadlocks

Exemplo: Deadlock “AB-BA”


Thread 1 Thread 2
Adquire lock A Adquire lock B
Tenta adquirir lock B Tenta adquirir lock A
Espera por lock B Espera por lock A
Locks aninhados devem sempre ser adquiridos na mesma
ordem.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Contenção

Locks freqüentemente obtidos podem resultar em perda de


desempenho.
Serialização do acesso aos recursos.
Maior granularidade de locks implica em melhor
escalabilidade e menor contenção...
... mas também em maior overhead para sistemas com
apenas 1 processador.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Contenção

Locks freqüentemente obtidos podem resultar em perda de


desempenho.
Serialização do acesso aos recursos.
Maior granularidade de locks implica em melhor
escalabilidade e menor contenção...
... mas também em maior overhead para sistemas com
apenas 1 processador.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Acesso Concorrente
Introdução
Instruções Atômicas
Implementação
Locks

Contenção

Locks freqüentemente obtidos podem resultar em perda de


desempenho.
Serialização do acesso aos recursos.
Maior granularidade de locks implica em melhor
escalabilidade e menor contenção...
... mas também em maior overhead para sistemas com
apenas 1 processador.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Operações Atômicas

Exemplo: Condição de corrida: i++;


Thread 1 Thread 2
Incrementa i -
atomicamente (7 -> 8)
- Incrementa i
atomicamente (8 -> 9)

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Operações Atômicas – cont.

API:
atomic_t v;
atomic_set(&v, 7); /* v = 7 (atomicamente) */
atomic_add(2, &v); /* v = v + 2 (atomicamente) */
atomic_inc(&v); /* v = v + 1 (atomicamente) */
printk("%d\n", atomic_read(&v)); /* imprime 10 */

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

Proteção de operações mais complexas.


Podem ser adquiridos por apenas um thread de cada vez.
Demais threads tentando obter o spin lock ficam em espera
ocupada.
Devem ser adquiridos por pequenos intervalos de tempo.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

Proteção de operações mais complexas.


Podem ser adquiridos por apenas um thread de cada vez.
Demais threads tentando obter o spin lock ficam em espera
ocupada.
Devem ser adquiridos por pequenos intervalos de tempo.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

Proteção de operações mais complexas.


Podem ser adquiridos por apenas um thread de cada vez.
Demais threads tentando obter o spin lock ficam em espera
ocupada.
Devem ser adquiridos por pequenos intervalos de tempo.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

API:
spin_lock_t lock = SPIN_LOCK_UNLOCKED;
spin_lock(&lock);
/* Região crítica */
spin_unlock(&lock);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

Spin locks no Linux não são recursivos.


Se existir a possibilidade de um manipulador de interrupções
tentar adquirir o mesmo spin lock, interrupções locais devem
ser desabilitadas:
spin_lock_t lock = SPIN_LOCK_UNLOCKED;
spin_lock_irqsave(&lock);
/* Região crítica */
spin_unlock_irqrestore(&lock);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks

Spin locks no Linux não são recursivos.


Se existir a possibilidade de um manipulador de interrupções
tentar adquirir o mesmo spin lock, interrupções locais devem
ser desabilitadas:
spin_lock_t lock = SPIN_LOCK_UNLOCKED;
spin_lock_irqsave(&lock);
/* Região crítica */
spin_unlock_irqrestore(&lock);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks Leitor-Escritor

Permitem que o acesso exclusivo seja realizado apenas na


escrita.
Múltiplos leitores podem compartilhar o lock, sendo apenas
as escritas bloqueadas.
Implementação no Linux favorece leitores.
Adquirir um lock de escrita quando já se tem adquirido um
lock de leitura causa deadlock.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks Leitor-Escritor

Permitem que o acesso exclusivo seja realizado apenas na


escrita.
Múltiplos leitores podem compartilhar o lock, sendo apenas
as escritas bloqueadas.
Implementação no Linux favorece leitores.
Adquirir um lock de escrita quando já se tem adquirido um
lock de leitura causa deadlock.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks Leitor-Escritor

Permitem que o acesso exclusivo seja realizado apenas na


escrita.
Múltiplos leitores podem compartilhar o lock, sendo apenas
as escritas bloqueadas.
Implementação no Linux favorece leitores.
Adquirir um lock de escrita quando já se tem adquirido um
lock de leitura causa deadlock.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks Leitor-Escritor

Permitem que o acesso exclusivo seja realizado apenas na


escrita.
Múltiplos leitores podem compartilhar o lock, sendo apenas
as escritas bloqueadas.
Implementação no Linux favorece leitores.
Adquirir um lock de escrita quando já se tem adquirido um
lock de leitura causa deadlock.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks Leitor-Escritor

API:
rwlock_t lock = RW_LOCK_UNLOCKED;

/* Leitor */
read_lock(&lock);
/* Região crítica */
read_unlock(&lock);

/* Escritor */
write_lock(&lock);
/* Região crítica */
write_unlock(&lock);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

Uma tentativa de adquir um semáforo que já tenha sido


adquirido faz com que a tarefa bloqueada.
Quando o semáforo é liberado, uma tarefa na fila de espera é
escolhida para adquirí-lo.
Adequados para locks que precisam ser mantidos por
períodos mais extensos.
Semáforos não podem ser adquiridos em manipuladores de
interrupção, ou quando se possui um spin lock.
Um semáforo binário é também chamado “mutex”.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

Uma tentativa de adquir um semáforo que já tenha sido


adquirido faz com que a tarefa bloqueada.
Quando o semáforo é liberado, uma tarefa na fila de espera é
escolhida para adquirí-lo.
Adequados para locks que precisam ser mantidos por
períodos mais extensos.
Semáforos não podem ser adquiridos em manipuladores de
interrupção, ou quando se possui um spin lock.
Um semáforo binário é também chamado “mutex”.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

Uma tentativa de adquir um semáforo que já tenha sido


adquirido faz com que a tarefa bloqueada.
Quando o semáforo é liberado, uma tarefa na fila de espera é
escolhida para adquirí-lo.
Adequados para locks que precisam ser mantidos por
períodos mais extensos.
Semáforos não podem ser adquiridos em manipuladores de
interrupção, ou quando se possui um spin lock.
Um semáforo binário é também chamado “mutex”.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

Uma tentativa de adquir um semáforo que já tenha sido


adquirido faz com que a tarefa bloqueada.
Quando o semáforo é liberado, uma tarefa na fila de espera é
escolhida para adquirí-lo.
Adequados para locks que precisam ser mantidos por
períodos mais extensos.
Semáforos não podem ser adquiridos em manipuladores de
interrupção, ou quando se possui um spin lock.
Um semáforo binário é também chamado “mutex”.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

Uma tentativa de adquir um semáforo que já tenha sido


adquirido faz com que a tarefa bloqueada.
Quando o semáforo é liberado, uma tarefa na fila de espera é
escolhida para adquirí-lo.
Adequados para locks que precisam ser mantidos por
períodos mais extensos.
Semáforos não podem ser adquiridos em manipuladores de
interrupção, ou quando se possui um spin lock.
Um semáforo binário é também chamado “mutex”.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos

API:
static DECLARE_MUTEX(sem);

/*
* Tenta adquirir o semáforo. Se falhar, a tarefa é posta no
* estado TASK_INTERRUPTIBLE.
*/
if (down_interruptible(&sem)) {
/* Sinal recebido */
}

/* Região crítica */

/* Libera o semáforo */
up(&sem);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos Leitor-Escritor

Análogos aos spin locks leitor-escritor.


API:
static DECLARE_RWSEM(sem);

down_read(&sem); /* Se falhar, dorme em TASK_UNINTERRUPTIBLE */


/* Região crítica (apenas leitura) */
up_read(&sem);

/* ... */

down_write(&sem);
/* Região crítica (leitura/escrita) */
up_write(&sem);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Semáforos Leitor-Escritor

Análogos aos spin locks leitor-escritor.


API:
static DECLARE_RWSEM(sem);

down_read(&sem); /* Se falhar, dorme em TASK_UNINTERRUPTIBLE */


/* Região crítica (apenas leitura) */
up_read(&sem);

/* ... */

down_write(&sem);
/* Região crítica (leitura/escrita) */
up_write(&sem);

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Spin Locks vs. Semáforos

Requerimento Lock recomendado


Pequeno overhead Spin lock
Mantido por pouco tempo Spin lock
Mantido por muito tempo Semáforo
Necessário em contexto de interrupção Spin lock
Precisa bloquear enquanto em poder do lock Semáforo

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Desabilitando a Preempção

O kernel preemptivo permite que uma tarefa passe a rodar na


mesma região crítica em que a tarefa que sofreu preempção
estava.
Spin locks marcam regiões onde a preempção é desabilitada.
Algumas situações não requerem spin locks mas precisam
que a preempção seja desabilitada,
Dados exclusivos a um processador não precisam de spin
locks mas a preempção pode fazer com que outra tarefa
acesse variáveis compartilhadas.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Desabilitando a Preempção

O kernel preemptivo permite que uma tarefa passe a rodar na


mesma região crítica em que a tarefa que sofreu preempção
estava.
Spin locks marcam regiões onde a preempção é desabilitada.
Algumas situações não requerem spin locks mas precisam
que a preempção seja desabilitada,
Dados exclusivos a um processador não precisam de spin
locks mas a preempção pode fazer com que outra tarefa
acesse variáveis compartilhadas.

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Desabilitando a Preempção

API:
preempt_disable();
/* Manipulação de variável compartilhada */
preempt_enable();

Alternativa: get_cpu():
int cpu;

cpu = get_cpu(); /* Desabilita preempção e retorna a CPU atual */

/* Manipulação dos dados do processador */

/* Reabilita preempção -- ‘‘cpu’’ passa a ser inválido */


put_cpu();

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel


Operações Atômicas
Introdução Spin Locks
Implementação Semáforos
Desabilitando a Preempção

Desabilitando a Preempção

API:
preempt_disable();
/* Manipulação de variável compartilhada */
preempt_enable();

Alternativa: get_cpu():
int cpu;

cpu = get_cpu(); /* Desabilita preempção e retorna a CPU atual */

/* Manipulação dos dados do processador */

/* Reabilita preempção -- ‘‘cpu’’ passa a ser inválido */


put_cpu();

Andre Nathan andrenth@cos.ufrj.br Sincronização no Kernel

Você também pode gostar