Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Reentrant функция
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
toweroff
Добрый день!

Есть у меня 2 одинаковые задачи. Одинаковые с точностью до записи в один индикатор или другой, проверки этого датчика или этого
Замучился уже отлаживаться в одной задаче, потом копипастить во вторую и сидеть выверять куда там что отправилось и что проверилось

Идея-то давно витала - сделать одну reentrant функцию, в которую в качестве параметра будет валиться только OS_TID, из которой ее вызвали. Но как это грамотно сделать - пока не разбирался, да и смущает еще такой момент. В этой функции активно используются ожидания таймаута или событий. Как эти функции RTX будут вести себя в reentrant-функциях?
Вообще Keil RTX поддерживает такие вещи?

UPD
С кейлом вроде как порядок. (тыц)

Теперь остается узнать, как правильно писать reentrant функции? sm.gif
alexeyv
1. Не используйте статические, глобальные и иные переменные, которые могут повлиять на выполнение кода в другом потоке
2. Локальные переменные д.б. размещены в стеке (выполняется почти всегда по умолчанию)
3. Функция не должна возвращать к-либо глобальные указатели/объекты
4. И вообще, в функцию необходимо передавать только указатель на объект/структуру с данным объектом, в котором должны быть все данные, необходимые для работы, и там же необходимо сохранять все результаты работы функции над данным объектом
5. Если используете объекты синхронизации (мьютексы, семафоры и т.д.) - то необходимо детально проработать их использование - иначе деадлок

Как-то так, если своими словами.

AlexandrY
Цитата(alexeyv @ Dec 21 2012, 06:06) *
1. Не используйте статические, глобальные и иные переменные, которые могут повлиять на выполнение кода в другом потоке
2. Локальные переменные д.б. размещены в стеке (выполняется почти всегда по умолчанию)
3. Функция не должна возвращать к-либо глобальные указатели/объекты
4. И вообще, в функцию необходимо передавать только указатель на объект/структуру с данным объектом, в котором должны быть все данные, необходимые для работы, и там же необходимо сохранять все результаты работы функции над данным объектом
5. Если используете объекты синхронизации (мьютексы, семафоры и т.д.) - то необходимо детально проработать их использование - иначе деадлок

Как-то так, если своими словами.


Вы здесь описали какое-то чудо, но не реентерабельные функции.
Можно в эти функции и глобальные переменные передавать, можно и глобальные переменные возвращать.
Зато внутри них не должно быть статических переменных.
Обращение к глобальным переменным просто надо защитить.
А вот уже чем защитить есть некоторый нюанс.
Простой запретить прерываний будет плохо отражаться на риалтайме.
Если использовать семафоры, то если функция работает под разными задачами и над разными глобальными переменными, то и семафоры должны быть разные.
И тогда функции надо передать эти семафоры.
Я делаю так. Я семафоры включаю в структуру задачи. Функции же всегда могут определить идентификатор задачи в которой они выполняются. И по этому идентификатору найти свои семафоры. Тоже относится и к очередям и к мьютексам и проч.
SM
Цитата(AlexandrY @ Dec 21 2012, 12:13) *
Зато внутри них не должно быть статических переменных.


Это еще с какого перепуга? Просто их тоже надо защитить как и глобальные, если, конечно, они сами не "средство защиты" (например семафор доступа к ресурсу, с которым работает ф-ция).
AlexandrY
Цитата(SM @ Dec 21 2012, 10:26) *
Это еще с какого перепуга? Просто их тоже надо защитить как и глобальные, если, конечно, они сами не "средство защиты" (например семафор доступа к ресурсу, с которым работает ф-ция).


Т.е. защитить!? Какой тогда в них смысл?
Как у одной и той же функции выполняющейся в разных задачах будет свой экземпляр статической переменной, т.е. такой которая сохраняется не в стеке?
SM
Цитата(AlexandrY @ Dec 21 2012, 13:13) *
Как у одной и той же функции выполняющейся в разных задачах будет свой экземпляр статической переменной, т.е. такой которая сохраняется не в стеке?


