История изменений
Исправление KivApple, (текущая версия) :
Касательно планировщика набросал вот такой код:
Thread *threadQueue[TASK_SCHEDULER_MAX_PRIORITY];
int threadMaxRunningPriority = 0;
inline Thread *schedulerFindNextTask(void) {
for (; threadMaxRunningPriority >= 0; threadMaxRunningPriority--) {
if (threadQueue[threadMaxRunningPriority] != NULL) {
Thread *nextThread = threadQueue[threadMaxRunningPriority];
threadQueue[threadMaxRunningPriority] = nextThread->platformData.nextScheduled;
return nextThread;
}
}
return NULL;
}
void schedulerResumeTask(Thread *thread) {
if (threadQueue[thread->priority] == NULL) {
thread->platformData.nextScheduled = thread;
thread->platformData.prevScheduled = thread;
threadQueue[thread->priority] = thread;
} else {
thread->platformData.nextScheduled = threadQueue[thread->priority];
thread->platformData.prevScheduled = thread->platformData.nextScheduled->platformData.prevScheduled;
thread->platformData.nextScheduled->platformData.prevScheduled = thread;
thread->platformData.prevScheduled->platformData.nextScheduled = thread;
}
if (thread->priority > threadMaxRunningPriority) {
threadMaxRunningPriority = thread->priority;
}
}
void schedulerSuspendTask(Thread *thread) {
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = thread->platformData.nextScheduled;
}
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = NULL;
} else {
thread->platformData.nextScheduled->platformData.prevScheduled = thread->platformData.prevScheduled;
thread->platformData.prevScheduled->platformData.nextScheduled = thread->platformData.nextScheduled;
}
}
По идее должна быть производительность получше (O(1) пока у нас не уснут все задачи с максимальным в текущий момент приоритетом, затем O(N) для понижения максимального активного приоритета, причём N зависит от того насколько нужно спуститься приоритетов, а не от количества задач, затем опять О(1)).
Соответственно, когда поток начинает чего-то ждать вызываем schedulerSuspendTask для него (если это текущий поток, то ещё и сразу надо вызвать преждевременное переключение задач). Если событие, которое ждал поток случилось, то вызываем schedulerResumeTask. Ну а планировщик вызывает schedulerFindTask, чтобы определить, кому теперь надо отдавать управление. NULL возвращаться не должен никогда (в системе должен быть хотя бы один неспящий поток в любой момент времени, в крайнем случае это будет idle-поток с минимальным приоритетом). Если он вернулся устраиваем Kernel Panic.
Однако в этом коде не хватает синхронизации. В том плане, что если случится переключение задач (или же прерывание, которое вызывает пробуждение процесса, усыплять потоки прерывания не могут) в середине функции засыпания или пробуждения, то может случиться непредсказуемое. Я пока туплю, как её правильно добавить. Не поможете?
sudo cast beastie
Исходная версия KivApple, :
Касательно планировщика набросал вот такой код:
Thread *threadQueue[TASK_SCHEDULER_MAX_PRIORITY];
int threadMaxRunningPriority = 0;
inline Thread *schedulerFindNextTask(void) {
for (; threadMaxRunningPriority >= 0; threadMaxRunningPriority--) {
if (threadQueue[threadMaxRunningPriority] != NULL) {
Thread *nextThread = threadQueue[threadMaxRunningPriority];
threadQueue[threadMaxRunningPriority] = nextThread->platformData.nextScheduled;
return nextThread;
}
}
return NULL;
}
void schedulerResumeTask(Thread *thread) {
if (threadQueue[thread->priority] == NULL) {
thread->platformData.nextScheduled = thread;
thread->platformData.prevScheduled = thread;
threadQueue[thread->priority] = thread;
} else {
thread->platformData.nextScheduled = threadQueue[thread->priority];
thread->platformData.prevScheduled = thread->platformData.nextScheduled->platformData.prevScheduled;
thread->platformData.nextScheduled->platformData.prevScheduled = thread;
thread->platformData.prevScheduled->platformData.nextScheduled = thread;
}
if (thread->priority > threadMaxRunningPriority) {
threadMaxRunningPriority = thread->priority;
}
}
void schedulerSuspendTask(Thread *thread) {
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = thread->platformData.nextScheduled;
}
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = NULL;
} else {
thread->platformData.nextScheduled->platformData.prevScheduled = thread->platformData.prevScheduled;
thread->platformData.prevScheduled->platformData.nextScheduled = thread->platformData.nextScheduled;
}
}
По идее должна быть производительность получше (O(1) пока у нас не уснут все задачи с максимальным в текущий момент приоритетом, затем O(N) для понижения максимального активного приоритета, причём N зависит от того насколько нужно спуститься приоритетов, а не от количества задач, затем опять О(1)).
Соответственно, когда поток начинает чего-то ждать вызываем schedulerSuspendTask для него (если это текущий поток, то ещё и сразу надо вызвать преждевременное переключение задач). Если событие, которое ждал поток случилось, то вызываем schedulerResumeTask. Ну а планировщик вызывает schedulerFindTask, чтобы определить, кому теперь надо отдавать управление. NULL возвращаться не должен никогда (в системе должен быть хотя бы один неспящий поток в любой момент времени, в крайнем случае это будет idle-поток с минимальным приоритетом). Если он вернулся устраиваем Kernel Panic.
Однако в этом коде не хватает синхронизации. В том плане, что если случится переключение задач (или же прерывание, которое вызывает пробуждение процесса) в середине функции засыпания или пробуждения, то может случиться непредсказуемое. Я пока туплю, как её правильно добавить. Не поможете?
sudo cast beastie