A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

REENTRÂNCIA Funções reentrantes são aquelas que podem ser chamadas por mais de uma tarefa e ainda assim, sempre trabalham corretamente, mesmo que o SOTR.

Apresentações semelhantes


Apresentação em tema: "REENTRÂNCIA Funções reentrantes são aquelas que podem ser chamadas por mais de uma tarefa e ainda assim, sempre trabalham corretamente, mesmo que o SOTR."— Transcrição da apresentação:

1 REENTRÂNCIA Funções reentrantes são aquelas que podem ser chamadas por mais de uma tarefa e ainda assim, sempre trabalham corretamente, mesmo que o SOTR chaveie de uma tarefa para outra no meio da execução da função. As regras quem decidem se uma função é reentrante são: Uma função reentrante não pode usar variáveis de uma forma não atômica, a menos que elas estejam armazenadas na pilha da tarefa que chamou a função ou são de outra forma, variáveis privadas desta pilha. Uma função reentrante não pode chamar uma outra função que não seja ela própria uma função reentrante. Uma função reentrante não pode usar o hardware de uma forma não atômica.

2 Uma revisão de Armazenamento de Variáveis em Linguagem C
A melhor maneira de compreender a reentrância e em particular a regra 1 acima, é entender onde os compiladores C armazenam as variáveis. Veja o código abaixo e indique quais variáveis são armazenadas na pilha e quais são armazenadas em uma localização fixa da memória? static int static_int; int public_int; int inicializada=4; char *string=“Para onde esta string vai?”; void *vponteiro; void function (int parm, int *ptr_parm) { static int static_local; int local; : }

3 Resposta: Static_int - É armazenada em uma localização física da memória e portanto é compartilhada por qualquer tarefa que venha, porventura, a chamar a função. Public_int – A única diferença entre static int e public int, é que as funções de outros múdulos C, podem acessar public int. inicializada – O mesmo que para as outras variáveis, uma vez que a inicialização de uma variável não muda a forma de acesso da mesma. String – O mesmo. Vponteiro - O ponteiro em si, está em uma localização fixada na memória e portanto é uma variável compartilhada. Se function() usar ou alterar o valor do dado apontado por vponteiro, então estes valores também serão compartilhados entre as tarefas que venham a chamar function(). Parm – Está na pilha. Se mais que uma tarefa chamar function(), parm estará em uma localização diferente para cada uma, uma vez que cada tarefa tem sua própria pilha. Não importa quantas tarefas venha a chamar function(), parm não será um problema. ptr_parm – está na pilha, portanto function() pode fazer qualquer coisa com o valor de ptr_parm sem problemas. Contudo, se function() utilizar ou alterar o valor apontado por ptr_parm, então devemos nos preocupar com onde esse dado será armazenado antes de sabermos se termos ou não problemas. Se for garantido que cada tarefa que chamar function() passar um valor diferente para ptr_parm, tudo bem, caso contrário, teremos problemas.

4 APLICANDO AS REGRA DE REENTRÂNCIA
static local – Está em uma posição fixa na memória. A única diferença entre esta e static_int é que static_int pode ser utilizada por outra função do mesmo arquivo C, enquanto static_local somente poderá ser utilizada por function(). local – Está na pilha. APLICANDO AS REGRA DE REENTRÂNCIA Desafio: Examine o código da função display abaixo e determine se ela é ou não reentrante e porque sim ou não.

5 BOOL fError; Void diplay(int j) { if(!(fError)) printf(“Valor: %d”, j); j=0; fError=TRUE; } else printf(“\nNão pude exibir o valor”);

6 A função não é reentrante por duas razões
A função não é reentrante por duas razões. Primeira, a variável fError está em uma posição fixa da memória e, portanto, é compartilhada com todas as funções que chamarem display(). O uso de fError não é atômico, porque o SOTR pode chavear entre o tempo que ela é testada e o tempo em que ela é fixada. Portanto, esta função viola a regra 1. Note que a variável j não é problema, pois ela está na pilha. O segundo problema é que esta função pode, também violar a regra 2. Para esta função ser reentrante, printf() também deve ser reentrante. Pergunta, printf() é reentrante? Pode ser, mas não conte com isso antes de ler o manual que vem com o compilador que você está utilizando e encontrar uma declaração explícita disso.

