Hi,
As I have already said, I solved the problem. I am not allowed to post the full source code, but I can give a sketch about what it was.
Consider the following snippet:
dma_list_data _list[2];
dma_buffer _buf[2];
unsigned int buffer_idx = 0;
create_mfc_list(_list[buffer_idx]);
initiate_mfc_get_list(_list[buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx);
while (there_is_more_data)
{
const unsigned int next_buffer_idx = buffer_idx ^ 1;
create_mfc_list(_list[next_buffer_idx]); (4)
initiate_mfc_get(_list[next_buffer_idx], _buf[next_buffer_idx], first_tag_id+next_buffer_idx); (1)
mfc_wait(1 << (first_tag_id+buffer_idx));
process_buffer(_buf[buffer_idx]);
create_mfc_list(_list[buffer_idx]); (3)
initiate_mfc_put(_list[buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx); (2)
buffer_idx = next_buffer_idx;
}
mfc_wait(1 << (first_tag_id+buffer_idx));
process_buffer(_buf[buffer_idx]);
create_mfc_list(_list[buffer_idx]);
initiate_mfc_put(_list[buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx);
mfc_wait(1 << (first_tag_id+buffer_idx));
As you can see, this double buffering scheme puts and (immediately after it) gets one of the buffers while processing the other. Thus, the GET command (line 1) has to be enforced to be issued after the PUT (line 2) has already been completed. You can use either fence or barrier with the GET command, both of them should work. But it still won't, because the code has another trivial error, which was hard for me to notice. It is that the dma list created at line 3 will be overwritten at line 4 but that time the PUT command is still working! Unfortunately, the output of the program will depend on the speed of
process_buffer and which of the compiler optimizations are turned on. My solution was to use 3 buffers to store the lists for dma:
dma_list_data _list[3];
dma_buffer _buf[2];
unsigned int buffer_idx = 0;
unsigned int list_buffer_idx = 0;
create_mfc_list(_list[list_buffer_idx]);
initiate_mfc_get_list(_list[list_buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx);
list_buffer_idx = (list_buffer_idx + 1) % 3;
while (there_is_more_data)
{
const unsigned int next_buffer_idx = buffer_idx ^ 1;
create_mfc_list(_list[list_buffer_idx]);
initiate_mfc_get_with_barrier(_list[list_buffer_idx], _buf[next_buffer_idx], first_tag_id+next_buffer_idx);
list_buffer_idx = (list_buffer_idx + 1) % 3;
mfc_wait(1 << (first_tag_id+buffer_idx));
process_buffer(_buf[buffer_idx]);
create_mfc_list(_list[list_buffer_idx]);
initiate_mfc_put(_list[list_buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx);
list_buffer_idx = (list_buffer_idx + 1) % 3;
buffer_idx = next_buffer_idx;
}
mfc_wait(1 << (first_tag_id+buffer_idx));
process_buffer(_buf[buffer_idx]);
create_mfc_list(_list[list_buffer_idx]);
initiate_mfc_put(_list[list_buffer_idx], _buf[buffer_idx], first_tag_id+buffer_idx);
mfc_wait(1 << (first_tag_id+buffer_idx));
I hope the explanation was easy to understand.
Regards,