У меня есть два процесса C ++, которые обмениваются данными с отображением в памяти Single-Producer Single-Consumer (SPS C) двойной буфер . Процессы будут работать только в Linux / Intel x86-64. Семантика заключается в том, что производитель заполняет передний буфер, а затем меняет указатели и обновляет счетчик, давая потребителю знать, что он может memcpy()
задний буфер. Все совместно используемые состояния хранятся в блоке заголовка в начале отображаемой области.
int _fd;
volatile char *_mappedBuffer;
...
_fd = shm_open("/dev/shm/ipc_buffer", O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
...
_mappedBuffer = static_cast<char *>(mmap(nullptr, _shmFileSizeBytes, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE | MAP_POPULATE, _fd, 0));
Производителю необходим барьер StoreStore
, чтобы гарантировать, что своп виден до приращения счетчика, что должно быть неявным для x86, с памятью обратной записи (WB) :
void produce() {
...
// swap pointers
char *tmp = _frontBuffer;
_frontBuffer= _backBuffer;
_backBuffer= tmp;
...
// SFENCE needed here? Yes if uncacheable WC, NO if WB due to x86 ordering guarantees?
asm volatile ("sfence" ::: "memory");
_flipCounter++;
}
Потребителю необходим барьер LoadLoad
, если (W C), чтобы он загружал счетчик переворачивания до того, как новый указатель заднего буфера. Если память (WB), то мы знаем, что процессор не может переупорядочить нагрузки:
bool consume(uint64_t &localFlipVer, char *dst) {
if (localFlipVer < _flipCounter) {
// LFENCE needed here? Yes if uncacheable WC, NO if WB due to x86 ordering guarantees?
asm volatile ("lfence" ::: "memory");
std::memcpy(dst, _backBuffer, _bufferSize);
localFlipVer++;
return true;
}
return false;
}
Мой вопрос и мои предположения :
Is область отображения в памяти, возвращаемая mmapping /dev/shm
Write-Back или Non-cacheable Write-Combining? В последнем случае хранилища и загрузки заказаны слабо и не следуют традиционным гарантиям заказа x86 (без повторного заказа StoreStore или LoadLoad) согласно
https://hadibrais.wordpress.com/2019/02/26/the-significance-of-the-x86-sfence-instruction/
https://preshing.com/20120913/acquire-and-release-semantics/#IDComment721195741
https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/596002
и, следовательно, мне придется использовать SFENCE
и LFENCE
, в то время как обычно (с WB), я мог бы обойтись только с барьером компилятора asm volatile ("" ::: "memory");