|
|
  |
Reentrant функция, Keil, RTX |
|
|
|
Dec 20 2012, 10:14
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Добрый день! Есть у меня 2 одинаковые задачи. Одинаковые с точностью до записи в один индикатор или другой, проверки этого датчика или этого Замучился уже отлаживаться в одной задаче, потом копипастить во вторую и сидеть выверять куда там что отправилось и что проверилось Идея-то давно витала - сделать одну reentrant функцию, в которую в качестве параметра будет валиться только OS_TID, из которой ее вызвали. Но как это грамотно сделать - пока не разбирался, да и смущает еще такой момент. В этой функции активно используются ожидания таймаута или событий. Как эти функции RTX будут вести себя в reentrant-функциях? Вообще Keil RTX поддерживает такие вещи? UPD С кейлом вроде как порядок. ( тыц) Теперь остается узнать, как правильно писать reentrant функции?
|
|
|
|
|
Dec 21 2012, 08:13
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(alexeyv @ Dec 21 2012, 06:06)  1. Не используйте статические, глобальные и иные переменные, которые могут повлиять на выполнение кода в другом потоке 2. Локальные переменные д.б. размещены в стеке (выполняется почти всегда по умолчанию) 3. Функция не должна возвращать к-либо глобальные указатели/объекты 4. И вообще, в функцию необходимо передавать только указатель на объект/структуру с данным объектом, в котором должны быть все данные, необходимые для работы, и там же необходимо сохранять все результаты работы функции над данным объектом 5. Если используете объекты синхронизации (мьютексы, семафоры и т.д.) - то необходимо детально проработать их использование - иначе деадлок
Как-то так, если своими словами. Вы здесь описали какое-то чудо, но не реентерабельные функции. Можно в эти функции и глобальные переменные передавать, можно и глобальные переменные возвращать. Зато внутри них не должно быть статических переменных. Обращение к глобальным переменным просто надо защитить. А вот уже чем защитить есть некоторый нюанс. Простой запретить прерываний будет плохо отражаться на риалтайме. Если использовать семафоры, то если функция работает под разными задачами и над разными глобальными переменными, то и семафоры должны быть разные. И тогда функции надо передать эти семафоры. Я делаю так. Я семафоры включаю в структуру задачи. Функции же всегда могут определить идентификатор задачи в которой они выполняются. И по этому идентификатору найти свои семафоры. Тоже относится и к очередям и к мьютексам и проч.
|
|
|
|
|
Dec 21 2012, 10:29
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(AlexandrY @ Dec 21 2012, 13:13)  Как у одной и той же функции выполняющейся в разных задачах будет свой экземпляр статической переменной, т.е. такой которая сохраняется не в стеке? Зачем свой? В том и суть, что он, экземпляр такой переменной, один для всех задач. Допустим функция работает с неким аппаратным ресурсом, осуществляя полное им управление, а другие функции с ним не работают. Функция захватывает владение ресурсом, используя семафор, (как вариант - находящийся в статической переменной внутри ф-ции, так как в принципе он никому кроме этой ф-ции не нужен), и затем может свободно распоряжаться остальными статическими переменными, связанными с работой с этим ресурсом, после чего освобождает семафор. Глобальная видимость этим переменным совершенно не нужна, раз кроме как в этой ф-ции, они нигде не используются, поэтому использование статических переменных, определенных внутри ф-ции, будет одним из оптимальных решений, и при этом с реентерабельностью (они защищены вместе с аппататным ресурсом семафором). И, заодно, будет защита от случайных ошибок, если по неосторожности будет написан код, обращающийся к этим переменным откуда то не оттуда. Или, самый элементарный пример - нужно знать, какой это экземпляр по счету из одновременно запущенных функций - статическая переменная, интерлокед инкремент при входе в ф-цию, и такой же декремент при выходе. И этому данному тоже не надо иметь видимость где либо вне ф-ции.
|
|
|
|
|
Dec 21 2012, 12:42
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(AlexandrY @ Dec 21 2012, 15:30)  Но тогда не остается ни одного формального отличительно признака реентерабельной функции! Все зависит от контекста? Формального и нету. Она лишь должна корректно работать при одновременном вызове из некоторых различных тредов/процессов/прерываний/т.п., а как это реализовано - хоть данные на стеке, хоть в десяти разных местах с выбором указателя на место в зависимости от ID треда (или например текущей глубины вложения вызова), хоть еще как - это лишь от удобства реализации и фантазии программиста зависит. Кстати, автору... А какой процессор то? Кейл кейлом, а вот если речь о 51 например - то там придется десять раз подумать, так как локальные переменные там не в стеке, и придется делать свою реализацию раздельных мест хранения локальных данных.
|
|
|
|
|
Dec 22 2012, 07:58
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(SM @ Dec 21 2012, 16:42)  Кстати, автору... А какой процессор то? Кейл кейлом, а вот если речь о 51 например - то там придется десять раз подумать, так как локальные переменные там не в стеке, и придется делать свою реализацию раздельных мест хранения локальных данных. и то правда, забыл... CortexM3 с Cx51 проще, там было такое Код void func(void) reentrant { } почему убрали из CARM - не понять локомотива прогресса
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|