Есть вот такой код:
Thread * volatile threadQueue[TASK_SCHEDULER_MAX_PRIORITY + 1];
int threadMaxRunningPriority = 0;
Mutex threadQueueMutex;
Thread * volatile threadResumeQueue;
Mutex threadResumeQueueMutex;
void schedulerInit(void) {
mutexInit(&threadQueueMutex);
mutexInit(&threadResumeQueueMutex);
}
inline Thread *schedulerFindNextTask(void) {
Thread *nextThread = NULL;
if (mutexTryLock(&threadQueueMutex)) {
for (; threadMaxRunningPriority >= 0; threadMaxRunningPriority--) {
if (threadQueue[threadMaxRunningPriority] != NULL) {
nextThread = threadQueue[threadMaxRunningPriority];
threadQueue[threadMaxRunningPriority] = nextThread->nextScheduled;
break;
}
}
mutexUnlock(&threadQueueMutex);
}
return nextThread;
}
void schedulerResumeTask(Thread *thread);
void schedulerResumeDelayedTasks(void) {
if (mutexTryLock(&threadResumeQueueMutex)) {
while (threadResumeQueue != NULL) {
Thread *thread = threadResumeQueue;
if (__sync_bool_compare_and_swap(&threadResumeQueue, thread, thread->nextScheduled)) {
schedulerResumeTask(thread);
}
}
mutexUnlock(&threadResumeQueueMutex);
}
}
void schedulerResumeTask(Thread *thread) {
if (mutexTryLock(&threadQueueMutex)) {
if (threadQueue[thread->priority] == NULL) {
thread->nextScheduled = thread;
thread->prevScheduled = thread;
threadQueue[thread->priority] = thread;
} else {
thread->nextScheduled = threadQueue[thread->priority];
thread->prevScheduled = thread->nextScheduled->prevScheduled;
thread->nextScheduled->prevScheduled = thread;
thread->prevScheduled->nextScheduled = thread;
}
if (thread->priority > threadMaxRunningPriority) {
threadMaxRunningPriority = thread->priority;
}
mutexUnlock(&threadQueueMutex);
schedulerResumeDelayedTasks();
} else {
do {
thread->nextScheduled = threadResumeQueue;
} while (!__sync_bool_compare_and_swap(&threadResumeQueue, thread->nextScheduled, thread));
}
}
void schedulerSuspendTask(Thread *thread) {
mutexLock(&threadQueueMutex);
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = thread->nextScheduled;
if (threadQueue[thread->priority] == thread) {
threadQueue[thread->priority] = NULL;
}
return;
}
thread->nextScheduled->prevScheduled = thread->prevScheduled;
thread->prevScheduled->nextScheduled = thread->nextScheduled;
mutexUnlock(&threadQueueMutex);
schedulerResumeDelayedTasks();
}
Поля структуры Thread nextScheduled и prevScheduled описаны как Thread * volatile.
Условия такие:
1) schedulerFindNextTask может прервать любую функцию, кроме самой себя. Ей допустимо иногда возвращать NULL вместо того, чтобы выполнить свою работу.
2) schedulerResumeTask может прервать любую функцию, в том числе саму себя. Она не имеет права блокироваться.
3) schedulerSuspendTask не может прервать никакую функцию, но два потока могут вызвать эту функцию одновременно. Допустима блокировка выполнения.
Больше никакой код к полям nextScheduled и prevScheduled, а также вышеописанным глобальным переменным не обращается.
1) Достаточно ли проверок и условий в этих функциях, чтобы гарантировать, что структура данных (связанный список) не будет никогда повреждена и не возникнет зависания (schedulerFindNextTask и schedulerResumeTask не имеют права блокироваться ни при каких обстоятельствах).
2) Можно ли доверять встроенной функции GCC __sync_bool_compare_and_swap на платформе ARM Cortex-M3?
3) Возможно ли переписать данный код более оптимально, сохранив безопасность?