|
Зависает один процесс |
|
|
|
Mar 31 2010, 12:30
|
Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205

|
Здравствуйте! Столкнулся с проблемой зависания процесса, который занимается аналоговыми измерениями. Всего в системе 4 процесса, приоритеты распределены следующим образом Код #define ANMEAS_PRI (OS::pr1) /* Аналоговые измерения */ #define UART0_PRI (OS::pr0) /* Работа с UART */ #define TECHNO_PRI (OS::pr3) /* Технология (логика работы программы) */ #define PERIPH_PRI (OS::pr2) /* Работа с периферийными устройствами */ Если я меняю значение приоритета ANMEAS_PRI на максимальный (с OS::pri1 на OS::pri0) то зависания пропадают. Проблема в том что я не могу разобраться почему в одном случае оно работает, а в другом - нет. Исходный код доступен здесь. Для поиска неисправностей, я написал небольшой макрос (SET_INFO(x)), который посылает в UART текущий номер, все вызовы макроса расположены в порядке возрастания порядкового номера. Модифицированный вариант исходника лежит здесь. Таким образом установил, что после зависания процесса, в UART отправляется число 26 Код 104 } 105 SET_INFO(26); 106 107 Sleep(5,5);// 11 mc 108 SET_INFO(27); 109 LED_Out_Str[24] = GREEN_LAMP; 110 SET_INFO(28); Т.е. прямо перед вызовом функции Sleep(). Далее я перегрузил функцию Sleep() (чтоб вызывалась конкретная функция только для одного процесса), и модифицировал по описанной выше методике, получилось такое Код void TBaseProcess::Sleep(TTimeout timeout, uint8_t huita) { { TCritSect cs;
SET_INFO(30); Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout; SET_INFO(31); Kernel.SetProcessUnready(Kernel.CurProcPriority); SET_INFO(32); Kernel.Scheduler(); SET_INFO(33); } SET_INFO(34); } Теперь последнее отправляемое число в UART 32, т.е. прямо перед вызовом Kernel.Scheduler(). Дальше лезть страшно. В чем может возникать проблема что при смене приоритетов процесс наглухо зависает? Может есть какие-то рекомендации, чего делать не стоит или у меня какие-то существенные ошибки в описании процесса? Заранее Спасибо!:)) P.S. Версия scmRTOS 3.10, компилятор avr-gcc (4.3.3)
|
|
|
|
|
Mar 31 2010, 14:19
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание. И если процесс uart у вас продолжет работать, то в нем можно выводить наружу по запросу адрес такого сервиса. Далее поиском по map-файлу находим, что за сервис и думаем, почему он не отпускает процесс: Код в Kernel.h, в TBaseProcess: void *waiter() { return Waiter; } // <----- protected: void *Waiter; // <----- TStackItem* StackPointer; TTimeout Timeout; TPriority const Priority;
а в сервисах, в меестах ожидания, вызов Kernel.Scheduler() обрамляем: ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map Kernel.ProcessTable[Kernel.CurProcPriority]->Waiter = this; // <----- Kernel.Scheduler(); Kernel.ProcessTable[Kernel.CurProcPriority]->Waiter = 0; // <---- Остается по какому-то событию пройтись по Kernel.ProcessTable и выдать наружу результат waiter().
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 29 2011, 12:31
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 22-12-05
Пользователь №: 12 556

|
Столкнулся с похожей проблемой. Есть проект, где в паре процессов используется в основном цикле Sleep. Что-то типа CODE for(;;) { Sleep(10); . . .
} Время от времени (достаточно редко) процессы застревают именно в Sleep. Timeout процесса при этом равен нулю. Процесс к выполнению в карте процессов не готов. Порт под STM Cortex-M3. IAR 6.10. Стек не переполняется с запасом. Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать. Некорректное использование переменных с доступом из разных процессов может приводить к такому? Правда одновременная модификация нигде не используется.
|
|
|
|
|
Mar 30 2011, 03:02
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(BAT @ Mar 29 2011, 19:31)  Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать. Некорректное использование переменных с доступом из разных процессов может приводить к такому? Правда одновременная модификация нигде не используется. Сложно сказать удалённо. Возможно, что с вашей стороны косяков и нет. Есть нюанс, связанный с приоритетным многоуровневым аппаратным контроллером и приоритетом прерывания переключения контекстов, который в текущей версии не учитывается (пофиксен в новой версии, которая готовится к выпуску). Не знаю в деталях, как это устроено у кортекса, и как это сконфигурировано в порте, поэтому, возможно, дело не в этом. Но на всякий случай. Добавьте в OS::TKernel::context_switch_hook() (OS_Kernel.h) первой строчкой TCritSect cs; и посмотрите, пропадёт ли зависание.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Mar 30 2011, 06:33
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 22-12-05
Пользователь №: 12 556

