Одновременный доступ к памяти пользователя - PullRequest
1 голос
/ 02 марта 2012

Рассмотрим это

Тема 1 в пользовательской программе:

buf = malloc(9000);
memset(buf, 0xee, 9000);
read(buf, 9000); //for example gives pages [part of 7, 8, 9, part of 10]

Тема 2 в пользовательской программе:

buf = malloc(9000); //for example gives pages [part of 4, 6, 5, part of 7]
memset(buf, 0xee, 9000);
read(buf, 9000);

Драйвер прочитан:

get_user_pages();

//build dma sg list from pages
//...

//the platform demands a cachesync
for(all pages) {
    dma_cache_wback_inv();
}

//start dma and wait for it to be done
//...
wait_event_interruptible_timeout(); //blocks calling thread until dma done

for(all pages) {
    if(read) SetPageDirty();
    page_cache_release();
}

Обратите внимание, что страница 7 используется обеими передачами, и это было большой проблемой, иногда приводившей к неверным данным (0xee находится в конце одного буфера). Просто чтобы прояснить, эти два чтения выполняются на разных каналах DMA, поэтому они могут выполняться одновременно.

Мое решение состояло в том, чтобы выровнять буферы страницы в пользовательской программе так, чтобы два драйвера DMA никогда не разделяли части одной страницы.

Интересно, есть ли другое решение для этого? Мне также интересно, почему именно это было большой проблемой.

1 Ответ

1 голос
/ 02 марта 2012

Это ограничение вашего встроенного процессора и DMA, которые не связаны с кэшем.В высокопроизводительных чипах PowerPC эта проблема исчезает.

Ваши два буфера совместно используют строку кэша в точке, где они встречаются.В то время как один поток находится в драйвере, записывающем кеш в ОЗУ, второй поток все еще находится в memset, заполняя строку кеша 0xee.

DMA 1 записывает ваши данные в ОЗУ, но процессор все еще удерживаетгрязная строка кэша для этих данных, содержащая 0xee.Когда второй поток записывает кэш, он помещает 0xee поверх данных, полученных из DMA1.

Решения:

  1. Кэширование выравнивания ваших буферов (максимальная производительность).
  2. Использование отказов буфера в драйвере ядра (наиболее совместимо с существующим кодом пространства пользователя).

get_user_pages() здесь не является частью проблемы - это касается аппаратного обеспечения ивремя. * 1 016 *

...