Подтвердить что ты не робот

Являются ли барьеры памяти необходимыми для подсчета атомных ссылок совместно используемыми неизменяемыми данными?

У меня есть некоторые неизменные структуры данных, с которыми я бы хотел справиться, используя подсчет ссылок, разделяя их по потокам в системе SMP.

Вот что выглядит код выпуска:

void avocado_release(struct avocado *p)
{
    if (atomic_dec(p->refcount) == 0) {
        free(p->pit);
        free(p->juicy_innards);
        free(p);
    }
}

Требуется ли atomic_dec в нем барьер памяти? Если да, то какой барьер памяти?

Дополнительные примечания: приложение должно работать на PowerPC и x86, поэтому приветствуется вся информация, относящаяся к конкретному процессору. Я уже знаю о атомных сборках GCC. Что касается неизменности, то refcount является единственным полем, которое изменяется в течение продолжительности объекта.

4b9b3361

Ответ 1

На x86 он превратится в инструкцию по сборке с префиксом блокировки, например LOCK XADD.
Будучи единой инструкцией, она не прерывается. В качестве добавленного "feauture" префикс блокировки приводит к полному барьеру памяти:

"... заблокированные операции сериализуют все выдающиеся операции загрузки и хранения (то есть ждут их завершения)."... "Заблокированные операции являются атомарными по отношению ко всем другим операциям памяти и всем видимым извне событиям. Доступ к команде и выбор таблицы страниц могут передавать заблокированные инструкции. Заблокированные инструкции могут использоваться для синхронизации данных, написанных одним процессором и считанных другим процессором". - Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32, глава 8.1.2.

На самом деле барьер памяти реализуется как манекен LOCK OR или LOCK AND в .NET и JAVA JIT на x86/x64.
Таким образом, у вас есть полный забор на x86 в качестве дополнительного бонуса, нравится вам это или нет.:)

В КПП это другое. Пара LL/SC - lwarx и stwcx - с вычитанием внутри можно использовать для загрузки операнда памяти в регистр, вычесть его, затем либо записать обратно, если в целевое местоположение не было другого хранилища, либо повторить весь цикл, если он был. LL/SC может быть прерван.
Это также не означает автоматический полный забор.
Это никоим образом не скомпрометирует атомарность счетчика.
Это просто означает, что в случае x86 вы также получаете забор, "бесплатно" .
В PPC можно вставить полный забор, испустив (lw)sync .Суб >

В общем, явные барьеры памяти не нужны, чтобы атомный счетчик работал правильно.

Ответ 2

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

Пункты памяти препятствуют переупорядочению чтений и записи, а переупорядочение полностью ортогонально к атомарности. Например, на PowerPC, если вы реализуете наиболее эффективный атомный приращение, это не помешает переупорядочению. Если вы хотите предотвратить переупорядочение, вам понадобится инструкция lwsync или sync или какой-либо эквивалентный высокоуровневый (С++ 11?) Барьер памяти.

Утверждается, что "нет возможности компилятора переупорядочить вещи проблематичным образом" кажутся наивными, как общие утверждения, поскольку оптимизация компилятора может быть довольно неожиданным и потому, что процессоры (в частности, PowerPC/ARM/Alpha/MIPS) агрессивно меняют порядок операций с памятью.

Когерентный кеш не спасет вас. См. http://preshing.com/, чтобы увидеть, как действительно работает переупорядочение памяти.

В этом случае, однако, я считаю, что ответ заключается в том, что никаких барьеров не требуется. Это связано с тем, что для этого конкретного случая (подсчета ссылок) нет необходимости в отношении отношения между счетчиком ссылок и другими значениями в объекте. Единственное исключение - когда счетчик ссылок достигает нуля. В этот момент важно обеспечить, чтобы все обновления из других потоков были видны текущему потоку, поэтому может потребоваться барьер считывания.

Ответ 3

Намерены ли вы реализовать свой собственный atomic_dec или вам просто интересно, будет ли система, работающая под управлением, вести себя так, как вы хотите?

Как правило, поставляемые в комплекте атомарные устройства увеличения/уменьшения уровня будут применяться к любым барьерам памяти, чтобы делать правильные действия. Вы, как правило, не должны беспокоиться о барьерах памяти, если вы не делаете что-то нелепо, как реализовать свои собственные блокированные структуры данных или библиотеку STM.