LINUX.ORG.RU

История изменений

Исправление 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