Ошибка найдена

55 views
Skip to first unread message

Sergey A. Borshch

unread,
Jan 12, 2017, 3:12:06 AM1/12/17
to scmrt...@googlegroups.com
Привествую всех.

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

Ситуация такая: некий процесс с приоритетом (для примера) pr7 запускает
периферию и уходит в спячку в ожидании, скажем, флага или освобождения mutex. В
спячку он уходит находясь в критической секции через OS::TService::suspend(),
там вызывается sched(). Внутри sched() он выясняет, что максимальный приоритет
из готовых у процесса с более низким приоритетом, например у Idle, заносит
prIDLE в SchedProcPriority, делает raise_context_switch() и разрешает прерывания
для вызова прерывания переключателя контекста.

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

В обработчике прерывания периферии в деструкторе OS::TISRW вызывается
sched_isr(), там определяется самый приоритетный процесс (pr7) и происходит
сравнение: if(NextPrty != CurProcPriority), а они равны (напоминаю, что
переключатель контекста еще не вызвался, не отработал переключение в prIDLE и
CurProcPriority все еще равна pr7) и исходя из этого sched_isr() ничего не
делает и просто выходит из прерывания.

После этого наконец-то вызывается запланированный переключатель контекста,
который честно отрабатывает переключение контекста на IdleProc (ведь
SchedProcPriority у нас так и остался равным prIdle) и мы при готовом к
выполнению pr7 сидим в prIDLE до следующего прерывания c OS::TISRW или до
следующего тика системного таймера.

Предлагаемое решение - в sched_isr() вынести из-под условия SchedProcPriority =
NextPrty; т.е. заменить

void OS::TKernel::sched_isr()
{
uint_fast8_t NextPrty = highest_priority(ReadyProcessMap);
if(NextPrty != CurProcPriority)
{
SchedProcPriority = NextPrty;
raise_context_switch();
}
}

на

void OS::TKernel::sched_isr()
{
uint_fast8_t NextPrty = highest_priority(ReadyProcessMap);
SchedProcPriority = NextPrty;
if(NextPrty != CurProcPriority)
raise_context_switch();
}

Решение проверено, проблему решает. Есть какие-нибудь возражения?

--
Regards,
Sergey A. Borshch mailto: sb...@sourceforge.net
SB ELDI ltd. Riga, Latvia

Harry Zhurov

unread,
Jan 12, 2017, 3:27:12 AM1/12/17
to scmrt...@googlegroups.com
01/12/2017 03:12 PM, Sergey A. Borshch пишет:
> Нашел новую ошибку в коде ОС. Ошибка не критичная, к падению не
> приводит. Вкратце - если прерывание, будящее сервис происходит до
> того, как вызвалось прерывание переключателя контекста, усыпляющее
> этот сервис, то пробуждение сервиса затягивается (в худшем случае на
> один тик системного таймера).

<...>

> void OS::TKernel::sched_isr() { uint_fast8_t NextPrty =
> highest_priority(ReadyProcessMap); SchedProcPriority = NextPrty;
> if(NextPrty != CurProcPriority) raise_context_switch(); }
>
> Решение проверено, проблему решает. Есть какие-нибудь возражения?
>
Если всё работает, то внести правку в ветку develop. Сам сделаешь или мне?

__
HZ


oesd.ru


Anton Gusev

unread,
Jan 12, 2017, 3:31:04 AM1/12/17
to scmrt...@googlegroups.com
Sergey A. Borshch пишет 12.01.2017 13:12:
> void OS::TKernel::sched_isr()
> {
> uint_fast8_t NextPrty = highest_priority(ReadyProcessMap);
> SchedProcPriority = NextPrty;
> if(NextPrty != CurProcPriority)
> raise_context_switch();
> }
>
> Решение проверено, проблему решает. Есть какие-нибудь возражения?

Да, логический косяк.
Может, для пущей ясности ввести специальную функцию, типа

INLINE void TKernel::switch_context_to(uint_fast8_t newPriority)
{
SchedProcPriority = newPriority;
raise_context_switch();
}

И заменить вызовы raise_context_switch() на вызовы этой функции?

Там, конечно, всего два места, но так будет яснее.

Harry Zhurov