Зачем свой? В том и суть, что он, экземпляр такой переменной, один для всех задач. Допустим функция работает с неким аппаратным ресурсом, осуществляя полное им управление, а другие функции с ним не работают. Функция захватывает владение ресурсом, используя семафор, (как вариант - находящийся в статической переменной внутри ф-ции, так как в принципе он никому кроме этой ф-ции не нужен), и затем может свободно распоряжаться остальными статическими переменными, связанными с работой с этим ресурсом, после чего освобождает семафор. Глобальная видимость этим переменным совершенно не нужна, раз кроме как в этой ф-ции, они нигде не используются, поэтому использование статических переменных, определенных внутри ф-ции, будет одним из оптимальных решений, и при этом с реентерабельностью (они защищены вместе с аппататным ресурсом семафором). И, заодно, будет защита от случайных ошибок, если по неосторожности будет написан код, обращающийся к этим переменным откуда то не оттуда.

Или, самый элементарный пример - нужно знать, какой это экземпляр по счету из одновременно запущенных функций - статическая переменная, интерлокед инкремент при входе в ф-цию, и такой же декремент при выходе. И этому данному тоже не надо иметь видимость где либо вне ф-ции.
AlexandrY
Цитата(SM @ Dec 21 2012, 12:29) *
Или, самый элементарный пример - нужно знать, какой это экземпляр по счету из одновременно запущенных функций - статическая переменная, интерлокед инкремент при входе в ф-цию, и такой же декремент при выходе. И этому данному тоже не надо иметь видимость где либо вне ф-ции.


Мда, в принципе возразить трудно.
Но тогда не остается ни одного формального отличительно признака реентерабельной функции! wacko.gif biggrin.gif
Все зависит от контекста?

toweroff
Цитата(AlexandrY @ Dec 21 2012, 15:30) *
Все зависит от контекста?

я вот тоже к этому склоняюсь sm.gif
если сферический конь, то таки да, статические переменные в подобных функциях неприемлемы. А вот если их использование (да вообще использование всего) четко оговорено, то почему бы и нет?
У меня пяток локальных переменных, да вызовы (помимо функций RTX) пары моих функций, у которых также только локали и в качестве параметра - канал SSP (SSP0 или SSP1) и пяток байт, так что копии друг другу не помешают
SM
Цитата(AlexandrY @ Dec 21 2012, 15:30) *
Но тогда не остается ни одного формального отличительно признака реентерабельной функции! wacko.gif biggrin.gif
Все зависит от контекста?


Формального и нету. Она лишь должна корректно работать при одновременном вызове из некоторых различных тредов/процессов/прерываний/т.п., а как это реализовано - хоть данные на стеке, хоть в десяти разных местах с выбором указателя на место в зависимости от ID треда (или например текущей глубины вложения вызова), хоть еще как - это лишь от удобства реализации и фантазии программиста зависит.



Кстати, автору... А какой процессор то? Кейл кейлом, а вот если речь о 51 например - то там придется десять раз подумать, так как локальные переменные там не в стеке, и придется делать свою реализацию раздельных мест хранения локальных данных.
toweroff
Цитата(SM @ Dec 21 2012, 16:42) *
Кстати, автору... А какой процессор то? Кейл кейлом, а вот если речь о 51 например - то там придется десять раз подумать, так как локальные переменные там не в стеке, и придется делать свою реализацию раздельных мест хранения локальных данных.

и то правда, забыл... CortexM3
с Cx51 проще, там было такое
Код
void func(void) reentrant
{
}

почему убрали из CARM - не понять локомотива прогресса
SM
Цитата(toweroff @ Dec 22 2012, 11:58) *
почему убрали из CARM - не понять локомотива прогресса


потому что там все на стеке, а стека завались. Не актуально, оно всегда "reentrant" c тем ABI, что там. Нереентерабельность можно разве что самому написать при неосторожным обращении с глобальными и статическими ресурсами/переменными
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.