Ensuring proper invalidation of the memory cache

So, I have a piece of code that looks like this:

uint8_t *buffer = <16 MB memory region> uint32_t count = 1024; uint32_t position = 0; uint8_t *get_data() { uint8_t *region = buffer + position * 16; position += 1; position %= count; do { __sync_synchronize(); } while (reigon[0] != 1); return region; } 

The buffer in question is written by the hardware device. At some point (maybe before we start the cycle, maybe after we start), the hardware will write to this place, as well as to the rest of the buffer.

I am currently using __sync_synchronize in order to release a memory barrier, because I would like to make sure that the compiler will not cache the rest of this memory area all the time until region[0] == 1 .

I know that I can mark the entire buffer as volatile. However, I would like to be able to return a non-volatile buffer from this function.

So, is there a way to do __sync_synchronize , but only it targets the range of memory that I specify. In this case, the memory from [region, region + 1024) ?

Aside, this code lives in user space. The memory buffer is a fixed area of ​​memory that I allocated with a kernel module mapped to user space and told FPGA, ultimately, to DMA. This is basically an attempt to implement a polling mechanism on an FPGA that completes the DMA transition.

+4
source share
2 answers

A fence with a limited region will be a rather unusual architectural feature. However, after the loop is complete, you only need a fence:

 while (*(volatile uint8_t *)region != 1) ; __sync_synchronize(); return region; 
+2
source

This should do the trick:

 uint8_t *get_data() { uint8_t *region = buffer + position * 16; volatile uint8_t *volatile_region = region; position += 1; position %= count; do { } while (volatile_region[0] != 1); return region; } 
0
source

All Articles