freertos, mutex, interrupções

159 views
Skip to first unread message

Bruno L. Albrecht

unread,
Jun 8, 2017, 12:08:43 PM6/8/17
to piclistbr, sis_emb...@googlegroups.com
pessoal,
to aqui estudando os demos do freertos e me deparei com um problema.

estudei bem a API para os mutexes, em específico no que diz respeito a utilizá-los em interrupções:


Aí diz que não pode usar um mutex (criado com xSemaphoreCreateMutex()) com a função xSemaphoreGiveFromISR().

Pois bem, verifiquem o arquivo IntSemTest.c (um fonte de demos do freertos, na pasta freertos/Demo/Common/Minimal/), mais especificamente o mutex xISRMutex.

Ele é criado na vStartInterruptSemaphoreTasks() -> xISRMutex = xSemaphoreCreateMutex();

e depois é utilizado numa interrupção vInterruptSemaphorePeriodicTest() -> xSemaphoreGiveFromISR( xISRMutex, NULL );

e ai? achei que não podia usar um mutex com essa função (macro).

Eu que entendi algo errado? ou é alguma funcionalidade antiga que acabou ficando ai? ou é um erro feio do freertos mesmo?

Att,
Bruno


--
  Eng. Bruno Landau Albrecht
  e-mail/G-Talk: brun...@gmail.com

Gustavo Laureano

unread,
Jun 8, 2017, 1:27:00 PM6/8/17
to PICLISTBR, sis_emb...@googlegroups.com
Na realidade a principal diferença entre um mutex e um semáforo binário é a possibilidade de causar um deadlock, por isso que mutexes devem ser usados para guardar recursos, e semáforos para realizar sincronia entre tasks

Um mutex sempre deve ser adquirido primeiro e depois liberado sempre na mesma task (e sempre nessa ordem), quando a task adquire o mutex ela se torna dona daquele recurso, caso outra task seja bloqueada tentando adquirir o mutex, a task queé dona do mutex naquele momento tem a sua prioridade elevada para o mesmo nível da task que tenta adquirir, evitando o deadlock..
Como mutexes nao podem ser adquiridos em uma interrupt, eles por consequencia nao podem ser liberados dela, já que a interrupt nao pode adquirir um recurso.

Já semáforos sao mecanismos de sincronização, nenhuma task é dona de um recurso e semáforos podem ser adquiridos dentro de uma task e liberados de uma interrupt.. 

Ah, e mutexes tem um penalti em desempenho devido à essa logica extra


On Thursday, June 8, 2017 at 2:07:55 PM UTC-3, Lucas V. Hartmann wrote:
Estranho mesmo... Pela definição de mutex não faz sentido você usar uma em interrupção.

Mutexes são usadas pra impedir que duas threads usem um mesmo recurso ao mesmo tempo, e acabem uma corrompendo a outra. Pra uma porta serial, por exemplo, isso garante que uma task mande a mensagem completa antes de outra task começar, e evita "Oi mãe!" e "Vai se catar Zé!" de sairem " Oi vai se catar mãe Ze". O procedimento comum é trava-usa-libera na mesma task. Se a mutex estiver ocupada, porém, a segunda task é obrigada a ficar esperando, o que é proibido em interrupções. Essa é a razão que não faz sentdo usar mutex em interrupção.

Se você está travando a mutex em uma task, e tentando liberar via interrupção então você tem um erro conceitual no teu projeto de programa. O que você quer é um semáforo, que espera pacientemente. Mutex é uma espera impaciente, tipo porta de banheiro: "Saí daí FDP, tou me cagando e vc aí escovando dente, libera essa porcaria!"

--
Lucas Vinicius Hartmann

Subscription software is ransomware disguised.

--
WEB: http://www.piclistbr.org | GRUPO: http://groups.piclistbr.org | COMANDOS: http://lista.piclistbr.org
---
Você recebeu essa mensagem porque está inscrito no grupo "PICLISTBR" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para piclistbr+...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

