mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-14 13:18:19 +00:00
trace_buffer: revise trace buffer implementation
This commit simplifies the current implementation by overloading the length field with a padding indicator in addition to the zero-length head entry. This simplifies the iteration semantics as it eliminates the need for determining whether a zero-length entries is the actual head of the buffer or a padding at the buffer end. genodelabs/genode#4434
This commit is contained in:
committed by
Norman Feske
parent
d24552f5e2
commit
edc46d15f8
@ -46,62 +46,37 @@ class Trace_buffer
|
||||
if ((_buffer.wrapped() - 1) != _wrapped_count) {
|
||||
warning("buffer wrapped multiple times; you might want to raise buffer size; curr_count=",
|
||||
_buffer.wrapped(), " last_count=", _wrapped_count);
|
||||
_curr = _buffer.first();
|
||||
}
|
||||
_wrapped_count = (unsigned)_buffer.wrapped();
|
||||
}
|
||||
|
||||
Trace::Buffer::Entry new_curr { _curr };
|
||||
Trace::Buffer::Entry entry { _curr };
|
||||
|
||||
/**
|
||||
* If '_curr' is marked 'last' (i.e., the entry pointer it contains
|
||||
* is invalid), either this method wasn't called before on this
|
||||
* buffer or the buffer was empty on all previous calls (note that
|
||||
* '_curr' is only updated with valid entry pointers by this
|
||||
* method). In this case, we start with the first entry (if any).
|
||||
* Iterate over all entries that were not processed yet.
|
||||
*
|
||||
* If '_curr' is not marked 'last' it points to the last processed
|
||||
* entry and we proceed with the, so far unprocessed entry next to
|
||||
* it (if any). Note that in this case, the entry behind '_curr'
|
||||
* might have got overridden since the last call to this method
|
||||
* because the buffer wrapped and oustripped the entry consumer.
|
||||
* This problem is well known and should be avoided by choosing a
|
||||
* large enough buffer.
|
||||
* A note on terminology: The head of the buffer marks the write
|
||||
* position. The first entry is the one that starts at the lowest
|
||||
* memory address. The next entry returns an invalid entry called
|
||||
* if the 'last' end of the buffer (highest address) was reached.
|
||||
*/
|
||||
if (entry.last())
|
||||
entry = _buffer.first();
|
||||
else
|
||||
entry = _buffer.next(entry);
|
||||
|
||||
/* iterate over all entries that were not processed yet */
|
||||
for (; wrapped || !entry.last(); entry = _buffer.next(entry)) {
|
||||
/* if buffer wrapped, we pass the last entry once and continue at first entry */
|
||||
bool applied_wrap = false;
|
||||
if (wrapped && entry.last()) {
|
||||
wrapped = false;
|
||||
applied_wrap = true;
|
||||
for (; !entry.head(); entry = _buffer.next(entry)) {
|
||||
/* continue at first entry if we hit the end of the buffer */
|
||||
if (entry.last())
|
||||
entry = _buffer.first();
|
||||
if (entry.last()) {
|
||||
new_curr = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry.length()) {
|
||||
/* skip empty entries */
|
||||
if (entry.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!functor(entry)) {
|
||||
if (applied_wrap)
|
||||
new_curr = Trace::Buffer::Entry();
|
||||
/* functor may return false to continue processing later on */
|
||||
if (!functor(entry))
|
||||
break;
|
||||
}
|
||||
|
||||
new_curr = entry;
|
||||
}
|
||||
|
||||
/* remember the last processed entry in _curr */
|
||||
if (update) _curr = new_curr;
|
||||
/* remember the next to be processed entry in _curr */
|
||||
if (update) _curr = entry;
|
||||
}
|
||||
|
||||
void * address() const { return &_buffer; }
|
||||
|
Reference in New Issue
Block a user