Program Listing for File tohost_buffer.cpp
↰ Return to documentation for file (tohost_buffer.cpp
)
#include "tohost_buffer.hpp"
#include "log.hpp"
#include <algorithm>
ToHostBuffer::ToHostBuffer(int dmaid, std::shared_ptr<Device> d)
: m_dmaid(dmaid), m_device(d), m_block_size(0),
m_irq_on_data(IRQ_DATA_AVAILABLE + dmaid), m_irq_counter(0), m_size(0),
m_stop_flag(false), m_has_zero_copy_reader(false), m_min_bytes_sent(0)
{}
std::vector<std::vector<Elink>> ToHostBuffer::split_elinks_of_type(elink_type_t t, size_t n)
{
std::vector<Elink> vec = get_elinks_of_type(t);
std::vector<std::vector<Elink>> result;
size_t length = vec.size() / n;
size_t remain = vec.size() % n;
size_t begin = 0;
size_t end = 0;
for (size_t i = 0; i < std::min(n, vec.size()); ++i) {
end += (remain > 0) ? (length + !!(remain--)) : length;
result.push_back(std::vector<Elink>(vec.begin() + begin, vec.begin() + end));
begin = end;
}
return result;
}
uint32_t ToHostBuffer::reader_register(bool zero_copy)
{
std::scoped_lock lock(m_mutex);
uint64_t offset = (uint64_t)dma_get_read_offset();
m_bytes_read.push_back(offset);
m_bytes_sent.push_back(offset);
uint32_t reader_id = m_bytes_read.size() - 1;
return reader_id;
}
//The amount of data available is computed with read blocks
//also when zero-copy publishers are used.
//Otherwise the "data available" signal would be always fired
//at the end of the ToHostReader<B>::read function
size_t ToHostBuffer::reader_get_available_bytes(uint32_t reader_id)
{
uint64_t write_offset = dma_get_write_offset();
uint64_t read_offset = m_bytes_read[reader_id] % m_size;
LOG_TRACE("Reader id %u, write 0x%lx read 0x%lx", reader_id, write_offset, read_offset);
if (write_offset > read_offset) {
return write_offset - read_offset;
}
else if (write_offset < read_offset) {
return m_size - read_offset;
}
else if (dma_is_full()) {
if (m_bytes_read[reader_id] == m_min_bytes_sent) {
return m_size - read_offset;
}
}
return 0;
}
bool ToHostBuffer::reader_is_data_available(uint32_t reader_id)
{
return reader_get_available_bytes(reader_id);
}
std::span<Block> ToHostBuffer::reader_get_available_blocks(uint32_t reader_id)
{
return std::span(reinterpret_cast<Block*>(m_buffer->vaddr + m_bytes_read[reader_id] % m_size),
reader_get_available_bytes(reader_id)/sizeof(Block));
}
void ToHostBuffer::reader_advance_read_ptr(uint32_t reader_id, uint32_t read_bytes, uint32_t sent_bytes)
{
std::scoped_lock lock(m_mutex);
auto last_bytes_sent = m_bytes_sent[reader_id];
m_bytes_read[reader_id] += read_bytes;
m_bytes_sent[reader_id] += sent_bytes;
if (m_min_bytes_sent == last_bytes_sent) {
m_min_bytes_sent = *std::ranges::min_element(m_bytes_sent);
if (m_min_bytes_sent != last_bytes_sent) {
dma_set_read_ptr_paddr(m_buffer->paddr + (m_min_bytes_sent % m_size));
}
}
}
uint32_t ToHostBuffer::dma_get_free_MB()
{
auto to_read = dma_bytes_available();
return (m_buffer->size - to_read)/1024/1024;
}