Как многопоточность SMP разделяет память и прерывания? - PullRequest
9 голосов
/ 07 января 2009

Я работаю над входными буферами для моего ядра, и у меня возникли вопросы. На двухъядерных машинах я знаю, что одновременно может выполняться более одного «процесса». Чего я не знаю, так это как ОС и отдельные программы работают для защиты коллизий в данных.

В этой теме я хотел бы знать две вещи:

(1) Где происходят прерывания? Гарантируется ли, что они происходят на одном ядре, а не на другом, и может ли это использоваться для того, чтобы убедиться, что операции в реальном времени на одном ядре не были прерваны, скажем, файловым вводом-выводом, который можно обрабатывать на другом ядре? (Логично предположить, что прерывания будут происходить на 1-м ядре, но всегда ли это так, и как бы вы сказали? Или, возможно, каждое ядро ​​имеет свои собственные настройки для прерываний? Не приведет ли это к сценарию, в котором каждый ядро может одновременно реагировать на одно и то же прерывание, возможно, по-разному?)

(2) Как двухъядерный процессор справляется с коллизией памяти кода операции? Что произойдет, если одно ядро ​​считывает адрес в памяти в то же время, когда другое ядро ​​записывает этот же адрес в памяти? Выдается исключение или считывается значение? (Я бы предположил, что запись будет работать в любом случае.) Если значение читается, гарантируется ли оно как старое, так и новое значение во время столкновения?

Я понимаю, что в идеале программы должны быть написаны, чтобы избежать подобных сложностей, но ОС определенно не может этого ожидать, и должна быть в состоянии обрабатывать такие события, не задыхаясь сама по себе.

Ответы [ 3 ]

6 голосов
/ 22 мая 2009

В процессорах x86 это обрабатывается APIC. Вы можете увидеть подробности в Руководстве разработчика программного обеспечения Intel® 64 и IA-32 для архитектур , в частности в том 3 , главе 9, и в спецификации x2APIC .

Я просто дам краткое резюме, если вы не хотите вдаваться во все детали.

Прерывания могут поступать из трех разных источников:

  • Внешние контакты (в процессорах Intel вплоть до Core i7 у вас есть LINT0, LINT1, SMI, INIT. Я не знаю, как они называются в процессорах Core i7, AMD или Via).
  • Автобусные операции. Это основной способ, которым один поток отправляет прерывание другому потоку в современной системе. Они называются IPI - I nter- P rocessor I nterrupts.
  • Внутренние события, такие как тепловые прерывания, мониторы событий или внутренние ошибки.

Каждый логический процессор (поток в системе SMT, ядро ​​в многоядерной системе без SMT, процессор в многоядерной системе без SMT) имеет APIC. APIC контролирует, как логический процессор реагирует на любые такие прерывания.

Короче говоря:

Выводы SMI и INIT всегда направляются на SMI или INIT соответственно.

Если APIC отключен, LINT0 направляется в INTR, LINT1 направляется в NMI, а IPI игнорируются.

Если включено:

  • LINT0, LINT1, тепловые события, мониторы событий и ошибки имеют записи в LVT ( L ogical V ector T способны), которые указывают он замаскирован или нет, и если нет, то каким будет тип прерывания.
  • IPI обрабатываются. IPI включают тип прерывания (то есть INTR, SMI, NMI, INIT, SIPI) и назначение. Каждый логический процессор имеет APIC-ID, который является. Если пункт назначения IPI совпадает с его идентификатором, он обрабатывает прерывание. В противном случае он игнорирует это.

Если вы хотите получить подробную информацию о включении APIC, программировании LVT, настройке APIC-ID и отправке IPI, вам придется взглянуть на руководства, с которыми я связан.

1 голос
/ 12 января 2009

Операционная система устанавливает, где обрабатываются прерывания. Linux выполняет распределение нагрузки по прерываниям, чтобы они могли обрабатываться обоими процессорами. Каждый обработчик прерываний должен получить блокировку, чтобы избежать одновременного выполнения одного и того же обработчика на другом процессоре, а также для защиты от другого кода ядра, работающего в контексте без прерываний и обращающегося к тем же структурам данных. Тем не менее, я думаю, что можно связать выполнение данного прерывания на данном процессоре.

О вопросе (2): гарантии в основном те же, что и для машины SMP, то есть исключение не выдается, и результат зависит от того, кто получит выполнить / передать значение в память / передать значение в общий ресурс кеш первый. В любом случае, вы не можете полагаться на значение read - на самом деле, данные гарантии гораздо менее надежны, чем вы ожидаете.

Посмотрите в Интернете (в Google или Википедии), что такое гонка данных, и начните с изучения того, как правильно писать многопоточный код на Java. Изучение этого облегчило мне понимание механизмов параллелизма ядра Linux.

Или просто перейдите к C / C ++ почти "официальной" FAQ по модели памяти , для Documentation / memory-barriers.txt из дерева исходников ядра Linux или для поста Джереми Мэнсона на выпуск . В любом случае, я забыл указать, что прочитанное вами значение не обязательно было записано каким-либо процессором. Для 32-битных значений это гарантируется тем фактом, что 32-битная запись является атомарной. Для 64-битных значений это обычно не так (я не уверен насчет 64-битных платформ, но по причинам переносимости я обычно не полагаюсь на это).

В любом случае, если вы задаетесь этим вопросом, вам, вероятно, следует улучшить блокировку, используемую вашим кодом. Работая с ядром, вам сначала нужно написать собственную библиотеку spinlock / семафоров, чтобы это исправить.

Когда вы говорите «ваше ядро», неясно, что вы имеете в виду, но я думаю, что вряд ли вы на самом деле имеете в виду «ядро, которое я пишу». В любом случае, я не позволю никому задавать вопрос (2) запускать многопоточные программы на моей машине: -).

Я понимаю, что программы должны в идеале быть написано, чтобы избежать этих виды осложнений, но ОС конечно не могу этого ожидать, и будет нужно уметь обрабатывать такие события без удушья.

Ответ на этот вопрос - это то, что вам нужно знать, чтобы писать также многопоточные программы в пользовательском пространстве. Ну, вам не нужно знать точный ответ «какое значение вы читаете», но просто потому, что вы не можете на это полагаться, он определяется реализацией, даже если вы пишете код сборки для конкретного процессора. Просто потому, что вы не можете рассчитывать на относительную скорость двух параллельных потоков. Когда-либо.

1 голос
/ 07 января 2009

Справочное руководство IA-32 ответит на ваши вопросы окончательно.

Мой инстинкт инстинкта заключается в том, что оба ядра rx прерывают работу, и ОС пытается их разобраться. Вероятно, в каждом ядре есть регистр настроек, который определяет, какое ядро ​​получает какое прерывание.

Столкновение. Без гарантии. Чтобы быть более точным, посмотрите на механизмы кэширования и как они сортируют согласованность.

Для других тем, связанных с этим:

Как работают прерывания в многоядерных / многоядерных компьютерах?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...