Видимо так будет получаться, что помимо статей, в блоге будет некоторое количество мимоходных заметок. Встречайте первую из них.
Так уж исторически случилось, что сейчас пишу под AVR, а точнее под ATmega64. Железка сама по себе интересная, с богатой переферией, но речь не об этом. Среда разработки IAR, компилятор их же. Это вводная, а теперь суть.Есть у IAR'а некоторый набор расширений, для удобства, так сказать. Предметом разговора сегодня будет ключевое слово __monitor. Вот что нам говорит про него документация:
The __monitor keyword causes interrupts to be disabled during execution of the function. This allows atomic operations to be performed, such as operations on semaphores that control access to resources by multiple processes. A function declared with the __monitor keyword is equivalent to any other function in all other respects. (IAR C/C++ Compiler Reference Guide p. 210)
Ну что можно сказать, просто отлично, то что надо, кроме того, обещают:
A monitor function causes interrupts to be disabled during execution of the function. At function entry, the status register is saved and interrupts are disabled. At function exit, the original status register is restored, and thereby the interrupt status that existed before the function call is also restored. (IAR C/C++ Compiler Reference Guide p. 52)
Ну что можно сказать, просто отлично, то что надо, кроме того, обещают:
A monitor function causes interrupts to be disabled during execution of the function. At function entry, the status register is saved and interrupts are disabled. At function exit, the original status register is restored, and thereby the interrupt status that existed before the function call is also restored. (IAR C/C++ Compiler Reference Guide p. 52)
А дальше приводиться пример кода реализующего атомарную блокировку ресурса. Всё бы хорошо, но не дайте себе обмануться. Может сложиться впечатление что по выходу из __monitor функции разрешает прерываия, но нет.
Понять, что такое поведение было бы некорректно, просто. Предположим случай вложенного вызова одной __monitor функции foo() из другой __monitor функции bar(). Если бы по выходу из foo() прерывания разрешались, то остаток bar() выполнялся бы не эксклюзивно и мог быть прерван. Такое поведение не предполагалось нами при объявлении bar(). Вызов не __monitor из bar() так же неоднозначен. Единственным разумным выходом оказалось не разрешать прерывания по выходу из __monitor функций, что и подтвердил дизассемблированный код.
Разработчики же документации на компилятор получают минус в карму за откровенный обман:
A monitor function causes interrupts to be disabled during execution of the function. At function entry, the status register SREG is saved and global interrupts are disabled. At function exit, the global interrupt enable bit (I) is restored in the SREG register, and thereby the interrupt status existing before the function call is also restored. (IAR C/C++ Compiler Reference Guide p. 107)
Из всего этого можно сделать простой вывод, что
только критическая оценка и эксперимент дают адекватное представление о действительности.
2 комментария:
в концу __monitor`ной функции прерывания не разрешаются, а просто восстанавливается sreg.
Не было такого, вот о чем я. Сейчас проверить не могу, но точно не было.
Отправить комментарий