mmap проблеми с четенето на споделен буфер

Имам модул на ядрото, който разпределя голям буфер от памет, този буфер след това е mmap-ed в потребителското пространство.
Модулът получава някои данни от хардуера и след това поставя новите данни в буфера с флаг пред него . (паметта се инициализира на нула, флагът е 1).

Програмата за потребителско пространство чете флага в цикъл, преди да върне указател към валидни данни

опростена версия на кода:

uint8_t * getData()
{
    while(1)
   {
      if(*((volatile uint32_t*)this->buffer) == 1)
          return this->buffer+sizeof(uint32_t);
   }
}

регионът на паметта е картографиран като споделен и пълен дъмп на паметта на буфера потвърждава, че буферът е записан правилно.

Проблемът е, че след определен брой правилни четения тази функция спира да се връща.
Възможно ли е това да се дължи на кеширане на процесора? Има ли начин да се заобиколи това и да се уверите, че четенето се извършва директно от RAM всеки път, а не от кеша?


person Lifesworder    schedule 07.02.2012    source източник
comment
Това е много специфично за архитектурата, а вие не сте ни казали вашата архитектура. Като цяло, излъчването на бариера за съхранение/освобождаване след запис в ядрото и бариера за зареждане/придобиване преди четене в потребителското пространство трябва да е достатъчно, ако това наистина е проблемът.   -  person Useless    schedule 08.02.2012
comment
@Lifesworder изглежда, че сте нов потребител, но етикетът тук изисква отговор, когато сте задали въпрос и ви бъдат предложени някои отговори.   -  person chetan    schedule 09.02.2012
comment
Извинявам се, срокове, много работа :). Не съм сигурен какво е причинило проблема на първо място, но изглежда, че премахването на флаговете MAP_SHARED и MAP_LOCKED от mmap манипулатора на ядрото е коригирало проблема...   -  person Lifesworder    schedule 11.02.2012
comment
Имам предвид VM_LOCKED и VM_SHARED от vma-›флагове.   -  person Lifesworder    schedule 11.02.2012


Отговори (2)


Да, вероятно се дължи на кеша на процесора от страната на четеца. Човек може да си помисли, че ключовата дума "volatile" трябва да предпазва от този вид проблем, но това не е съвсем правилно, тъй като volatile е просто директива към компилатора да не регистрира променливата, а не съвсем същото като насочване на процесора да чете директно от основната памет всеки път.

Проблемът трябва да се реши от страната на запис. От вашето описание звучи, че записът се случва в модула на ядрото и се чете от страна на потребителя. Ако тези две операции се случват на различни процесори (различни домейни за кеширане) и няма нищо, което да задейства невалидност на кеша от страната на четене, ще се забиете от страната на четене, както описвате. Трябва да принудите промиване на буфера на магазина на ядрото на linux след вашата инструкция за магазин. Ако приемем, че това е ядрото на Linux, вмъкването на извикване на smp_mb веднага след като сте задали флага и стойността от модула най-вероятно ще направи правилното нещо на всички архитектури.

person chetan    schedule 08.02.2012
comment
Тъй като тествах на едноядрен процесор, това не помогна за моя проблем само по себе си, но вашият отговор ще ми бъде от полза, когато трябва да пренеса това, за да работи на многоядрен процесор (което ще направя). - person Lifesworder; 11.02.2012
comment
аха... интересно. Някак си в наши дни е лесно да се предположи, че всички работят върху многоядрени системи. - person chetan; 14.02.2012

По-добър начин да предупредите приложението за потребителско пространство за наличието на повече данни би било да го блокирате в read() на файлов дескриптор, предоставен от модула на ядрото, като модулът на ядрото го събужда, когато има повече данни.

person caf    schedule 08.02.2012