Sincronização com Posix Threads Sistemas Embutidos 2004.

24
Sincronização com Posix Threads Sistemas Embutidos 2004

Transcript of Sincronização com Posix Threads Sistemas Embutidos 2004.

Page 1: Sincronização com Posix Threads Sistemas Embutidos 2004.

Sincronização com Posix Threads

Sistemas Embutidos

2004

Page 2: Sincronização com Posix Threads Sistemas Embutidos 2004.

Motivação

Como compartilhar recursos?

Processo 0 Processo 1

Inicio

lê (in)

out = in

imprime (out)

Fim

Inicio

lê (in)

out = in

imprime (out)

Fim

Page 3: Sincronização com Posix Threads Sistemas Embutidos 2004.

Revisão de Conceitos

Condição de corridaConjunto de eventos que levam a resultados não determinísticos

Região CríticaParte do código que implementa o acesso a um recurso compartilhado

Exclusão mútuaMecanismo que impede o uso simultâneo de um recurso compartilhado

Page 4: Sincronização com Posix Threads Sistemas Embutidos 2004.

Um problemaconst n=50;var t: integer; procedure total;

var count:integer;begin

for count = 1 to n do t= t + 1

end; 

begint=0;parbegin

total;total;

parend;write ( t );

end.

A: Ra t RaRa+1 t=0 Ra=1B: t 49 Rb49 t=49 Rb=49A: tRa t=1B: Rbt Rb=1A: t50 t=50B: RbRb+1 t2 t=2

 

Page 5: Sincronização com Posix Threads Sistemas Embutidos 2004.

Semáforos

Solução proposta por Dijkstra em 1965

Principio básico: um processo é suspenso enquanto não obtém permissão para executar uma RC e é “ acordado” através de um sinal

Para enviar um sinal via semáforo s o processo executa uma primitiva signal(s) e para receber um sinal via semáforo s o processo executa um primitiva wait(s)

Page 6: Sincronização com Posix Threads Sistemas Embutidos 2004.

Threads

Modelo de Processo (únicoThread)

Bloco de

controle de

processo

Espaço de

endereçamento

do usuário

Pilha

Usuário

Pilha

Kernel

Modelo MultiThread

Bloco de

controle de

processo

Espaço de

endereçamento

do usuário

Pilha

Usuário

Pilha

Kernel

Bloco do

controle

Thread

Pilha

Usuário

Pilha

Kernel

Bloco do

controle

Thread

Pilha

Usuário

Pilha

Kernel

Bloco do

controle

Thread

Thread Thread Thread

Page 7: Sincronização com Posix Threads Sistemas Embutidos 2004.

Threads de Usuário

Escalonamento e sincronização não passam pelo kernelEscalonamento é determinado pelo aplicativoPodem ser usadas em qualquer S.O.

Chamadas ao sistema bloqueiam o processoNão pode fazer uso de mais de um processador

Page 8: Sincronização com Posix Threads Sistemas Embutidos 2004.

Threads de Kernel

Threads do mesmo processo podem ser executados simultaneamente em processadores diferentes

O bloqueio de um thread não bloqueia as demais threads de um processo

Escalonamento e sincronização são muito custosos

Page 9: Sincronização com Posix Threads Sistemas Embutidos 2004.

LightWeightProcess

Criação de threads é feita em modo usuário

A maior parte do escalonamento e sincronização acontece em modo usuário

Os threads em modo usuário são mapeadas num número possivelmente menor de threads do kernel

Page 10: Sincronização com Posix Threads Sistemas Embutidos 2004.

Comunicação entre Threads

• compartilhamento de recursos

• espaço de endereçamento de memória compartilhado

• técnicas de sincronização semelhante as utilizadas em processos

Page 11: Sincronização com Posix Threads Sistemas Embutidos 2004.

Threads no Linux

• Implementação no kernel através da função clone()

• Utilização da biblioteca Pthreads para garantir a portabilidade

• Em um programa em C, incluir o cabeçalho pthread.h e acrescentar –lpthread na linkedição.

Page 12: Sincronização com Posix Threads Sistemas Embutidos 2004.

Pthreads

pthread_create(*t, *a, rotina, arg);

t é um ponteiro para uma variável do tipo pthread_t que a é um ponteiro para os atributos. Os atributos são

armazenados em uma variável do tipo pthread_attr_t. Um valor NULL indica o uso de valores default. Para detalhes veja pthread_attr_init(3)

rotina é o nome (ponteiro) para a função que será executada.

arg é um void * que é passado como argumento para rotina.

Page 13: Sincronização com Posix Threads Sistemas Embutidos 2004.

Pthreads

• A nova thread é disparada imediatamente e termina no retorno da função ou pela chamada da função pthread_exit(*ret)

• O argumento ret aponta uma variável que armazenará o valor de retorno.

• Já que pthread_exit nunca retorna, é de certa forma o equivalente à função exit.

Page 14: Sincronização com Posix Threads Sistemas Embutidos 2004.

Pthreads

pthread_join(pthread_t id, void **return);pthread_detach(id );

id é identificação da threadreturn é o valor de retorno (pode ser NULL)

Page 15: Sincronização com Posix Threads Sistemas Embutidos 2004.

Pthreads - Sincronização

Mutex

int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex

Variáveis de condição

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond);

Page 16: Sincronização com Posix Threads Sistemas Embutidos 2004.

Ex. Calculo de Pi

#include <stdio.h>#include <stdlib.h>#include <pthread.h>volatile double pi = 0.0; pthread_mutex_t pi_lock; volatile double intervals;

void *process(void *arg){ double width, localsum; int i; int iproc = (*((char *) arg) - ’0’); width = 1.0 / intervals; localsum = 0; for(i = iproc; i < intervals; i += 2) { register double x = (i + 0.5) * width; localsum += 4.0 / (1.0 + x * x); } localsum *= width;// Lock & Unlock before accessing PIpthread_mutex_lock(&pi_lock); pi += localsum;pthread_mutex_unlock(&pi_lock);return(NULL);}

int main(int argc, char **argv){pthread_t thread0, thread1;void * retval;intervals = atoi(argv[1]); //intervalospthread_mutex_init(&pi_lock, NULL);if (pthread_create(&thread0, NULL, process, "0") ||pthread_create(&thread1, NULL, process, "1")){fprintf(stderr, "%s: cannot make thread\n", argv[0]);exit(1);}if (pthread_join(thread0, &retval) ||pthread_join(thread1, &retval)){fprintf(stderr, "%s: thread join failed\n", argv[0]);exit(1);}printf("Estimation of pi is %f\n", pi);exit(0);}

Page 17: Sincronização com Posix Threads Sistemas Embutidos 2004.

Sincronização de Threads

Comunicação Serial

Page 18: Sincronização com Posix Threads Sistemas Embutidos 2004.

Características

• Um “servidor” pode receber/enviar mensagens através de uma porta serial RS485.

• A comunicação com um “cliente” só pode acontecer quando a linha estiver livre

• O acesso ao meio serial deve ser controlado por mutex

Page 19: Sincronização com Posix Threads Sistemas Embutidos 2004.

Problema

RespServ

GERENTEContagem

ConvL

armazenamento

Ocorrências de queda ou retorno de fase

Poll

Mensagens não transmitidas ao Servidor

Fast Select Caso servidor não esteja disponível

EnviaMsg

Servidor

Servidor

Page 20: Sincronização com Posix Threads Sistemas Embutidos 2004.

Programa principal

int main(int argc, char **argv){pthread_t tp;pthread_mutex_t lock;

config_serial();pthread_mutex_init(&lock,NULL); pthread_mutex_lock(&lock); //obtém lockpthread_mutex_init(&serial,NULL);

if (pthread_create(&tp, NULL,(void *)Poll, NULL) ) { perror("Criacao da thread Poll");

exit(1); }while(1);}

Page 21: Sincronização com Posix Threads Sistemas Embutidos 2004.

Tratamento de relógio

//Inicializa Timervoid init_timer(){ struct sigaction timer; timer.sa_handler = handler_timer; timer.sa_flags = SA_RESTART; sigemptyset(&timer.sa_mask); sigaction(SIGALRM,&timer,

NULL);}

void handler_timer (){int p;p =0;trata_relogio(p);

}

void trata_relogio(int p){struct itimerval valor,ovalor; if (p == 1){ // liga timer valor.it_interval.tv_sec = 30; pthread_mutex_lock(&lock);

}else{ // desliga timervalor.it_interval.tv_sec = 0;valor.it_value.tv_sec=0;pthread_mutex_unlock(&lock); } valor.it_interval.tv_usec = 0; valor.it_value = valor.it_interval; setitimer (ITIMER_REAL, &valor,0);}

Page 22: Sincronização com Posix Threads Sistemas Embutidos 2004.

Rotina Poll

void Poll() {estado = INICIO_POLL; while (1) {

switch (estado){ case INICIO_POLL:

pthread_mutex_lock(&lock); // fica preso pthread_mutex_lock(&serial); // obtém meio serial

• • •

case FIM_POLL:pthread_mutex_unlock(&serial); // libera meio serialtrata_relogio(1);

}

Page 23: Sincronização com Posix Threads Sistemas Embutidos 2004.

O que aconteceria ...

• se durante um ciclo, a thread poll atualizasse uma tabela compartilhada na memória?

• se após o ciclo, esta tabela fosse atualizada no disco?

• Se durante o ciclo, uma outra thread retirasse um elemento da tabela?

CUIDADO COM A ORDEM DOS SEMÀFOROS:SUJEITO A DEADLOCK

Page 24: Sincronização com Posix Threads Sistemas Embutidos 2004.

Exercício

Altere o programa anterior para que os dados obtidos no ciclo de Poll sejam armazenados em um arquivo. Periodicamente este arquivo é lido por um outro thread e enviado via internet para um servidor remoto (simplesmente utilize uma função Envia( ) admitindo que está funcionando corretamente)