Да, все "нормальные" ISA, включая 8080 и x86, гарантируют, что инструкции являются атомарными по отношению к прерываниям на одном ядре. Либо инструкция полностью выполнена, и все ее архитектурные эффекты видны (в прерывании обработчик), или ни один из них не является. Любые отклонения от этого правила, как правило, тщательно документируются.
Например, Руководство Intel по архитектуре x86, том 3 (~ 1000 страниц в формате PDF) имеет смысл особо сказать следующее:
6.6 ПЕРЕЗАГРУЗКА ПРОГРАММЫ ИЛИ ЗАДАЧИ
Чтобы разрешить перезапуск программы или задачи после обработки исключения или прерывания, все исключения
(кроме прерываний) гарантированно сообщать об исключениях на границе инструкции. Все прерывания гарантированно будут
взят на границе инструкции.
В старом абзаце руководства Intel по vol.1 говорится об одноядерных системах, использующих cmpxchg
без a lock
префикса для атомарного чтения-изменения-записи (в отношении к другому программному обеспечению, а не к аппаратному доступу DMA).
Инструкция CMPXCHG обычно используется для тестирования и модификации семафоров. Он проверяет, является ли семафор
это бесплатно. Если семафор свободен, он помечается как выделенный; в противном случае он получает идентификатор текущего владельца. Это все сделано
за одну непрерывную операцию . [потому что это одна инструкция] В однопроцессорной системе инструкция CMPXCHG устраняет необходимость
переключитесь на уровень защиты 0 (чтобы отключить прерывания) перед выполнением нескольких инструкций для проверки и изменения семафора.
Для многопроцессорных систем CMPXCHG можно комбинировать с префиксом LOCK для выполнения сравнения и
обменная операция атомарно. (См. «Заблокированные атомарные операции» в главе 8 «Управление несколькими процессорами»).
Руководства разработчика программного обеспечения Intel® 64 и IA-32, том 3A, для получения дополнительной информации об атомных
операции.)
(Подробнее о префиксе lock
и о его реализации по сравнению с неблокированным add [mem], 1
см. Может ли num ++ быть атомарным для 'int num'? )
Как указывает Intel в этом первом абзаце, один из способов достижения атомарности в нескольких командах - отключить прерывания, а затем снова включить, когда вы закончите. Это лучше, чем использование мьютекса для защиты большее целое число, особенно если вы говорите о данных, которыми обмениваются основная программа и обработчик прерываний. Если прерывание происходит, когда основная программа удерживает блокировку, она не может ждать , пока блокировка не будет снята; этого никогда не произойдет.
Отключение прерываний обычно довольно дешево для простых конвейеров, особенно микроконтроллеров. (Иногда вам нужно сохранить предыдущее состояние прерывания вместо того, чтобы безоговорочно разрешать прерывания. Например, функция, которая может быть вызвана с уже отключенными прерываниями.)
В любом случае, отключение прерываний - это то, как вы можете атомарно что-то делать с 64-разрядным целым числом на 8080.
Несколько длительных инструкций являются прерываемыми в соответствии с правилами, задокументированными для этой инструкции.
например. rep
-строковые инструкции x86, такие как rep movsb
(memcpy одной инструкции произвольного размера), архитектурно эквивалентны повторению базовой инструкции (movsb
) RCX раз, уменьшению RCX каждый раз и увеличению или уменьшению входов указателя (RSI) и RDI). Прерывание, прибывающее во время копирования, может установить RCX «начальное_значение - byte_copied , so on resuming after the interrupt the
rep movsb` будет запущен снова и сделает оставшуюся часть копии.
К другим примерам x86 относятся сборочные нагрузки SIMD (AVX2 / AVX512) и хранилища разброса (AVX512). например vpgatherdd ymm0, [rdi + ymm1*4], ymm2
выполняет до 8 32-битных нагрузок, в соответствии с которыми установлены элементы ymm2
. И результаты объединены в ymm0.
В гоВ обычном случае (без прерываний, сбоев страниц или других синхронных исключений во время сбора) вы получаете данные в регистре назначения, и регистр маски обнуляется. Таким образом, регистр маски дает центральному процессору место для сохранения прогресса.
Сбор и разбрасывание выполняются медленно, и может потребоваться запуск нескольких сбоев страниц, поэтому для синхронных исключений это гарантирует продвижение вперед даже при патологических условиях, когда обработка сбоя страницы не отображает все остальные страницы. Но, что более важно, это означает, что нужно избегать повторных пропусков TLB, если страница среднего элемента дает сбой, и не отбрасывать работу, если приходит асинхронное прерывание.
Некоторые другие длительные инструкции (например, wbinvd
, которые сбрасывают все кэши данных на всех ядрах) не являются архитектурно прерываемыми или даже микро архитектурно не могут быть отменены (чтобы отказаться от частичной работы и иди обрабатывать прерывание). Он привилегирован, поэтому пользовательское пространство не может выполнить его как атаку типа «отказ в обслуживании», вызывающую высокую задержку прерывания.
связанный пример документирования забавного поведения - это когда x86 popad
выходит за пределы стека (предел сегмента). Это исключение (не внешнее прерывание), задокументированное ранее в руководстве по vol.3, в разделе 6.5 КЛАССИФИКАЦИИ ИСКЛЮЧЕНИЙ (то есть неисправность / прерывание / прерывание, см. PDF-файл для более подробной информации.)
Примечание
Одно подмножество исключений, обычно сообщаемое как ошибка, не перезапускается Такие исключения приводят к потере
некоторого состояния процессора. Например, выполняет команду POPAD , где находится кадр стека
пересечение конца сегмента стека вызывает сообщение об ошибке. В этой ситуации
Обработчик исключений видит, что указатель команд (CS: EIP) был восстановлен, как если бы POPAD
Инструкция не была выполнена. Однако состояние внутреннего процессора (общего назначения
регистры) будут изменены. Такие случаи считаются ошибками программирования. Приложение
вызывающий этот класс исключений должен быть прерван операционной системой.
Обратите внимание, что это только в том случае, если popad
само по себе вызывает исключение, не по любой другой причине. Внешнее прерывание не может разделить popad
так, как это возможно для rep movsb
или vpgatherdd
(Я полагаю, что в случае сбоя popad
он эффективно работает итеративно, извлекая 1 регистр за раз и логически модифицируя RSP / ESP / SP, а также целевой регистр. Вместо проверки всего региона он собирается загрузка предела сегмента перед запуском, потому что это потребует дополнительного добавления, я думаю.)
Процессоры, вышедшие из строя, возвращаются к прерыванию из-за прерываний.
Процессоры, такие как современный x86 с нестандартным выполнением и разделением сложных команд на несколько мопов, по-прежнему гарантируют, что это так. Когда приходит прерывание, ЦПУ должен выбрать точку между двумя инструкциями, которые он находится в середине выполнения, как место, где архитектурно происходит прерывание. Он должен отказаться от любой работы, которая уже проделана для декодирования или начала выполнения любых последующих инструкций. Если предположить, что прерывания возвращаются, они будут переизбраны и снова начнут выполняться.
См. Когда происходит прерывание, что происходит с инструкциями в конвейере? .
Как говорит Энди Глеу, современные процессоры не переименовывают уровень привилегий, поэтому то, что логически должно произойти (отбрасывая более поздние инструкции из конвейера), соответствует тому, что на самом деле происходит. Интересный факт: прерывания x86 не полностью сериализуются. Это означает, что у них нет для очистки буфера хранилища, а также для опустошения буфера ReOrder выполнения вне очереди. Они возвращают серверную часть OoO обратно в состояние вывода из эксплуатации (поскольку он не переименовывает уровень привилегий, поэтому он не может безопасно обрабатывать одновременное выполнение пользовательских и ядерных операций в полете), но обработчик прерываний может потенциально начать выполняться до того, как Буфер хранилища передал все ожидающие хранилища на L1d.
(Хранить данные из вышедших из употребления инструкций хранилища не спекулятивно; это определенно произойдет, и ЦП уже сбросил состояние, к которому необходимо иметь возможность откатиться до этой инструкции хранилища. Таким образом, большой буфер хранилища полон разбросанных Запасы кэша могут привести к задержке прерывания.)