|
Цитата(AHTOXA @ Mar 30 2011, 08:34)  Меня смутила эта фраза. Вы хотели сказать - "стеки"? ну да  конечно для каждого процесса свой просто как-то по старой очень привычке называю их одним иногда Попробую добавить TCritSect cs. Попозже напишу результат.
|
|
|
|
|
Mar 30 2011, 08:18
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 22-12-05
Пользователь №: 12 556

|
CODE TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp) { TCritSect cs; <--- здесь
ProcessTable[CurProcPriority]->StackPointer = sp; sp = ProcessTable[SchedProcPriority]->StackPointer;
#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 ContextSwitchUserHook(); #endif
CurProcPriority = SchedProcPriority; return sp; } Туда я добавил? Если да, то не помогло  . Все это чаще всего проявляется, когда активно начинает работать высокоприоритетный процес + идет активно связь по компорту, а она реализована в силу особенностей на прерываниях с использованием канала оси. OS::TISRW ISR на обработчиках стоит.
|
|
|
|
|
Mar 30 2011, 12:56
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(BAT @ Mar 30 2011, 15:18)  Туда я добавил? Если да, то не помогло  . Все это чаще всего проявляется, когда активно начинает работать высокоприоритетный процес + идет активно связь по компорту, а она реализована в силу особенностей на прерываниях с использованием канала оси. OS::TISRW ISR на обработчиках стоит. Да, добавили правильно. Если у вашего порта приоритетный контроллер прерываний и прерывание переключения контекстов может быть прервано (вытеснено) другим прерыванием, то эту критическую секцию надо там оставить (иначе чревато проблемами). В противном случае можно убрать. Причину найти с ходу тяжело. Если есть возможность, то для начала добиться повторяемости (определить, при каких условиях это происходит). Тогда уже можно экспериментировать с целью локализовать проблему. По симптомам вообще похоже на переполнение стека, когда данные стека налезают на чужую память. Ну, и вообще, такое поведение характерно для ошибок работы с памятью, когда из-за неправильной адресации портится чужая память. Посмотрите - остальные потроха объекта-процесса не портятся? Только Timeout? По размерам стеков как определили, что их объём достаточен? По самой оси кроме вышеописанного косяка с приоритетными контроллерами прерываний, вопросов, вроде, не замечено.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Mar 30 2011, 13:19
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 22-12-05
Пользователь №: 12 556

|
Остальные данные в объектах-процессах не портятся. Насколько я смог увидеть. Стек проверяю простой инициализацией его константой и потом просто в отладчике отслеживаю сколько не модифицировалось. Пока проект в отладке стараюсь выделять с сильным запасом(часто более 2х кратного). Кстати, в новом релизе не планируется добавить дебагрежима на такие случаи, чтоб были переменные с данными по использованию стеков?
Самое неприятное, что ошибка вылезает нечасто. И пока не могу добиться стабильности в этом.
|
|
|
|
|
Mar 30 2011, 14:15
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(dxp @ Mar 30 2011, 18:56)  Да, добавили правильно. Если у вашего порта приоритетный контроллер прерываний и прерывание переключения контекстов может быть прервано (вытеснено) другим прерыванием, то эту критическую секцию надо там оставить (иначе чревато проблемами). В противном случае можно убрать. В порте(ах) для Cortex-M3 прерывания при вызове OS::TKernel::ContextSwitchHook() и так запрещены: OS_Target_asm.S: Код PendSVC_ISR: CPSID I // Prevent interruption during context switch ... LDR R1, =os_context_switch_hook // os_context_switch_hook(); BLX R1 так что эта критическая секция не нужна.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Mar 31 2011, 05:04
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(AHTOXA @ Mar 30 2011, 21:15)  В порте(ах) для Cortex-M3 прерывания при вызове OS::TKernel::ContextSwitchHook() и так запрещены: OS_Target_asm.S: Код PendSVC_ISR: CPSID I // Prevent interruption during context switch ... LDR R1, =os_context_switch_hook // os_context_switch_hook(); BLX R1 так что эта критическая секция не нужна. Ты про свой порт или это у IAR'ного подсмотрел? Цитата(BAT @ Mar 30 2011, 20:19)  Кстати, в новом релизе не планируется добавить дебагрежима на такие случаи, чтоб были переменные с данными по использованию стеков? Да, будет специальный режим отладки (кстати, это уже есть, лежит в репозитории в ветке, которая относится к подготовке релиза, pre-v400), и интерфейс (специальная функция) для получения информации о запасе по стеку. Также, будет возможность засекать адрес сервиса, который ожидает процесс - бывает, что процесс висит, чего-то ждёт, тут полезно бывает узнать, чего он ждёт. Ещё будет профилировка работы процессов (два вида, в виде расширений). Всё это будет подробно описано в документации. Цитата(BAT @ Mar 30 2011, 20:19)  Самое неприятное, что ошибка вылезает нечасто. И пока не могу добиться стабильности в этом. Вот это и есть ключ к решению - если добиться повторяемости, тогда станет понятно, в каких условиях оно проявляется и, меняя условия, можно будет локализовать проблему.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|