Как работает sig_atomic_t?

Как компилятор или ОС различают тип sig_atomic_t и нормальную переменную типа int и гарантирует, что операция будет атомарной? Программы, использующие оба, имеют одинаковый код ассемблера. Как сделать дополнительную операцию, чтобы сделать операцию атомой?

Ответ 1

sig_atomic_t не является типом данных атома. Это только тип данных, который вы можете использовать в контексте обработчика сигналов, вот и все. Поэтому лучше читать имя как "атомный относительно обработки сигналов".

Чтобы гарантировать связь с обработчиком сигналов и от него, требуется только одно из свойств атомных типов данных, а именно тот факт, что чтение и обновление всегда будут видеть согласованное значение. Другие типы данных (например, возможно, long long) могут быть записаны с несколькими инструкциями ассемблера для нижней и верхней частей, например. sig_atomic_t гарантированно читается и записывается за один раз.

Таким образом, платформа может выбрать любой целочисленный базовый тип как sig_atomic_t, для которого он может гарантировать, что volatile sig_atomic_t можно безопасно использовать в обработчиках сигналов. Многие платформы выбрали для этого int, потому что они знают, что для них int записывается с одной инструкцией.

Последний C-стандарт C11 имеет атомные типы, но это совершенно другая вещь. Некоторые из них (те, которые являются "неблокируемыми" ) также могут использоваться в обработчиках сигналов, но это опять-таки совершенно другая история.

Ответ 2

Обратите внимание, что sig_atomic_t не является потокобезопасным, только безопасным для асинхронного сигнала.

Атомы включают два типа барьеров:

  • Предел компилятора. Он гарантирует, что компилятор не изменяет порядок чтения/записи с/на атомную переменную относительно чтения и записи на другие переменные. Это ключевое слово volatile.
  • ЦП и видимость ЦП. Он гарантирует, что процессор не будет изменять порядок чтения и записи. На x86 все нагрузки и хранилища в выровненном 1,2,4,8-байтовом хранилище являются атомарными. Видимость гарантирует, что магазины станут видимыми для других потоков. Опять же, на процессорах Intel магазины сразу видны для других потоков из-за согласования когерентности и протокола согласования памяти MESI. Но это может измениться в будущем. Подробнее см. В §8.1 "ЗАБЛОКИРОВАННЫЕ АТОМНЫЕ ОПЕРАЦИИ" в Руководстве разработчиков программного обеспечения Intel® 64 и IA-32, том 3A.

Для всестороннего рассмотрения тематических часов атомное оружие: модель памяти С++ и современное оборудование.

Ответ 3

sig_atomic_t часто бывает просто typedef (к некоторому системному интегральному типу, обычно int или long). И очень важно использовать volatile sig_atomic_t (не только sig_atomic_t).

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

Недавно добавлен C11 _Atomic и <stdatomic.h>. Вам понадобится очень недавний GCC (например, 4.9), чтобы он поддерживался.

Ответ 4

Программы, использующие оба, имеют одинаковый код ассемблера. Как сделать дополнительную операцию, чтобы сделать операцию атомой?

Хотя это старый вопрос, я думаю, что он по-прежнему стоит рассматривать эту часть вопроса конкретно. В Linux sig_atomic_t предоставляется glibc. sig_atomic_t в glibc является typedef для int и не имеет специального лечения (начиная с этого поста). glibc docs адресуется к этому:

На практике вы можете предположить, что int является атомарным. Вы также можете предположить что типы указателей являются атомарными; это очень удобно. Оба из них предположения верны для всех машин, которые Библиотека GNU C поддерживает и на всех POSIX-системах, о которых мы знаем.

Другими словами, бывает так, что обычный int уже удовлетворяет требованиям sig_atomic_t на всех платформах, поддерживаемых glibc, и никакой специальной поддержки не требуется. Тем не менее, стандарты C и POSIX гарантируют sig_atomic_t, потому что может быть какая-то экзотическая машина, на которой мы хотим реализовать C и POSIX, для которых int не соответствует требованиям sig_atomic_t.

Ответ 5

Этот тип данных выглядит атомарным.
С здесь:

24.4.7.2 Атомарные типы Чтобы избежать неопределенности в прерывании доступа к переменной, вы можете использовать конкретный тип данных, для которого доступ всегда атомарный: sig_atomic_t. Чтение и запись этого типа данных гарантированно произойдет в одной инструкции, поэтому нет никакого способа для обработчик для запуска "в середине" доступа.

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

Тип данных: sig_atomic_t Это целочисленный тип данных. Объекты этого тип всегда доступен атомарно.

На практике вы можете предположить, что int является атомарным. Вы также можете предположить, типы указателей являются атомарными; это очень удобно. Оба эти допущения верны на всех машинах, которые библиотека GNU C поддерживает и во всех известных нам системах POSIX.