Line data Source code
1 : #include "tohost_buffer.hpp" 2 : #include "log.hpp" 3 : #include <algorithm> 4 : 5 22 : ToHostBuffer::ToHostBuffer(int dmaid, std::shared_ptr<Device> d) 6 44 : : m_dmaid(dmaid), m_device(d), m_block_size(0), 7 22 : m_irq_on_data(IRQ_DATA_AVAILABLE + dmaid), m_irq_counter(0), m_size(0), 8 22 : m_stop_flag(false), m_has_zero_copy_reader(false), m_min_bytes_sent(0) 9 22 : {} 10 : 11 : 12 22 : std::vector<std::vector<Elink>> ToHostBuffer::split_elinks_of_type(elink_type_t t, size_t n) 13 : { 14 22 : std::vector<Elink> vec = get_elinks_of_type(t); 15 22 : std::vector<std::vector<Elink>> result; 16 22 : size_t length = vec.size() / n; 17 22 : size_t remain = vec.size() % n; 18 22 : size_t begin = 0; 19 22 : size_t end = 0; 20 44 : for (size_t i = 0; i < std::min(n, vec.size()); ++i) { 21 20 : end += (remain > 0) ? (length + !!(remain--)) : length; 22 40 : result.push_back(std::vector<Elink>(vec.begin() + begin, vec.begin() + end)); 23 20 : begin = end; 24 : } 25 22 : return result; 26 22 : } 27 : 28 : 29 24 : uint32_t ToHostBuffer::reader_register(bool zero_copy) 30 : { 31 24 : std::scoped_lock lock(m_mutex); 32 24 : uint64_t offset = (uint64_t)dma_get_read_offset(); 33 24 : m_bytes_read.push_back(offset); 34 24 : m_bytes_sent.push_back(offset); 35 24 : uint32_t reader_id = m_bytes_read.size() - 1; 36 24 : return reader_id; 37 24 : } 38 : 39 : //The amount of data available is computed with read blocks 40 : //also when zero-copy publishers are used. 41 : //Otherwise the "data available" signal would be always fired 42 : //at the end of the ToHostReader<B>::read function 43 6885741 : size_t ToHostBuffer::reader_get_available_bytes(uint32_t reader_id) 44 : { 45 6885741 : uint64_t write_offset = dma_get_write_offset(); 46 6885809 : uint64_t read_offset = m_bytes_read[reader_id] % m_size; 47 6885809 : LOG_TRACE("Reader id %u, write 0x%lx read 0x%lx", reader_id, write_offset, read_offset); 48 6885809 : if (write_offset > read_offset) { 49 5822531 : return write_offset - read_offset; 50 : } 51 1063278 : else if (write_offset < read_offset) { 52 857288 : return m_size - read_offset; 53 : } 54 205990 : else if (dma_is_full()) { 55 20344 : if (m_bytes_read[reader_id] == m_min_bytes_sent) { 56 19330 : return m_size - read_offset; 57 : } 58 : } 59 : return 0; 60 : } 61 : 62 : 63 0 : bool ToHostBuffer::reader_is_data_available(uint32_t reader_id) 64 : { 65 0 : return reader_get_available_bytes(reader_id); 66 : } 67 : 68 : 69 6885728 : std::span<Block> ToHostBuffer::reader_get_available_blocks(uint32_t reader_id) 70 : { 71 13771322 : return std::span(reinterpret_cast<Block*>(m_buffer->vaddr + m_bytes_read[reader_id] % m_size), 72 6885728 : reader_get_available_bytes(reader_id)/sizeof(Block)); 73 : } 74 : 75 : 76 6885608 : void ToHostBuffer::reader_advance_read_ptr(uint32_t reader_id, uint32_t read_bytes, uint32_t sent_bytes) 77 : { 78 6885608 : std::scoped_lock lock(m_mutex); 79 6885929 : auto last_bytes_sent = m_bytes_sent[reader_id]; 80 6885929 : m_bytes_read[reader_id] += read_bytes; 81 6885929 : m_bytes_sent[reader_id] += sent_bytes; 82 : 83 6885929 : if (m_min_bytes_sent == last_bytes_sent) { 84 6709238 : m_min_bytes_sent = *std::ranges::min_element(m_bytes_sent); 85 : 86 6709238 : if (m_min_bytes_sent != last_bytes_sent) { 87 545303 : dma_set_read_ptr_paddr(m_buffer->paddr + (m_min_bytes_sent % m_size)); 88 : } 89 : } 90 6885841 : } 91 : 92 : 93 177 : uint32_t ToHostBuffer::dma_get_free_MB() 94 : { 95 177 : auto to_read = dma_bytes_available(); 96 177 : return (m_buffer->size - to_read)/1024/1024; 97 : }