dev: Fix incorrect terminal backlog handling

The Terminal device currently uses the peek functionality in gem5's
circular buffer implementation to send existing buffered content on
the terminal when a new client attaches. This functionallity is
however not implemented correctly and re-sends the same block multiple
time.

Add the required functionality to peek with an offset into the
circular buffer and change the Terminal::accept() implementation to
send the buffered contents.

Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Radhika Jagtap <radhika.jagtap@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
This commit is contained in:
Andreas Sandberg 2016-04-27 15:33:58 +01:00
parent 67e93a5846
commit 6d74892b38
2 changed files with 20 additions and 8 deletions

View file

@ -103,24 +103,36 @@ class CircleBuf
*/ */
template <class OutputIterator> template <class OutputIterator>
void peek(OutputIterator out, size_t len) const { void peek(OutputIterator out, size_t len) const {
panic_if(len > size(), peek(out, 0, len);
}
/**
* Copy buffer contents without advancing the read pointer
*
* @param out Output iterator/pointer
* @param offset Offset into the ring buffer
* @param len Number of elements to copy
*/
template <class OutputIterator>
void peek(OutputIterator out, off_t offset, size_t len) const {
panic_if(offset + len > size(),
"Trying to read past end of circular buffer.\n"); "Trying to read past end of circular buffer.\n");
if (_start + len <= buf.size()) { const off_t real_start((offset + _start) % buf.size());
std::copy(buf.begin() + _start, if (real_start + len <= buf.size()) {
buf.begin() + _start + len, std::copy(buf.begin() + real_start,
buf.begin() + real_start + len,
out); out);
} else { } else {
const size_t head_size(buf.size() - _start); const size_t head_size(buf.size() - real_start);
const size_t tail_size(len - head_size); const size_t tail_size(len - head_size);
std::copy(buf.begin() + _start, buf.end(), std::copy(buf.begin() + real_start, buf.end(),
out); out);
std::copy(buf.begin(), buf.begin() + tail_size, std::copy(buf.begin(), buf.begin() + tail_size,
out + head_size); out + head_size);
} }
} }
/** /**
* Copy buffer contents and advance the read pointer * Copy buffer contents and advance the read pointer
* *

View file

@ -204,7 +204,7 @@ Terminal::accept()
char buf[1024]; char buf[1024];
for (size_t i = 0; i < txbuf.size(); i += sizeof(buf)) { for (size_t i = 0; i < txbuf.size(); i += sizeof(buf)) {
const size_t chunk_len(std::min(txbuf.size() - i, sizeof(buf))); const size_t chunk_len(std::min(txbuf.size() - i, sizeof(buf)));
txbuf.peek(buf, chunk_len); txbuf.peek(buf, i, chunk_len);
write((const uint8_t *)buf, chunk_len); write((const uint8_t *)buf, chunk_len);
} }
} }