[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4219649#p4219649"]В стандартные библиотечные функции встраивался код, определяющий прошло ли достаточно времени, и если да - переключающий контекст..[/uquote]
Ну хорошо, и как вы представляете себе это, как должен этот встраиваемый код определять, достаточно ли времени прошло, с какой периодичностью он должен проверять это, на что опираться, на чем основываться, а что он должен делать, если прошло недостаточно времени, а как быть с переносимостью кода, а что делать с уже скомпилированными и закрытыми библиотеками? Вот подумайте и ответьте на эти вопросы. Только конкретно.
И это... Кажись, вы путаете теплое с соленым, кооперативную многозадачность с гибридной.
Как выглядит рядовой пример без ОС:
Код: Выделить всё
while(1)
{
if(f0_ready)
{
f0_ready = 0;
Funct0();
}
if(f1_ready)
{
f1_ready = 0;
Funct1();
}
if(f2_ready)
{
f2_ready = 0;
Funct2();
}
}
в цикле по флагам готовности ф-ции выполняются без ограничения их длительности. Если хотите принудительно ограничить максимальную длительность каждой ф-ции, вы вовсе не должны встраивать внутрь этой функций никакого кода! Наоборот, вы должны запустить системный таймер, который бы по истечении выделенного интервала вызывал прерывание, а в прерывании происходила бы принудительная передача исполнения на следующую ожидающую исполнения ф-цию. То есть, механизм переключения работает извне, а не изнутри функции, особенно библиотечной, в которую вообще нежелательно влезать руками.
При этом, во избежание потерь результатов текущей работы ф-ции, у каждой ф-ции должен быть собственный стек, в котором бы и хранились эти результаты и точка возврата, с которой нужно возобновить выполнение прерванной ф-ции.
Вот. А то, что вы там нафантазировали про "достаточно ли времени", то вы путаете гибридную многозадачность ОС с кооперативной. В операционной системе поверх всего работает ядро ОС, которое заведует распределением процессорного времени, будь то передача исполнения по команде из задачи или принудительное вытеснение задачи по времени и приоритетам.
Сам по себе вызов функции обозначает, что часть регистров не будет сохранена.
С чего бы это вдруг? Во-первых, никто не запрещает дописать сохранение нужных регистров (да оно так и делается, только для сишного текста незаметно). А во-вторых, дело не только в сохранении регистров. В ОС для каждой задачи выделяется отдельный стек, в котором она хранит все свои результаты работы. При переключении задач происходит переключение указателя стека на стек другой задачи. Этим занимается ядро ОС, оно для того и писано.
Вам не мешает подробнее ознакомиться с внутрянкой ОС и её внутренней работой.
Создайте проект с FreeRTOS, в конфиге в строчке configUSE_PREEMPTION поставьте 0 и посмотрите, как именно реализованы механизмы ОС. Есть просто некоторые правила написания тела задачи для ОС и есть предоставляемый ОС инструментарий. Но ничего такого, что бы потребовало распиливания библиотечных функций и внедрения в них какого-то самовыдуманного кода, определяющего, истекло ли чего-то там или нет.
В частности, можно не сохранять половину регистров.
А две трети можно? А четыре пятых? А шесть вторых?
Посмотрите подробнее тему касательно работы стека вызовов, работы указателя стека, различия между Main Stack Pointer и Process Stack Pointer, места хранения локальных переменных, посмотрите генерируемый ассемблерный код при вызовах и возвратах ф-ций. А то у вас есть некоторое недопонимание того, где и как хранится содержимое регистров ядра.