Я думаю о "Сведение к минимуму ошибок страниц (и ошибок TLB) при «перемещении» по большому графику"
«Как узнать, находится ли указатель в физической памяти или он вызовет ошибку страницы?» - это связанный вопрос, рассматривающий проблему с другой стороны, но не имеющий решения.
Я хочу иметь возможность загружать некоторые данные из памяти в регистр, но иметь прерывание загрузки, а не получение ошибки страницы, если память в настоящее время выгружена. Мне нужен код для работы в пользовательском пространстве как в Windows, так и в Linux без каких-либо стандартных разрешений.
(Идеально, я также хотел бы прервать работу при ошибке TLB.)
Часть RTM (Restricted Transactional Memory) функции TXT-NI позволяет подавлять исключения:
Any fault or trap in a transactional region that must be exposed to software will be suppressed. Transactional execution will abort and execution will transition to a non-transactional execution, as if the fault or trap had never occurred.
[...]
Synchronous exception events (#DE, #OF, #NP, #SS, #GP, #BR, #UD, #AC, #XM, #PF, #NM, #TS, #MF, #DB, #BP/INT3) that occur during transactional execution may cause an execution not to commit transactionally, and require a non-transactional execution. These events are suppressed as if they had never occurred.
Я никогда не использовал RTM, но он должен работать примерно так:
xbegin fallback
; Don't fault here
xend
; Somewhere else
fallback:
; Retry non-transactionally
Обратите внимание, что транзакция может быть прервана по многим причинам, см. Главу 16.8.3.2 тома 1 руководства Intel. Также обратите внимание, что RTM не является повсеместным.
Помимо RTM, я не могу придумать другого способа подавления нагрузки, поскольку он должен возвращать значение или, в конечном итоге, сигнализировать об условии прерывания (что было бы таким же, как #PF).
Я хочу, чтобы ОС не видела #PF, поэтому ошибка, с которой я мог справиться в пользовательском пространстве, также решит проблему.
Если бы RTM была более распространенной, это было бы отличным решением, так как это также сделало бы мою блокировку потоков пасхальной.
@IanRingrose RTM подавляет #PF, и это единственное, что я придумал. Я не могу придумать другого механизма для прерывания загрузки, архитектура x86 на самом деле не построена вокруг концепции «прерывания загрузки». Посмотрим, есть ли у кого-нибудь другие мысли :)
@IanRingrose У него все еще есть некоторые проблемы, например, не все ядра x86 поддерживают TSX. Возможно, с C++ 20 и поддержкой более высокого языка это будет более распространено. (en.cppreference.com/w/cpp/language/transactional_memory)
Хорошая идея! @IanRingrose: к сожалению, нет инструкции, которая просто запрашивает TLB или текущую таблицу страниц с результатом в регистре на x86. Возможно, у какой-то другой ISA есть инструкции для этого, но я не знаю ни одной из них. В качестве дизайнерской идеи это было бы полезно только для производительности, а не для правильности, потому что всегда будет разрыв между запросом и использованием. Команда try_load insn, которая также устанавливает / очищает флаги вместо того, чтобы поднимать #PF, могла бы избежать состояния гонки, но ни одна из известных мне ISA также не имеет этого.
@PeterCordes Одна проблема, чтобы быть полезной, она должна быть ОЧЕНЬ быстрой в случае, если страница находится в TLB (или в памяти).
TryLoad, который прерывается, если элемент не был в кэш-памяти ЦП (уровень 3), также был бы очень хорош ...
@IanRingrose: Быть быстрым - не проблема; Я не понимаю, почему гипотетическая инструкция queryTLB
будет медленнее, чем загрузка, которая попадает в кеш L1dTLB и L1d, если страница уже горячая. Он просто запустится на порту загрузки и выдаст целочисленный результат. Порты загрузки Intel уже знают, как запускать широковещательные нагрузки, нагрузки с нулевым расширением и даже vmovddup ymm, m256
(две линейные широковещательные передачи) по какой-то причине, поэтому добавление другого типа нагрузки не кажется проблемой. То же самое для загрузки, которая устанавливает флаги в зависимости от того, прервали ли мы загрузку вместо #PF.
Загрузка действительно прерывается за исключением. Затем ОС загрузит страницу и позволит вашей программе повторить загрузку. Так что это зависит от ОС. Может быть,
verr
(intel.com/content/dam/www/public/us/en/documents/manuals/…) проверяет, выйдет ли загрузка из строя или нет, но я не уверен в этом.