Trace_buffer: do not reprocess last read entry

genodelabs/genode#4244
This commit is contained in:
Johannes Schlatow 2021-08-06 17:13:43 +02:00 committed by Christian Helmuth
parent 436d946300
commit 1416b2258f
2 changed files with 58 additions and 27 deletions

View File

@ -45,31 +45,47 @@ class Trace_buffer
if (wrapped) if (wrapped)
_wrapped_count = _buffer.wrapped(); _wrapped_count = _buffer.wrapped();
/* initialize _curr if _buffer was empty until now */ Trace::Buffer::Entry new_curr { _curr };
Trace::Buffer::Entry curr { _curr }; Trace::Buffer::Entry entry { _curr };
if (_curr.last())
curr = _buffer.first(); /**
* 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).
*
* 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.
*/
if (entry.last())
entry = _buffer.first();
else
entry = _buffer.next(entry);
/* iterate over all entries that were not processed yet */ /* iterate over all entries that were not processed yet */
Trace::Buffer::Entry e1 = curr; for (; wrapped || !entry.last(); entry = _buffer.next(entry)) {
for (Trace::Buffer::Entry e2 = curr; wrapped || !e2.last();
e2 = _buffer.next(e2)) {
/* if buffer wrapped, we pass the last entry once and continue at first entry */ /* if buffer wrapped, we pass the last entry once and continue at first entry */
if (wrapped && e2.last()) { if (wrapped && entry.last()) {
wrapped = false; wrapped = false;
e2 = _buffer.first(); entry = _buffer.first();
if (e2.last()) if (entry.last())
break; break;
} }
e1 = e2; if (!functor(entry))
if (!functor(e1))
break; break;
new_curr = entry;
} }
/* remember the last processed entry in _curr */ /* remember the last processed entry in _curr */
curr = e1; if (update) _curr = new_curr;
if (update) _curr = curr;
} }
void * address() const { return &_buffer; } void * address() const { return &_buffer; }

View File

@ -50,28 +50,43 @@ class Trace_buffer
_wrapped_count = _buffer.wrapped(); _wrapped_count = _buffer.wrapped();
} }
/* initialize _curr if _buffer was empty until now */ Trace::Buffer::Entry entry { _curr };
if (_curr.last())
_curr = _buffer.first(); /**
* 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).
*
* 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.
*/
if (entry.last())
entry = _buffer.first();
else
entry = _buffer.next(entry);
/* iterate over all entries that were not processed yet */ /* iterate over all entries that were not processed yet */
Trace::Buffer::Entry e1 = _curr; for (; wrapped || !entry.last(); entry = _buffer.next(entry))
for (Trace::Buffer::Entry e2 = _curr; wrapped || !e2.last();
e2 = _buffer.next(e2))
{ {
/* if buffer wrapped, we pass the last entry once and continue at first entry */ /* if buffer wrapped, we pass the last entry once and continue at first entry */
if (wrapped && e2.last()) { if (wrapped && entry.last()) {
wrapped = false; wrapped = false;
e2 = _buffer.first(); entry = _buffer.first();
if (e2.last()) if (entry.last())
break; break;
} }
e1 = e2; /* remember the last processed entry in _curr */
functor(e1); _curr = entry;
functor(_curr);
} }
/* remember the last processed entry in _curr */
_curr = e1;
} }
}; };