\begin{myslide}

\begin{center}

{\large \sf \textbf{MO806/MC914\\
Tópicos em Sistemas Operacionais}\\
2s2006}

\bigskip

\subheading{Leitores e escritores}

\end{center}

\end{myslide}

\begin{myslide}
  \heading{Leitores e escritores}
\alltt{semaforo sem_dados = 1;
{\Large\textbf{\textsf{Leitor:}}}
   while(true)
      wait(sem_dados);
      le_dados();
      signal(sem_dados);
{\Large\textbf{\textsf{Escritor:}}}
   while(true)
      wait(sem_dados);
      escreve_dados();
      signal(sem_dados);}
\end{myslide}

\begin{myslide}
   \heading{Leitores e escritores}

   \begin{itemize}
   \item Problema: apenas um leitor pode fazer acesso ao banco de
     dados por vez
   \item Veja o código: l-e-sem-concorrencia.c
   \item Possível solução: permitir o acesso simultâneo a vários
     leitores
   \end{itemize}
\end{myslide}

\begin{myslide}
  \heading{Vários leitores simultâneos}
\alltt{semaforo sem_dados = 1, sem_nl = 1;
int nl; /* Leitores ativos num dado instante */
{\Large\textbf{\textsf{Leitor:}}}
   while(true)
      wait(sem_nl); 
      nl++; if (nl == 1) wait(sem_dados);      
      signal(sem_nl);
      le_dados();
      wait(sem_nl); 
      nl--; if (nl == 0) signal(sem_dados);
      signal(sem_nl);}
\end{myslide}


\begin{myslide}
  \heading{Vários leitores simultâneos}

  \begin{itemize}
  \item Problema: os escritores podem morrer de fome
  \item Veja o código: l-e-starvation.c
  \item Como escrever este código usando locks e
      variáveis de condição?
  \end{itemize}

\end{myslide}

\begin{myslide}
  \heading{Leitores simultâneos}
  \subheading{Locks e variáveis de condição}
  \subheading{Primeira tentativa}
\bigskip

\alltt{ 
int nl = 0;      /* Número de leitores ativos */
mutex_t lock_nl; /* Lock para o contador nl   */

mutex_t lock_dados; /* Lock para os dados     */


}
\end{myslide}

\begin{myslide}
  \heading{Leitor}
\alltt{
  mutex_lock(&lock_nl);
  nl++;
  if (nl == 1) mutex_lock(&lock_dados);
  mutex_unlock(&lock_nl);
  le_dados();
  mutex_lock(&lock_nl);
  nl--;
  if (nl == 0)
    mutex_unlock(&lock_dados);
  mutex_unlock(&lock_nl);
}
\end{myslide}

\begin{myslide}
  \heading{Leitores simultâneos}

  \begin{itemize}
  \item Problema: Uma thread leitora faz o lock e outra
  faz o unlock
  
  \item Veja o código: l-e-lock.c

  \item Tipos de lock:
    \begin{itemize}
    \item FAST
    \item RECURSIVE
    \item ERROR CHECKING
    \end{itemize}
  \end{itemize}
\end{myslide}

\begin{myslide}
  \heading{Leitores simultâneos}
  \subheading{Locks e variáveis de condição}
  \subheading{Segunda tentativa}
\alltt{
mutex_t lock_dados; /* Controle dos dados */  
boolean bloq_leitura = false; 

mutex_t lock_nl; /* Lock para o contador  */
int nl = 0;      /* Número de leitores ativos */
}
\end{myslide}

\begin{myslide}
  \heading{Leitor}
\alltt{
  mutex_lock(&lock_nl);
  nl++;
  if (nl == 1) 
     mutex_lock(&lock_dados);
     bloq_leitura = true;
     mutex_unlock(&lock_dados);
  mutex_unlock(&lock_nl);
  le_dados();
  /* ... */
}
\end{myslide}

\begin{myslide}
  \heading{Leitor}
\alltt{
  /* ...*/
  le_dados();
  mutex_lock(&lock_nl);
  nl--;
  if (nl == 0) 
     mutex_lock(&lock_dados);
     bloq_leitura = false;
     cond_signal(&cond_dados);
     mutex_unlock(&lock_dados);
  mutex_unlock(&lock_nl);
}
\end{myslide}

\begin{myslide}
  \heading{Escritor}
\alltt{
  mutex_lock(&lock_dados);  
  while (bloq_leitura) 
    cond_wait(&cond_dados, &lock_dados);
  escreve_dados();
  cond_signal(&cond_dados);
  mutex_unlock(&lock_dados);

}
\end{myslide}

\begin{myslide}
  \heading{Leitores simultâneos}
  \subheading{Locks e variáveis de condição}
  \subheading{Terceira abordagem}
\alltt{ 
cond_t  cond_dados; /* Espera pelos dados */

mutex_t lock_cont; /* Lock para os contadores  */
int nl = 0;  /* Número de leitores ativos */
int ne = 0;  /* Número de escritores ativos */

Veja o código: l-e-broadcast.c
}
\end{myslide}


\begin{myslide}
  \heading{Leitor}
\alltt{
  mutex_lock(&lock_cont);
  while (ne > 0) 
    cond_wait(&cond_dados, &lock_cont);
  nl++;
  mutex_unlock(&lock_cont);
  le_dados();
  mutex_lock(&lock_cont);
  nl--;
  if (nl == 0)
    cond_signal(&cond_dados);
  mutex_unlock(&lock_cont);
}
\end{myslide}

\begin{myslide}
  \heading{Escritor}
\alltt{
  mutex_lock(&lock_cont);
  while (nl > 0 || ne > 0) 
    cond_wait(&cond_dados, &lock_cont);
  ne++;
  mutex_unlock(&lock_cont);
  escreve_dados();
  mutex_lock(&lock_cont);
  ne--;
  cond_broadcast(&cond_dados);
  mutex_unlock(&lock_cont);
}
\end{myslide}

\begin{myslide}
  \heading{Leitores e escritores}
  \subheading{Prioridade para os escritores}

\alltt{
int nl = 0;  /* Número de leitores */
int ne = 0;  /* Número de escritores */
int nw = 0;  /* Número de escritores esperando */
mutex_t lock_cont;
cond_t cond_esc, cond_leit;

}
Veja o código: l-e-broadcast2.c
\end{myslide}

\begin{myslide}
  \heading{Leitor}
\alltt{
  mutex_lock(&lock_cont);
  while (ne > 0 || nw > 0) 
    cond_wait(&cond_leit, &lock_cont);
  nl++;
  mutex_unlock(&lock_cont);
  /* Leitura */  
  mutex_lock(&lock_cont);
  nl--;
  if (nl == 0 && nw > 0)
    cond_signal(&cond_esc);
  mutex_unlock(&lock_cont);
}
\end{myslide}

\begin{myslide}
  \heading{Escritor}
\alltt{\normalsize
  mutex_lock(&lock_cont);
  nw++;
  while (nl > 0 || ne > 0) 
    cond_wait(&cond_esc, &lock_cont);
  nw--; ne++;
  mutex_unlock(&lock_cont);
  /* Escrita */
  mutex_lock(&lock_cont);
  ne--;
  if (nw > 0)
    cond_signal(&cond_esc);
  else
    cond_broadcast(&cond_leit);
  mutex_unlock(&lock_cont);
}
\end{myslide}

\begin{myslide}
   \heading{Leitores e escritores}
\subheading{Como implementar um bom compromisso?}
   \begin{itemize}
   \item Ausência de starvation
   \item Leitores simultâneos
   \end{itemize}

\end{myslide}   
%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "../base"
%%% End: 