Bruno L. Albrecht

unread,
Jun 8, 2017, 3:18:01 PM6/8/17
to piclistbr, sis_emb...@googlegroups.com
Gustavo,

tu misturou os conceitos. Deadlock pode ocorrer tanto em semáforos binários quanto em mutexes.

Deadlock é quando uma task trava esperando a outra e vice versa. Quando se tem dois mutexes e duas tasks, por exemplo: task 1 pega o mutex 1; task 2 pega o mutex 2; task 1 espera mutex 2 ser liberado pra liberar o mutex 1; task 2 espera o mutex 1 ser liberado pra liberar o mutex 2. Isso é deadlock e é um erro de design da aplicação.

Inversão de prioridade é quando uma task de prioridade mais alta precisa esperar uma task de prioridade mais baixa executar - isso ocorre com semáforos. Por exemplo, 3 tasks com 3 prioridades diferentes (1 é a mais baixa) e um semaforo binario. Task 1 (prioridade baixa) pega o semáforo e começa a executar. Task 3 (prioridade alta) tenta pegar o semáforo e bloqueia esperando. Task 1 volta a processar. Task 2 (prioridade média) interrompe a execução da task 1 pra fazer qualquer coisa (task 3 esperando). Task 1 volta a processar e libera o semaforo. Task 3 pega o semáforo.
Nesse caso, a task 3, de prioridade mais alta, precisou esperar a task 2, que não tem nada a ver com a história do semáforo, executar. Isso foi uma inversão de prioridades.
O que o mutex faz a mais do que o semáforo é a herança de prioridades, ou seja, se uma task de prioridade mais alta bloquear esperando um mutex, a task de prioridade mais baixa que está com o mutex tem sua prioridade aumentada momentaneamente  para que possa executar o mais rápido possível e liberar o mutex. No exemplo que dei acima, a Task 2 não conseguiria interromper a task 1, pois a task 1 teria momentaneamente a mesma prioridade da task 3.


att,
Bruno


Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para piclistbr+unsubscribe@googlegroups.com.

Para mais opções, acesse https://groups.google.com/d/optout.

Gustavo Laureano

unread,
Jun 9, 2017, 6:39:49 AM6/9/17
to PICLISTBR, sis_emb...@googlegroups.com
Bom dia

Voce tem razão Bruno, troquei os termos!


E sobre o assunto original, fui olhar agora ele no arquivo que voce mencionou, e realmente ele libera o mutex de uma interrupt.. mas não dá nenhuma explicação sobre o motivo além de dizer isso:
 * The master is a task that receives a mutex that is given from an interrupt -
 * although generally mutexes should not be used given in interrupts (and
 * definitely never taken in an interrupt) there are some circumstances when it
 * may be desirable.

Mesmo que (como voce ja disse) a referencia da função diga explicitamente que ela nao deve ser usada com mutexes

Dei uma procurada por cima nos foruns do FreeRTOS e nao achei nada questionando isso, agora também estou curioso para saber quais as circunstancias é considerado OK liberar mutex de dentro do contexto de interrupt

Alain Mouette

unread,
Jun 9, 2017, 8:45:48 AM6/9/17
to sis_emb...@googlegroups.com

A recomendação sempre é a mesma: compre o manual... Como o sw é free, o manual é pago e vale cada centavo!!!

Tem um exemplo tipico que eu uso "binary semaphore" que fiz segundo o manual:
A ethernet usa spi e precisa de um mutex para controlar um acesso. A chegada de um pacote gera uma interrupção...
Então tem uma thread de recepção que fica travada nesse semaphore, a IRQ libera o semaphore e daí a thead pode continuar pegando o mutex da spi e ler o pacote que chegou.
Ajustando as prioridades fica rápido e eficiente...

-----
Alain Mouette (ツ)

Você recebeu essa mensagem porque está inscrito no grupo "sis_embarcados" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para sis_embarcado...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para sis_emb...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/sis_embarcados.
Reply all
Reply to author
Forward
0 new messages