Sistemas Operativos 3º Ano MIEEC
Folha nº 5: Mutexes POSIX

Questões

  1. Considere o seguinte segmento de código C:
    1: tmp = n;
    2: tmp++;
    3: n = tmp;
    

    onde tmp e n são variáveis inteiras.

    Ilustre através duma sequência das instruções acima (interleaving) como a a sua execução concorrente por 2 threads pode dar origem a uma race condition. Assuma que cada uma das instruções em linguagem C é atómica.

  2. Considere a substituição da sequência acima por uma única instrução:
    1: n++;
    
    1. Há possibilidade de race conditions quando é executada por mais do que um thread e a variável n é implementada em memória? Justifique.
    2. E se a variável n for implementada num registo do processador? Há possibilidade de race conditions? Justifique.

Problemas

Nota

Os seus programas deverão usar a biblioteca libpthread. Não se esqueça de indicá-lo ao compilador, i.e. especificar -lpthread na linha de comandos.

Deverá ainda definir a variável _REENTRANT na linha de comandos do gcc, usando o argumento -D_REENTRANT, para garantir que o compilador usa as funções apropriadas da biblioteca C.

    1. Escreva um programa cujo thread principal cria 3 novos threads.

      Cada thread (diferente do principal) deve executar a função tfun(), a qual incrementa uma variável definida em main() 10 M vezes. A função tfun() deve ainda imprimir indicando o início e o termo da sua actividade.

      O thread principal deve esperar que os outros 3 threads terminem, e depois deverá imprimir o valor da variável de contagem.

      Leia a função tfun() com cuidado para especificar correctamente o último argumento de pthread_create().

      IMP. Os threads deverão incrementar a mesma variável.

      Compile o seu programa e execute-o várias vezes. Explique os resultados observados.

    2. Escreva uma nova versão deste programa usando mutexes para sincronização. Procure maximizar a concorrência entre os diferentes threads.

      Dica Escreva uma nova versão da função tfun() que deverá designar por sfun() (s de sincronizada).

      Compile e teste a nova versão do seu programa.

  1. O ficheiro prob2.c contém parte da solução do problema do bounded buffer implementado com um vector circular e usando locks(pthread mutexes).

    O thread principal deve criar 3 threads produtores e 3 threads consumidores. Além destes, deve criar ainda um thread adicional que executa a função check() para verificar se o bounded buffer não é corrompido pelos restantes threads devido a race conditions.

    1. Estude o código fornecido e implemente as funções prod() e cons(), cujo esqueleto pode encontrar naquele ficheiro, executados por threads produtores e threads consumidores, respectivamente.

      Cada thread produtor deve produzir 10 M items: inteiros com o seu identificador (entre 0 e 2). Além disso, deve imprimir uma mensagem no início e outra no fim da sua execução.

      De modo análogo, cada thread consumidor deve consumir 10 M items. Além disso deve imprimir uma mensagem no início e outra no fim da sua execução. Nesta última deverá imprimir o total, discriminado por thread produtor, de items que consumiu.

      Use a função yield(), também incluída em prob2.c, para evitar busy waiting excessivo. Sempre que um thread invocar yield() deverá imprimir uma mensagem indicando-o.

      Teste o seu programa executando-o várias vezes. Anote os seus tempos de execução.

    2. Escreva uma nova versão do programa anterior. Nesta versão, o thread principal deverá calcular e imprimir o total, discriminado por thread produtor, dos items consumidos por todos os threads consumidores.
    3. Escreva uma nova versão do programa anterior. Nesta versão deverá remover as invocações da função yield().

      Compile e execute a nova versão do seu programa. Nota alguma alteração nos tempos de execução? Justifique os valores medidos.


This document was translated from LATEX by HEVEA.