Completion-блокировки
В Linux имеется еще один примитив синхронизации, аналогичный семафорам. Это completion-блокировки. Они были введены для разрешения нетривиальной конфликтной ситуации, возникающей в многопроцессорных системах, когда процесс А выделяет временную семафорную переменную, инициализирует ее как закрытый MUTEX-семафор, передает ее адрес процессу В, а затем вызывает для нее функцию down . Процесс А планирует уничтожить семафор, как только будет разбужен. Затем процесс В, работающий на другом процессоре, вызывает функцию up для семафора. Однако при теперешней реализации функций up о и down о они могут быть параллельно выполнены на одном семафоре. Получается, что процесс А может быть разбужен и уничтожит временный семафор, пока процесс В выполняет функцию up . В результате функция up попытается обратиться к несуществующей структуре.
Конечно, можно было изменить реализацию функций down о иир, запретив их параллельное выполнение на одном семафоре. Однако пришлось бы добавлять в код дополнительные инструкции, а этого следует избегать, когда функции используются настолько интенсивно.
Completion-блокировка — это примитив синхронизации, разработанный специально для решения этой проблемы. Структура completion включает в себя голову очереди и флаг:
struct completion {unsigned int done; wait_queue_head_t wait;
};Функция, соответствующая семафорной функции up , называется complete . Она принимает в качестве параметра адрес структуры completion, вызывает функцию spin iock irqsave о для спин-блокировки очереди ожидания completion-блокировки, увеличивает поле done, будит эксклюзивный процесс, спящий в очереди wait, и, наконец, вызывает функцию spin_unlock_irqrestore.
Функция, соответствующая функции down , называется wait_for_completion . Она принимает в качестве параметра адрес структуры completion и проверяет значение флага done. Если оно больше нуля, функция wait_for_compietion заканчивает работу, потому что функция complete уже была выполнена на другом процессоре. В противном случае функция wait_for_completion ставит процесс current в конец очереди в качестве эксклюзивного процесса и переводит его в спящее” состояние task uninterruptible. Пробудившись, функция удаляет процесс current из очереди. Затем она проверяет значение флага done. Если оно равно нулю, функция заканчивает работу; в противном случае процесс снова приостанавливается. Как и функция complete о, функция wait_for_compietion пользуется спин-блокировкой очереди ожидания completion-блокировки.
Основная разница между completion-блокировками и семафорами состоит в том, как используется спин-блокировка, входящая в состав очереди ожидания. В completion-блокировках спин-блокировка служит для гарантии того, ЧТО функции complete И wait for completion (не будут ВЫПОЛНЯТЬСЯ па- раллельно. В семафорах спин-блокировка применяется, чтобы не позволить параллельно выполняющимся функциям down внести путаницу в структуру semaphore.
Предыдущая страница | 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | Следующая страница