7 As Áreas Cinzas da Reentrância
Existem algumas áreas cinzas entre funções reentrantes e não reentrantes. O código abaixo mostra uma função simples na área cinza. static int cErros; void vContaErros(void) { ++cErros; } Esta função obviamente modifica uma variável fora da pilha, mas a regra 1 diz que uma função reentrante pode não usar variáveis fora da pilha de uma forma não atômica. A questão aqui é: será o incremento de cErros atômico? Pode ser que sim ou não, a resposta depende do ,processador e do compilador que se está utilizando.

8 Se você estiver utilizando um microcontrolador de 8 bits do tipo 8051, então o compilador pode gerar algo do tipo para cErros(): MOV DPTR,#cErros+01H MOVX INC A MOV @DPTR,A JNZ semCarry MOV DPTR,#cErros MOVX INC a semCarry: RET

9 Mas se utilizarmos o 80x86 da Intel. Podemos obter:
Que não é atômico e realmente está longe disso, visto que utiliza 10 instruções para fazer o trabalho real e uma interrupção e conseqüentemente uma mudança de tarefa pode ocorrer em qualquer lugar entre essas 10 instruções. Mas se utilizarmos o 80x86 da Intel. Podemos obter: INC (cErros) RET Que é atômica.

10 SEMÁFOROS E DADOS COMPARTILHADOS
Já vimos que os SOTR podem causar uma nova classe de problemas, as variáveis compartilhadas, devido ao chaveamento do microprocessador entre as várias tarefas que concorrem pelo mesmo. Porém os SOTR também fornecem algumas novas ferramentas para lidar com este tipo de problema. O SEMÁFORO é uma dessas ferramentas. SEMÁFOROS PARA OS SOTR Trens e Linhas Férreas Os semáforos foram, originalmente, inseridos para controlar o fluxo de trens nas ferrovias e os trens fazem duas coisas com os semáforos: Primeiro, quando um trem sai de uma área protegida dos trilhos, ele levanta o semáforo. Segundo, quando um trem encontra um semáforo, ele espera o semáforo levantar, após o semáforo levantar ele pode passar, porém a sua segurança na área protegida dos trilhos exige que ele abaixe o semáforo ao passar pelo mesmo.

11 Embora cunhada para um uso específico, a palavra semáfora encontra, na área de computação, e principalmente nos SOTR, muitos significados diferentes. Nenhum SOTR utiliza os termos rise (levantar) ou lower (abaixar) para a sua terminologia agregada a semáforos, mas utilizam get e give, take e release, pend e post, p e v, wait e signal e inumeras outras combinações. Vamos convencionar o uso dos nomes take para abaixar e release para levantar.Vamso discutir o semáforo mais simples e mais comumente utilizado que é semáforo binário e que lembra muito a operação dos semáforos das linhas férreas. Esistem duas funções básicas do SOTR para operar com semáforos: TakeSemaforo() para abaixar o semáforo e ReleaseSemaforo() para levantar o semáforo. Se uma tarefa chamar TakeSemaforo() e não chamar ReleaseSemaforo() para libera-lo, todas as outras tarefas que chamarem TakeSemaforo() poderá obtê-lo ficando assim bloqueadas até que a primeira tafera chame ReleaseSemaforo(), liberando o semáforo para o sistema. Somente uma tarefa poderá utilizar o semáforo em um determinado tempo.

12 Vamos aplicar um semáforo binário ao problema dos tanques.
Struct { long lNivel_Tanque; long lTempo_Atualizacao; } Dados_Tanques[N_MAX_TANQUES]; /* Tarefa Botão */ void vRespostaAoBotao(void) /* Alta prioridade */ int i; while(TRUE) // bloqueie até o usuário apertar um botão. i = // obtenha o número do botão apertado => identificação do tanque TakeSemaforo(); printf(“\nTempo: %08ld NIVEL: %08ld”,Dados_Tanque[i].Tempo_Atualizacao, Dados_Tanque[i.lNivel_Tanque); ReleaseSemaforo(); }

13 /* Cont. do código */ /* Tarefa Niveis */ void vCacularNiveisTanques(void) /* prioridade menor */ { int i=0; while(TRUE) : TakeSemaforo(); // Estabeleça_Nível_do_Tanque[i].Atualização_Tempo // Estabeleça_Nível_do_Tanque[i].Nivel_Tanque ReleaseSemaforo(); }

14 Antes de “ Tarefa Níveis” (cCalularNiveisTaques) atualizar os dados da estrutura , ela chama TakeSemaforo() para obter (abaixar) o semáforo. Se o usuário pressionar um botão enquanto “Tarefa Níveis” está atualizando os dados e ainda tem o semáforo, então a seguinte seqüência de eventos ocorre: O SOTR chaveará para “Tarefa Botão” como antes, movendo a “Tarefa Níveis” para o estado pronto. Quando “Tarefa Botão” tentar obter o semáforo chamando TakeSemaforo(), ele bloqueará porque “Tarefa Níveis” já tem o semáforo. O SOTR buscará uma outra tarefa e perceberá que “Tarefa Níveis” está ainda no estado pronto, com “Tarefe Botão” bloqueada, “Tarefa Níveis” voltará a rodar até que ela libere o semáforo. Quando “Tarefa Níveis” liberar o semáforo chamando ReleaseSemaforo(), “Tarefa Botão” deixará de estar bloqueada, e o SOTR voltará a chavear para a mesma.

15 Seqüência das Instruções C

16 Vamos agora para uma situação de um sistema de controle de um reator nuclear, sendo que desta vez utilizaremos uma tarefa, ao invés de um interrupção para obter as temperaturas. As funções e estruturas de dados cujos nome iniciam com “OS” são aquelas utilizadas no uC/OS. As funções OSSemPost e OSSemPen levantam e abaixam o semáforo respectivamente. A função OSSemCreate inicializa o semáforo, e deve ser chamada antes das outras duas. A estrutura OS_EVENT armazena os dados que representam o semáforo e é inteiramente gerenciada pelo SOTR. O parâmetro WAIT_FOREVER da função OSSemPend indica que a tarefa que está fazendo a chamada, está preocupada com esperar para sempre o semáforo; isso será discutido posteriormente. A função OSTimeDly faz vTarefaLerTemperutura bloquear por aproximadamente um quarto de segundo, o evento que a desbloqueia é simplesmente a expiração desse período de tempo. Portanto, esta tarefa acorda lê as duas temperaturas e as coloca em um arranjo uma vez a cada quarto de segundo. Enquanto isso vTarefaDeControle verifica continuamente se as duas temperaturas são iguais.

17 #define TASK_PRIORITY_READ 11
#define TASK_PRIORITY_CONTROL 12 #define STK_SIZE static unsigned int LeiaPilha[STK_SIZE]; static unsigned int ControlePilha[STK_SIZE]; static int iTemperaturas[2]; OS_EVENT *p_semTemp; void main(void) { /* Inicialize ( mas não parta) o SOTR */ OS_INIT(); /* Explique ao SOTR as tarefas */ OSTaskKCreate(vTarefaLerTemperatura, NULLP, (void *)&LeiaPilha[STK_SIZE],TASK_PRIORITY_READ); OSTaskKCreate(vTarefaControle, NULLP, (void *)&ControlePilha[STK_SIZE],TASK_PRIORITY_CONTROL); /* Parta o SOTR – Esta função nuca retorna */ OSStart(); }

18 void vTarefaLerTemperatura(void)
{ while(TRUE) OSTimeDly(5); /* Deley de ¼ de segundo */ OSSemPend(p_semTemp, WAIT_FOREVER); // leia a entrada da iTemperatura[0]; // leia a entrada da iTemperatura[1]; OSSemPost (p_semTemp); } void vTarefaControle(void) p_semTemp = OSSemInit (1); OSSemPend(psemTemp, WAIT_FOREVER); if(iTemperatur´[0] != iTemperatura[1]) // Ative o alarme de temperatura do sistema OSSemPost(p_semTemp); // Faça algum outro trabalho útil

19 O código acima apresenta um bug – tente identifica-lo.
Discussão do problema: O bug se origina com a chamada de OSSemCreate, o qual deve acontecer antes de vTarefaLerTemperatura chamar OSSemPend para usar o semáforo. Como saber se isso realmente ocorre? Impossível. Pode-se imaginar que desde que vTarefaLerTemperatura chama OSTimeDly no início, antes de chamar OSSemPend, VTarefaControle terá tempo suficiente para chamar OSSemCreate. Sim, você pode fazer isso, mas se seu código para sistemas embutidos confia neste tipo de coisa, você pode colher bugs misteriosos pelo resto de sua carreira. Como saber se, algum dia, não aparecerá alguma tarefa de alta prioridade que consuma todo o tempo de retardo em vTarefaLerTemperatura?

20 Alternativamente, pode-se imaginar que colocando uma prioridade maior para vTarefaControle em relação a vTarefaLerTemperatura, o problema será resolvido. Sim, estará até que outra pessoa que não participou do desenvolvimento do sistema, mas seja do ramo, perceba que vTarefaLerTemperatura deve ter maior prioridade e altere as prioridades do sistema e efetue a mudança. Aí seu código transformou-se em uma bomba de tempo. Não se desespere. Ponha a chamada de inicialização do semáforo em algum ponto de partida do código que garanta que ela rode primeiro. Isso pode ser feito na função main, onde deve-se colocar OSSemInit em algum ponto antes da chamada de OSStart.

21 REENTRÂNCIA E SEMÁFOROS
Vamos retornar à função vContaErros() que não era reentrante por tinha problema de variável compartilhada. Porém nesta nova versão, a variável static cErros é envolvida por rotinas de chamada de semáforo, ou na liguagem dos dados compartilhados, cErros foi protegida por semáforos. Sempre que uma tarefa chamar vContaErrros(), a primeira será bloqueada ao tentar utilizar o semáforo. Na linguagem da reentrância, nós tornamos cErros atômica., não no sentido de que ela não possa ser interrompida por um evento qualquer, mas no sentido que ela não pode ser interrompida por alguma coisa semelhante a ela que procure utilizar a mesma variável compartilhada. Portant, tornamos assim a função vContaErrros() reentrante. As funções e estruturas de dados que comecem com “NU” são aquelas utilizadas em um SOTR denominado Nucleous (Accelerate Techology Incorporated)

22 void Tarefa1(void) { : vContaErros(9); } void Tarefa2 (void) vContaErros(11); static int cErros; Static NU_SEMAPHORE semErros; void vContaErros(int cNovosErros) NU_Obtain_Semaphore (SemErros, NU_SUSPENDED); cErros += cNovosErros; NU_Release_Semaphore(&SemErros);

23 O parâmetro NU_SUSPENDED da função Obtain_Semaphore() é semelhante ao WAIT_FOREVER utilizado em um outro exemplo. Pode-se imaginar se o código do exemplo funcionaria se as chamadas NU_Obtain_Semaphore() e NU_Release_Semaphore() estivessem envolvendo a chamada de vContaErros()? Sim, mas é preciso se lembrar que obter e liberar o semáforo em torno de cada chamada da função. Com a colocação da chamada dos semáforos dentro da função vContaErros() é impossível esquecer.

24 MÚLTIPLOS SEMÁFOROS Nos dois exemplos anteriores pudemos perceber que as todas as funções semáforo tem um parâmetro que identifica o semáforo que está sendo utilizado, abaixado ou levantado. Visto que a maioria dos SOTR têm quantos semáforos quanto se desejar, cada chamada do SOTR deve identificar sobre qual semáforo deve-se operar. Os semáforos são todos independentes um do outro: se uma tarefa toma o semáforo A e outra o semáforo B, não ocorre bloqueio. Da mesma forma, se uma tarefa está esperando pelo semáforo C, ela ainda permanecerá bloqueada se uma outra tarefa liberar o semáforo D. Qual é a vantagem de se ter múltiplos semáforos? Sempre que uma Tarefa toma um semáforo, ela está, potencialmente, diminuindo o tempo de resposta de qualquer outra tarefa que necessite do mesmo semáforo. Em um sistema com apenas um semáforo, se a tarefa de menor prioridade tomar o semáforo para atualizar os dados em um arranjo de temperaturas, uma tarefa de maior prioridade pode ficar bloqueada esperando por esse semáforo.

25 Com múltiplos semáforos é possível colocar u, para proteger a temperaturas e outro para proteger a contagem de erros, com a tarefa de maior prioridade podendo obter o processador sem ficar bloqueado por uso de semáforo, e por outro lado as variáveis compartilhadas continuarão a ser protegidas quando as funções que a utilizam estiverem em suas regiões críticas. Diferentes semáforos podem corresponder a diferentes recursos compartilhados. Como pode um SOTR saber qual semáforo protege qual dado? Ele não sabe. Se você estiver utilizando múltiplos semáforos, você deverá se lembrar de qual semáforo corresponde a qual dado. Uma tarefa que está modificando a contagem de erros deve ter um semáforo correspondente. Você deve decidir qual dado compartilhado cada um de seus semáforos protege.

26 OS SEMÁFOROS COMO DISPOSITIVOS DE SINALIZAÇÃO
Um outro uso comum dos semáforos é como um meio simples de comunicação de uma tarefa com outra, ou de uma rotina de interrupção com uma tarefa. Exemplo: Suponha que a tarefa que formata relatórios impressos construa esses relatórios em um buffer na memória fixa. Suponha também que a impressora interrompa após cada linha e que a rotina de interrupção da impressora alimente a próxima linha para a impressora cada vez que ela interrompe. Em tal sistema, após a formatação de um relatório no buffer, a rotina deve esperar até que a rotina de interrupção tenha terminado de imprimir esse relatório antes de poder formatar o próximo relatório. Uma maneira de resolver esse problema muito facilmente, é fazer a tarefa esperar por um semáforo após ter formatado cada relatório. A rotina de interrupção assinala para a tarefa quando um relatório tiver sido mandado para a impressora liberando o semáforo. Quando a tarefa obtém o semáforo e desbloqueia, ela sabe que pode formatar o próximo relatório.

27 /* Local para construir os relatório */
static char a_chPrint[10][21]; /* Contagem das linhas do relatório */ static int iTotalLinhas; /* Contagem de linhas já impressas */ static int iLinhasImpressas; /* Semáforo para esperar pelo fim do relatório */ Static OS_EVENT *SemImpressora; Continua:

28 void vTarefaImpressora(void)
{ BYTE byErro; /* Local para um retorno de erro */ int wMsg; /* Inicializar o semáforo como já abaixado */ SemImpressora = OSSemInit(0); while(TRUE) /* Espere por uma mensagem dizendo qual relatório formatar * wMsg=(int) OSQPend (QPrinterTask, WAIT_FOREVER, &byErro); !! Formate o relatório em c_chPrint iTotalLinhas = !! Conta o número de linha do relatório /* Imprime a primeira linha do relatório */ iLinhasImpressas=0; vSaidaLinhaImpressoraHard(a_chPrint[iLinhasImpressas++]); /* Espere a tarefa de impressão terminar */ OSSemPend(SemImpressora, WAIT_FOREVER,&byErro); } } continua

29 void vInterrupcaoImpressora(void)
{ if(iLinhasImpressas == iTotalLinhas) /* O relatório está pronto */ OSSemPost (SemImpressora); else /* Imprima a próxima linha */ vSaidaLinhaImpressoraHard(a_chPrint,[LinhasImpressas++]); } A rotina de interrupção libera o semáforo e portanto desbloqueia a tarefa quando o relatório já foi impresso.

30 PROBLEMAS COM SEMÁFOROS
Aparentemente. Os semáforos constituem a solução para todos os problemas de dados compartilhados, porém isso não é verdade. De fato nossos sistemas trabalharão tanto melhor quanto menos utilizarmos os semáforos. O problema é que os semáforos funcionam bem somente se forem utilizados perfeitamente, e ninguém garante, dentro de uma equipe de desenvolvimento, que todos dominam bem o assunto. Modos de se estragar a utilização dos semáforos: Esquecer do abaixar ou tomar o semáforo. O semáforo somente funciona se a tarefa que utiliza o dado compartilhado, para escrita ou leitura, usar o semáforo. Se houver esquecimento, então o SOTR pode chavear pata fora de um código que esqueceu de tomar o semáforo e causa um bug feio de dado compartilhado.

31 Esquecer de liberar o semáforo
Esquecer de liberar o semáforo. Se uma tarefa falha na liberação de um semáforo, então todas as tarefas que utilizam esse semáforo, mais cedo ou mais tarde ficarão bloqueadas esperando obtê-lo numa condição de bloqueio eterno. Tomando o semáforo errado. Em um sistema de múltiplos semáforos, isto pode causar problemas imprevisíveis. Mantendo um semáforo por muito tempo. Sempre que uma tarefa toma um semáforo, todas as tarefas que utilizam este semáforo deve esperar até que esse semáforo seja liberado. Se uma tarefa matém um semáforo por muito tempo, outras tarefas podem falhar em suas operações de tempo real devido a ficarem fora do tempo (deadline). Um exemplo particularmente perverso disso, ocorre se o SOTR chavear de uma tarefa de baixa prioridade (Tarefa C) para uma de prioridade média de longa duração (Tarefa B) , após a tarefa C tomar um semáforo. Uma tarefa de alta prioridade (Tarefa A) que deseja o semáforo tem então que esperar até que a tarefa B libere o processador: A tarefa C não pode liberar o semáforo até que ela obtenha o controle do processador. Não importa o quão cuidadosamente se tenha codificado a tarefa C, a tarefa B não permite que a tarefa C acesse o processador e isso coloca a tarefa A em espera indefinida.

32 Problema de inversão de prioridade
Esse problema é denominado inversão de prioridade, alguns SOTR resolvem esse problema com herança de prioridade – Eles reforçam temporariamente a prioridade da tarefa C para igual a da tarefa A, toda vez que a tarefa C obtém o semáforo e a tarefa A está esperando por ele.

33 Provocando um abraço mortal
O código do próximo slide mostra o problema do abraço mortal . As funções ajsmrsv() e ajmrls() do código, são de um SOTR denominado AMX (Kadak Products). A função ajsmrsv() “reserva” um semáforo, e a função ajmrls() “libera” o semáforo. Os dois parâmetros adicionais a ajsmrsv() são as informações de time-out e a prioridade que não são relevantes aqui. No código, tanto Tarefa1 como Tarefa2 atuam sobre as variáveis a e b após obter a permissão de uso pela obtenção dos semáforos hSemaphoreA e hSemaphoreB. Dá para ver qual é o problema? Considere o que ocorre se vTarefa1 chamar ajsmrsv() para obter hSemaphoreA, mas antes dela poder chamar ajsmrsv() para obter o hSemaphoreB, o SOTR para e roda vTarefa2. A tarefa vTarefa2 agora chama ajsmrsv() para obter hSemaphoreB, quando vTarefa2 chama ajsmrsv() para obter hSemaphoreA, ela bloqueia, porque uma outra tarefa (vTarefa1) já está com hSemaphoreA. O SOTR chaveia de volta para vTarefa1, a qual chama agora ajsmrsv() para a obtenção de hSemaphoreB, que já está com vTarefa2, assim vTarefa1 bloqueia. Como nenhuma das tarefas liberará seu semáforo e ao mesmo temo estão esperando a liberação do semáforo da outra, termos um abraço mortal ou sistema em deadlock.

34 Int a; Int b; AMXID hSemaphoreA; AMXID hSemaphoreB; void Tarefa1(void) { ajsmrsv(hSemaphoreA, 0, 0); ajsmrsv(hSemaphoreB, 0, 0); a=b; ajsmrls(hSemaphoreB, 0, 0); } void Tarefa2(void) b=a; ajsmrls(hSemaphoreA, 0, 0);

35 Variações nos Semáforos
Existem tipos diferentes de semáforos e podem variar de SOTR para SOTR. Alguns sistemas oferecem semáforos que podem ser tomados múltiplas vezes. Tais semáforos são essencialmente inteiros, a tomada dos mesmo decrementa o inteiro associado ao mesmo e a liberação incrementa esse inteiro. Se uma tarefa tentar tomar o semáforo quando o inteiro associado ao mesmo é zero, ela bloqueará. Esses semáforos são chamados de semáforos contadores e constituem o tipo original de semáforos. Alguns sistemas oferecem semáforos que podem ser liberados apenas pela tarefa que os tomou. Esses semáforos são úteis nos problemas de dados compartilhados, mas não podem ser utilizados para comunicação entre duas tarefas. Tais semáforos são chamados de semáforos de recurso. Alguns SOTR oferecem semáforos para lidar especificamente com o problema de inversão de prioridade e outro que não lida com isso. O semásforo do primeiro caso é denominado de semáforo mutex ou simplesmente mutex. ( Alguns SOTR usam semáforos que eles chamam de mutex, mas não lidam com o problema de inversão de prioridade).

36 COMPARAÇÃO ENTRE OS TRÊS MÉTODOS
Maneiras de Proteger Dados Compartilhados Em geral os dois modos de se proteger dados compartilhados é através da desabilitando as interrupções e utilizando semáforos. Existe um outro modo que merecer ser mencionado que é a desabilitação do chaveamento de tarefa. A maioria dos SOTR tem duas funções que podem ser chamadas, uma de desabilitação do chaveamento de tarefa e outra de reabilitação do chaveamento das mesmas. COMPARAÇÃO ENTRE OS TRÊS MÉTODOS Desabilitação das Interrupções: é o método mais dramático, visto que afeta os tempos de respostas de todas as rotinas de interrupção e de todas as tarefas do sistema, uma vez que isso coloca o escalonador do sistema fora de ação, por outro lado a desabilitação das interrupções têm duas vantagens. (1) É o único método que funciona se nosso dados forem compartilhados entre nossas tarefas e nossas rotinas de interrupção. Note que a desabilitação do chaveamento entre tarefas não desabilita as interrupções, por outro lado a desabilitação das interrupções desabilitará o chaveamento entre tarefas.

37 (2)É rápido. A maioria doa processadores pode habilitar e desabilitar interrupções com uma única instrução, enquanto que todas as funções dos SOTR têm muitas instruções. Se o acesso de uma tarefa a um dado compartilhado demora apenas um curto período de tempo – o incremento de uma variável, por exemplo – as vezes é preferível sofre um pequeno contratempo na respostas das rotinas de interrupção, devido a desabilitação da interrupções, que contratempos nas respostas das tarefas devido ao uso de semáforos ou desabilitação do chaveamento das tarefas. Semáforos é o meio mais visado para se proteger dados, devido aos seus efeitos apenas sobre as tarefas que necessitam utilizar o mesmo semáforo. Os tempos de resposta das tarefas e das rotinas de interrupção que não necessitam do semáforo ficam invariáveis. Por outro lado os semáforos consomem algum tempo de processamento, embora não muito na maioria dos SOTR e eles não funcionam para rotinas de interrupçao. Desabilitação do Chaveamento de Tarefas Está em algum lugar entre os dois mencionados acima. Nâo tem efeito sobre as rotinas de interrupçao, mas paralisa a resposta do processador para todas as outras tarefas.


Carregar ppt "REENTRÂNCIA Funções reentrantes são aquelas que podem ser chamadas por mais de uma tarefa e ainda assim, sempre trabalham corretamente, mesmo que o SOTR."

Apresentações semelhantes


Anúncios Google