QUOTE (Timmy @ Feb 24 2017, 15:54)
Всем привет!
Обратил внимание на следующую вещь:
CODE
stack_item_t* OS::TKernel::context_switch_hook(stack_item_t* sp)
{
CONTEXT_SWITCH_HOOK_CRIT_SECT();
ProcessTable[CurProcPriority]->StackPointer = sp;
sp = ProcessTable[SchedProcPriority]->StackPointer;
#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
context_switch_user_hook();
#endif
CurProcPriority = SchedProcPriority;
return sp;
}
SchedProcPriority - volatile, читается дважды без создания локальной копии, что приводит к необходимости обязательно запрещать прерывания перед вызовом context_switch_hook() или в CONTEXT_SWITCH_HOOK_CRIT_SECT(). Иначе в случае прерывания с перепланировкой между двумя чтениями SchedProcPriority может призойти переключение на один просесс, а в CurProcPriority запишется другой процесс и всё развалится
. А вот если сделать локальную копию SchedProcPriority, то, например, для Cortex-M прерывания при переключении контекста можно и не запрещать.
Переключение контекста при разрешённых прерываниях не кажется хорошей идеей. Это открывает дорогу всяким неочевидным неприятностям, самое простая из которых - повышение требований размеру стека, куда сохраняются регистры.
Двойное чтение - да, тут есть элемент неэффективности, цена - одна команда загрузки "память-регистр".
QUOTE (Timmy @ Feb 24 2017, 15:54)
И ещё кусочек:
CODE
if(p->Timeout > 0)
{
if(--p->Timeout == 0)
{
set_process_ready(p->Priority);
}
}
Неиспользование локальной копии p->Timeout приводит к её двойному чтению, в данном случае без тяжёлых последствий, просто неоптимально по длине кода.
Да, тут приходится согласиться - та же дополнительная загрузка.
«Отыщи всему начало, и ты многое поймёшь» К. Прутков