Теоретически допустимо ли (ошибочно) использовать только случайное повторное использование диапазона памяти в динамическом распределении для синхронизации потоков? - PullRequest
0 голосов
/ 30 мая 2019

В C ++ динамическое выделение памяти (de) (malloc-free / new-delete), очевидно, может многократно получать тот же диапазон памяти, который освобождается и распределяется снова по порядку.В многопоточном C ++ это может происходить в нескольких потоках.

Очевидно, что такое повторное использование не должно быть проблемой пользователя, и он не должен заботиться об этом;вот как это указано в " гонках данных " [new.delete.dataraces]

В целях определения существования гонок данных,библиотечные версии оператора new, пользовательские версии замены глобального оператора new, стандартные библиотечные функции C align_alloc, calloc и malloc, библиотечные версии оператора delete, пользовательские замещающие версии оператора delete, свободная функция стандартной библиотеки C и CФункция стандартной библиотеки realloc не должна вводить гонку данных ([res.on.data.races]).Вызовы этих функций, которые выделяют или освобождают определенную единицу хранения, должны происходить в едином общем порядке, и каждый такой вызов освобождения должен происходить до следующего выделения (если есть) в этом порядке.

Последнее предложение интересно: не только повторное использование диапазона памяти не приводит к конфликту, но также и то, что должно существовать , предшествующее отношению (HB).Хотя это не говорит о том, что реализация должна создавать отношение HB, и, хотя требования HB обычно являются требованиями для пользователя, поскольку требование является условным и основано на особом случае, созданном реализацией (стандартный код библиотеки), онаКажется очевидным, что это может быть интерпретировано только как требование к реализации.

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

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

Чтовыглядело бы как очень странное бремя для реализации, используемое только чрезвычайно причудливым кодом, который запомнил бы копии удаленных адресов в случае, если какой-то другой поток получит эти же адреса (хотя и неповторение любой синхронизации, например, с помощью расслабленных атомарных операций RMW над представлениями указателей.

Заботятся ли реальные реализации, чтобы действительно обеспечить эту видимость?Функции выделения памяти рассматриваются как функции «черного ящика» или как операции получения (освобождения) компилятором?

ДОПОЛНИТЕЛЬНАЯ ТОЧНОСТЬ

Здесь потенциально проблемный случай: компилятор может предоставлять атрибутыуказать семантические свойства функций (например, GCC Common Function Attributes ), которые идентифицируют функции, которые могут влиять только на некоторый диапазон памяти (в текущем «модуле», который был бы областью программных инвариантов: user, stdlib,другая библиотека ...).Я признаю, что не проработал детали, но это кажется интуитивно выполнимым, и концепции кажутся потенциально полезными для оптимизации.

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

1 Ответ

1 голос
/ 30 мая 2019

Видимость произвольных операций с памятью не гарантируется при таких распределениях.

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

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

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

Спецификации иногда бывают довольно педантичными.

Это может показаться чрезвычайно странным бременем для реализации

Не совсем.Видимость может потребоваться только в отношении выделения / выделения памяти, но даже видимость вряд ли будет удивительной или обременительной.

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

И никто не ошибся в использовании общего распределителя памяти как операция fast .

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

Вотпотенциально проблемный случай: компилятор может предоставить атрибуты для указания семантических свойств функций (например, атрибутов общих функций GCC), которые идентифицируют функции, которые могут влиять только на некоторый диапазон памяти (в текущем «модуле», который будет являться областью программных инвариантов:user, stdlib, other library ...).

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

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