unread,
Jan 12, 2017, 3:59:13 AM1/12/17
to scmrt...@googlegroups.com
01/12/2017 03:31 PM, 'Anton Gusev' via scmrtos-ru пишет:
> Да, логический косяк. Может, для пущей ясности ввести специальную
> функцию, типа
>
> INLINE void TKernel::switch_context_to(uint_fast8_t newPriority) {
> SchedProcPriority = newPriority; raise_context_switch(); }
>
> И заменить вызовы raise_context_switch() на вызовы этой функции?
>
> Там, конечно, всего два места, но так будет яснее.
>
Я против. Тут правка Сергея всё решает. И по ясности тоже: две строки
кода ничего не запутывают, а дополнительная сущность в виде функции
только загромождает код. Будь много таких мест, другое дело, но их
всего, как ты сказал, два и больше не предвидится (а если вдруг они
появятся, то вернёмся к рассмотрению этого варианта).

Название функции тоже, имхо, неудачно, не отражает действия - реально
переключения в этом месте не происходит.
__
HZ



oesd.ru


Harry Zhurov

unread,
Jan 12, 2017, 4:05:37 AM1/12/17
to scmrt...@googlegroups.com
01/12/2017 03:31 PM, 'Anton Gusev' via scmrtos-ru пишет:
Кстати, как мне сейчас видится, такая функция не решает проблему - она
даёт тот же код, что был до правки.

__
HZ





oesd.ru


Anton Gusev

unread,
Jan 12, 2017, 4:09:24 AM1/12/17
to scmrt...@googlegroups.com
Harry Zhurov пишет 12.01.2017 14:04:

> Кстати, как мне сейчас видится, такая функция не решает проблему - она
> даёт тот же код, что был до правки.

Да, ты прав. Тогда отбой. Принимаем правку Сергея. Кто займётся?



Sergey A. Borshch

unread,
Jan 12, 2017, 4:32:10 AM1/12/17
to scmrt...@googlegroups.com
On 12.01.2017 10:26, Harry Zhurov wrote:
> 01/12/2017 03:12 PM, Sergey A. Borshch пишет:
>> Решение проверено, проблему решает. Есть какие-нибудь возражения?
>>
> Если всё работает, то внести правку в ветку develop. Сам сделаешь или мне?
Думаю, у тебя получится быстрее. Правь.

Harry Zhurov

unread,
Jan 12, 2017, 6:11:41 AM1/12/17
to scmrt...@googlegroups.com
01/12/2017 04:32 PM, Sergey A. Borshch пишет:
> Думаю, у тебя получится быстрее. Правь.

Закинул в develop

--
HZ


oesd.ru


Alexey Babec

unread,
Jan 12, 2017, 11:02:38 AM1/12/17
to scmrtos-ru
Добрый день!

У меня вопрос: "Если во время действия критической секции сработало прерывание периферии, то в
этот момент вызывается его обработчик"

Это противоречит реализации критической секции (по крайней мере в нашем варианте), где все прерывания запрещаются. У Вас как-то по-другому работает критическая секция?

четверг, 12 января 2017 г., 11:12:06 UTC+3 пользователь Sergey Borshch написал:

Sergey A. Borshch

unread,
Jan 12, 2017, 11:08:16 AM1/12/17
to scmrt...@googlegroups.com
On 12.01.2017 16:19, Alexey Babec wrote:
> Добрый день!
>
> У меня вопрос: "Если во время действия критической секции сработало прерывание
> периферии, то в
> этот момент вызывается его обработчик"
>
> Это противоречит реализации критической секции (по крайней мере в нашем
> варианте), где все прерывания запрещаются. У Вас как-то по-другому работает
> критическая секция?

Нет, она у всех работает одинаково. И смысл ее несколько в другом: внутри
критической секции у процесса не могут насильно отобрать управление если только
он сам его не отдаст путем засыпания в каком-нибудь из сервисов ОС.

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

Anton Gusev

unread,
Jan 12, 2017, 11:11:52 AM1/12/17
to scmrt...@googlegroups.com
Alexey Babec пишет 12.01.2017 19:19:
> Добрый день!
>
> У меня вопрос: "Если во время действия критической секции сработало
> прерывание периферии, то в
> этот момент вызывается его обработчик"
>
> Это противоречит реализации критической секции (по крайней мере в нашем
> варианте), где все прерывания запрещаются. У Вас как-то по-другому
> работает критическая секция?

Имеется в виду, что запрос на прерывание возник во время действия
критической секции. А обработчик конечно вызывается после выхода из
критической секции.


Reply all
Reply to author
Forward
0 new messages