Учти это
Поток 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 с двумя драйверами никогда не делил части одной и той же страницы.
Интересно, есть ли другое решение для этого? Я также удивляюсь, почему именно это было большой проблемой.