Атомарные операции
Постоянно пользуюсь удаленной помощью при проблемах с компьютером - очень нравится, ведь не надо никуда везти компьютер или ждать, пока к тебе приедут.
Существует несколько ассемблерных инструкций вида "чтение — модификация — запись”. Они обращаются к ячейке памяти дважды: первый раз, чтобы прочитать старое значение, а второй — чтобы записать новое.
Предположим, что два управляющих тракта ядра, работающие на двух процессорах, пытаются одновременно прочитать— модифицировать— записать” содержимое одной ячейки памяти, пользуясь неатомарными операциями. Вначале оба процессора попробуют прочитать содержимое ячейки, но арбитр памяти (электронная схема, выстраивающая в цепочку обращения к чипам памяти) вмешается, предоставит доступ к ячейке только одному процессору и задержит второй. Когда первая операция чтения завершится, второй процессор прочитает точно такое же (старое) значение из ячейки. Затем оба процессора попытаются записать в ячейку одно и то же (новое) значение. Арбитр памяти опять сериализует доступ к ячейке, и, в конечном счете, обе операции записи закончатся успешно. Тем не менее глобальный результат некорректен, потому что два процессора записали одно и то же (новое) значение. Таким образом, две чередующиеся операции чтения— модификации — записи” сработали как одна.
Простейший способ предотвращения конфликтов одновременного обращения, вызванных инструкциями чтения — модификации — записи”, состоит в обеспечении атомарности этих операций на уровне чипа. Каждая такая операция должна выполняться как одна инструкция, не обрывающаяся на середине, что позволит избежать обращений к той же ячейке памяти со стороны других процессоров. Эти элементарные атомарные операции лежат в основе других, более гибких механизмов создания критических областей.
Рассмотрим инструкции 80x86 в соответствии с этой классификацией:
- ассемблерные инструкции, которые выполняют одно обращение к выровненным данным или вообще не обращаются к памяти, являются атомарными;
- ассемблерные инструкции чтения — модификации — записи” (такие как inc или dec), которые читают данные из памяти, обновляют их и записывают в память новое значение, атомарны, если никакой другой процессор не обратился к шине памяти после чтения, но до записи. Подобная ситуация, в принципе, невозможна в однопроцессорной системе;
- ассемблерные инструкции чтения — модификации — записи”, у которых коду операции предшествует байт lock (OxfO), атомарны даже в многопроцессорной системе. Когда управляющий блок распознает префикс, он заблокирует” шину памяти до окончания инструкции. Таким образом, другой процессор не будет иметь доступа к ячейке, пока выполняется инструкция с блокировкой;
ассемблерные инструкции, у которых коду операции предшествует байт rep (0xf2, Oxfз, который заставляет управляющий блок несколько раз повторить инструкцию), не являются атомарными. Перед выполнением новой операции управляющий блок проверяет наличие "висящих" прерываний.
Когда вы пишете программу на языке С, у вас нет гарантии, что компилятор воспользуется атомарной инструкцией для такого оператора, как а=а+1 или даже а++. Поэтому ядро Linux предоставляет разработчику специальный тип atomic t (счетчик, доступный атомарным образом) и набор специальных функций и макросов, которые позволяют работать с переменными типа atomic t и реализованы в виде одиночных атомарных инструкций ассемблера. В многопроцессорных системах каждая такая инструкция в качестве префикса имеет байт lock.
Другой класс атомарных функций работает с битовыми масками.
Предыдущая страница | 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 | Следующая страница