Jump to content
    

Зависает один процесс

Здравствуйте!

Столкнулся с проблемой зависания процесса, который занимается аналоговыми измерениями. Всего в системе 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)

Share this post


Link to post
Share on other sites

Для начала разберитесь, почему зависает? Зависнуть он может либо в Sleep(), либо ожидая какого-нибудь события (флаг, мютекс) и не дожидается никогда. Проанализируйте, почему шедулер не ставит его в активное состояние.

Share this post


Link to post
Share on other sites

В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep().

Share this post


Link to post
Share on other sites

В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep().
А остальные процессы при этом продолжают работать?

Share this post


Link to post
Share on other sites

Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание. И если процесс 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().

Share this post


Link to post
Share on other sites

Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание

 

А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? :)

 

2 kurtis: Всё выглядит так, что процесс "Работа с UART" занимает всё процессорное время. Но при этом не работали бы и все остальные процессы, а не только TAnalogMeasure... Они точно работают?

Share this post


Link to post
Share on other sites

А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? :)
0

Можно добавить в OS::TBaseProcess:Sleep() занесение туда какого-то другого числа, скажем (void*) -1, чтобы отличить от работающего процесса, у которого более приоритетный отобрал управление насильно.

Share this post


Link to post
Share on other sites

2 Сергей Борщ

Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure.

 

2 AHTOXA

Остальные работают. В других процессах идет опрос клавиатуры, вывод информации на жки и засветка светодиодов.

Share this post


Link to post
Share on other sites

2 Сергей Борщ

Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure.

Значит, это он уснул добровольно. Посмотрите, чему равно значение таймаута этого процесса. При достижении таймаутом нуля процесс должен быть разбужен. Еще посмотрите ReadyProcessMap - точно ли процесс спит или готов к выполнению (соответствующий бит установлен), но по какой-то причине не работает.

Share this post


Link to post
Share on other sites

Столкнулся с похожей проблемой. Есть проект, где в паре процессов используется в основном цикле Sleep.

Что-то типа

    for(;;)
   {
       Sleep(10);

        . . . 

   }

 

Время от времени (достаточно редко) процессы застревают именно в Sleep.

Timeout процесса при этом равен нулю. Процесс к выполнению в карте процессов не готов.

Порт под STM Cortex-M3. IAR 6.10.

Стек не переполняется с запасом.

 

Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать.

Некорректное использование переменных с доступом из разных процессов может приводить к такому?

Правда одновременная модификация нигде не используется.

Share this post


Link to post
Share on other sites

У меня один раз косяк был, когда я для межпроцессорного обмена использовал глобальную переменную. Избавился от нее и все прошло.

Share this post


Link to post
Share on other sites

Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать.

Некорректное использование переменных с доступом из разных процессов может приводить к такому?

Правда одновременная модификация нигде не используется.

Сложно сказать удалённо. Возможно, что с вашей стороны косяков и нет. Есть нюанс, связанный с приоритетным многоуровневым аппаратным контроллером и приоритетом прерывания переключения контекстов, который в текущей версии не учитывается (пофиксен в новой версии, которая готовится к выпуску). Не знаю в деталях, как это устроено у кортекса, и как это сконфигурировано в порте, поэтому, возможно, дело не в этом. Но на всякий случай. Добавьте в OS::TKernel::context_switch_hook() (OS_Kernel.h) первой строчкой TCritSect cs; и посмотрите, пропадёт ли зависание.

Share this post


Link to post
Share on other sites

Стек не переполняется с запасом.

Меня смутила эта фраза. Вы хотели сказать - "стеки"?

Share this post


Link to post
Share on other sites

Меня смутила эта фраза. Вы хотели сказать - "стеки"?

 

ну да :) конечно для каждого процесса свой

просто как-то по старой очень привычке называю их одним иногда

 

Попробую добавить TCritSect cs. Попозже напишу результат.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...