Перейти к содержанию
    

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 Сергей Борщ

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

 

2 AHTOXA

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 Сергей Борщ

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Что-то типа

    for(;;)
   {
       Sleep(10);

        . . . 

   }

 

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

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

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

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

 

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...