Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
KivApple
0 / 0 / 0
Регистрация: 04.01.2016
Сообщений: 2
1

Оцените безопасность кода

04.01.2016, 20:31. Просмотров 202. Ответов 0
Метки нет (Все метки)

Имеется следующий код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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->platformData.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->platformData.nextScheduled)) {
                schedulerResumeTask(thread);
            }
        }
        mutexUnlock(&threadResumeQueueMutex);
    }
}
 
void schedulerResumeTask(Thread *thread) {
    if (mutexTryLock(&threadQueueMutex)) {
        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;
        }
        mutexUnlock(&threadQueueMutex);
        schedulerResumeDelayedTasks();
    } else {
        do {
            thread->platformData.nextScheduled = threadResumeQueue;
        } while (!__sync_bool_compare_and_swap(&threadResumeQueue, thread->platformData.nextScheduled, thread));
    }
}
 
void schedulerSuspendTask(Thread *thread) {
    mutexLock(&threadQueueMutex);
    if (threadQueue[thread->priority] == thread) {
        threadQueue[thread->priority] = thread->platformData.nextScheduled;
        if (threadQueue[thread->priority] == thread) {
            threadQueue[thread->priority] = NULL;
        }
        return;
    }
    thread->platformData.nextScheduled->platformData.prevScheduled = thread->platformData.prevScheduled;
    thread->platformData.prevScheduled->platformData.nextScheduled = thread->platformData.nextScheduled;
    mutexUnlock(&threadQueueMutex);
    schedulerResumeDelayedTasks();
}
Поля структуры Thread.platformData.nextScheduled и Thread.platformData.prevScheduled описаны как Thread * volatile. Никто кроме вышеприведённого кода к этим полям, а также вышеописанным глобальным переменным не обращается.
Имеются следующие условия:
1) schedulerFindNextTask может прервать исполнение любой другой функции кроме самой себя. Ему не допустимо блокироваться (ибо он может запуститься в середине другой функции, которая уже захватила mutex и никогда не дождаться его освобождения), но допустимо иногда выдавать NULL вместо ответа.
2) schedulerResumeTask может прерывать исполнение любой функции, в том числе самой себя. Ему недопустимо блокироваться (по той же причине, что и в случае 1 - мы можем не дождаться освобождения mutex), а его действие должно рано или поздно выполнится.
3) schedulerResumeTask не может никого прерывать. Может блокироваться, если это нужно.
"Может прерывать" значит, что в середине исполнения функции процессор ставит её на паузу и выполняет некий код, который может дёрнуть schedulerFindNextTask или schedulerResumeTask (причём в последнем случае возможно ещё одно вложенное прерывание исполнения), а затем вернуться. В таких ситуациях нельзя ожидать освобождения mutex, потому что пока функция не завершиться, прерванный код, захвативший mutex, не заработает. Это не отменяет обычной многозадачности, когда несколько процессов могут одновременно вызвать schedulerResumeTask или schedulerSuspendTask, но тут блокировки решают проблему.

Можно ли быть уверенным, что если библиотечные функции (работа с mutex и __sync_bool_compare_and_swap - атомарное сравнение и обмен) работают верно, а в качестве аргументов подаются корректные данные, то вышеприведённый код является безопасным (то есть невозможно разрушение структуры данных или зависание)?

Добавлено через 3 часа 50 минут
Переписал всё в lock-free стиле, теперь программа иногда зависает в строке помеченной звёздочками. Остальное вроде работает адекватно.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Thread * volatile threadQueue[TASK_SCHEDULER_MAX_PRIORITY + 1];
volatile int threadMaxRunningPriority = 0;
 
inline Thread *schedulerFindNextTask(void) {
    Thread *nextThread = NULL;
    do {
        int maxRunningPriority = threadMaxRunningPriority;
        while (maxRunningPriority >= 0) {
            nextThread = threadQueue[maxRunningPriority];
            if (nextThread != NULL) {
                break;
            }
            int newMaxPriority = maxRunningPriority - 1;
            __sync_bool_compare_and_swap(&threadMaxRunningPriority, maxRunningPriority, newMaxPriority);
            maxRunningPriority = threadMaxRunningPriority;
        }
    } while (nextThread && (!__sync_bool_compare_and_swap(&threadQueue[nextThread->priority], nextThread, nextThread->platformData.nextScheduled)));
    return nextThread;
}
 
void schedulerResumeTask(Thread *thread) {
    if (!__sync_bool_compare_and_swap(&(thread->platformData.running), false, true)) return;
    while (true) {
        if (threadQueue[thread->priority] == NULL) {
            thread->platformData.nextScheduled = thread;
            if (__sync_bool_compare_and_swap(&threadQueue[thread->priority], NULL, thread)) {
                break;
            }
        } else {
            thread->platformData.nextScheduled = threadQueue[thread->priority]->platformData.nextScheduled;
            if (__sync_bool_compare_and_swap(&(threadQueue[thread->priority]->platformData.nextScheduled),
                    thread->platformData.nextScheduled, thread)) {
                break;
            }
        }
    }
    int maxPriority, newMaxPriority;
    do {
        maxPriority = threadMaxRunningPriority;
        newMaxPriority = (thread->priority > maxPriority) ? thread->priority : maxPriority;
    } while (!__sync_bool_compare_and_swap(&threadMaxRunningPriority, maxPriority, newMaxPriority));
}
 
void schedulerSuspendTask(Thread *thread) {
    if (!__sync_bool_compare_and_swap(&(thread->platformData.running), true, false)) return;
    while (true) {
        Thread *prev = threadQueue[thread->priority];
        if (prev == NULL) break;
        while (prev->platformData.nextScheduled != thread) { // *************
            prev = prev->platformData.nextScheduled;
        }
        if (__sync_bool_compare_and_swap(&(prev->platformData.nextScheduled), thread, thread->platformData.nextScheduled)) {
            if (__sync_bool_compare_and_swap(&(threadQueue[thread->priority]), thread, thread->platformData.nextScheduled)) {
                __sync_bool_compare_and_swap(&(threadQueue[thread->priority]), thread, NULL);
            }
            break;
        }
    }
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.01.2016, 20:31
Ответы с готовыми решениями:

Безопасность кода
Только начал изучать php, вот пишу калькулятор)) Подскажите, пожалуйста правильно ли я делаю?...

Безопасность кода.
Могут ли данные такие как пароль указанные в коде попасть в чужие руки? $html =...

Безопасность кода
Дела вот в чём. В коде у меня содержится стринговое поле, в котором байтовое представление dll...

Безопасность исходного кода
Доброе время суток. Думаю, что подобные темы в разделе поднимаются не редко, однако информация...

безопасность php-кода
Добрый день! Интересует такой вопрос: вот я размещаю свой php-код. Как мне его обезопасить от...

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.01.2016, 20:31

Безопасность управляемого кода .NET
Прочитал для меня шокирующие заявление в статье журнала argc & argv '...При этом, вам нужно...

Оцените качество кода
Недавно начал усиленно изучать C++ и Qt и решил написать один более-менее практический пример, а...

Оцените программу ( написание кода )
Всем привет пишу уже 2 раз насчет оценки кода. Недавно выкладывал тут калькулятор, теперь вот...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru