Компоненты и технологии • №2 '2011 компоненты


Реентерабельность функций



Pdf көрінісі
бет78/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   74   75   76   77   78   79   80   81   ...   129
Kurniz

Реентерабельность функций
Функция называется реентерабельной, 
если она корректно работает при одновре-
менном ее вызове из нескольких задач и/или 
прерываний. Под одновременным вызовом 
понимается вызов функции из одной задачи 
в тот момент, когда та уже вызвана из другой 
задачи, но еще не выполнена до конца.
Во FreeRTOS каждая задача имеет свой соб-
ственный стек и свой набор значений реги-
стров процессора. Если функция использует 
переменные, расположенные только в стеке 
или в регистрах процессора, то она является 
реентерабельной. Напротив, функция, кото-
рая сохраняет свое состояние между вызова-
ми в статической или глобальной перемен-
ной, не является реентерабельной.
Таким образом, функция, которая зависит 
только от своих параметров, не использует 
глобальные и статические переменные и вы-
зывает только реентерабельные функции, 
будет реентерабельной [4].
Одновременный вызов нереентерабель-
ной функции из нескольких задач может 
привести к непредсказуемому результату. 
Реентерабельными функциями можно поль-
зоваться, не опасаясь одновременного их вы-
зова из нескольких задач.
Рассмотрим пример реентерабельной 
функции:
/* Параметр передается в функцию через регистр общего назначе-
ния или стек. Это безопасно, т. к. каждая задача имеет свой набор 
регистров и свой стек. */
long lAddOneHundered( long lVar1 )
{
/* Объявлена локальная переменная. Компилятор расположит ее 
или в регистре или в стеке в зависимости от уровня оптимизации. 
Каждая задача и каждое прерывание, вызывающее эту функцию, 
будет иметь свою копию этой локальной переменной. */
long lVar2;
/* Какие-то действия над аргументом и локальной переменной. 
*/
lVar2 = lVar1 + 100;
/* Обычно возвращаемое значение также помещается либо в стек, 
либо в регистр. */
return lVar2;
}
Теперь рассмотрим несколько нереентера-
бельных функций:
/* В этом случае объявлена глобальная переменная. Каждая зада-
ча, вызывающая функцию, которая использует эту переменную, 
будет «иметь дело» с одной и той же копией этой переменной */
long lVar1;
/* Нереентерабельная функция 1 */
long lNonReentrantFunction1( void )
{
/* Какие-то действия с глобальной переменной. */
lVar1 += 10;
return lVar1;
}
/* Нереентерабельная функция 2 */
void lNonReentrantFunction2( void )
{
/* Переменная, объявленная как статическая. Компилятор рас-
положит ее не в стеке. Значит, каждая задача, вызывающая эту 
функцию, будет «иметь дело» с одной и той же копией этой 
переменной. */
static long lState = 0;
switch( lState ) { /* … */};
}
/* Нереентерабельная функция 3 */
long lNonReentrantFunction3( void )
{
/* Функция, которая вызывает нереентерабельную функцию, 
также является нереентерабельной. */
return lNonReentrantFunction1() + 100;
}


Достарыңызбен бөлісу:
1   ...   74   75   76   77   78   79   80   81   ...   129




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет