Если добавлять volatile для всей памяти -- это будет треш, угар и
содомия (при просмотре дизассемблера -- крайне неоптимальный код).
Так делать не нужно. Потом возникает другая проблема -- вся область
памяти становится несовместимой (без постоянных
reinterpret_cast'ов) с обычными указателями и всеми интерфейсами в
программе. Вообще volatile не нужен. Достаточно вставлять memory
barrier. В случае кольцевого буфера: после записи данных и перед
измененим указателя записи, и после чтения данных и перед изменением указателя чтения. И после всех операций (если они делаются в цикле, например), иначе оно автоматом запишется на выходе из функции. Да, в случае чтения данных, перед изменением указателя нужен другой тип барьера в C++, в который можно запутаться (). Поэтому проще не ломать голову и пользоваться фактом, что функция сама по себе -- железобетонный барьер.
https://en.cppreference.com/w/cpp/atomic/memory_order