trace: make trace buffer resizeable

Trace buffers a re-allocated during subsequent calls to 'trace'.

issue #3294
This commit is contained in:
Sebastian Sumpf 2019-05-06 10:42:05 +02:00 committed by Christian Helmuth
parent ac0ecdf855
commit 25484f870e
2 changed files with 42 additions and 15 deletions

View File

@ -79,19 +79,18 @@ class Genode::Trace::Subject
/** /**
* Allocate new dataspace * Allocate new dataspace
*
* \return true on success, false on the attempt to call setup
* twice.
*/ */
bool setup(Ram_allocator &ram, size_t size) void setup(Ram_allocator &ram, size_t size)
{ {
if (_size && _size == size)
return;
if (_size) if (_size)
return false; _ram_ptr->free(_ds);
_ram_ptr = &ram; _ram_ptr = &ram;
_size = size; _size = size;
_ds = ram.alloc(size); _ds = ram.alloc(size);
return true;
} }
/** /**
@ -103,6 +102,9 @@ class Genode::Trace::Subject
if (!from_ds.valid()) if (!from_ds.valid())
return false; return false;
if (_size)
flush();
_ram_ptr = &ram; _ram_ptr = &ram;
_size = size; _size = size;
_ds = ram.alloc(_size); _ds = ram.alloc(_size);
@ -144,6 +146,7 @@ class Genode::Trace::Subject
Ram_dataspace _buffer { }; Ram_dataspace _buffer { };
Ram_dataspace _policy { }; Ram_dataspace _policy { };
Policy_id _policy_id { }; Policy_id _policy_id { };
size_t _allocated_memory { 0 };
Subject_info::State _state() Subject_info::State _state()
{ {
@ -162,6 +165,18 @@ class Genode::Trace::Subject
return Subject_info::UNTRACED; return Subject_info::UNTRACED;
} }
void _traceable_or_throw()
{
switch(_state()) {
case Subject_info::DEAD : throw Source_is_dead();
case Subject_info::FOREIGN : throw Traced_by_other_session();
case Subject_info::ERROR : throw Source_is_dead();
case Subject_info::INVALID : throw Nonexistent_subject();
case Subject_info::UNTRACED: return;
case Subject_info::TRACED : return;
}
}
public: public:
/** /**
@ -184,6 +199,9 @@ class Genode::Trace::Subject
*/ */
bool has_source_id(unsigned id) const { return id == _source_id; } bool has_source_id(unsigned id) const { return id == _source_id; }
size_t allocated_memory() const { return _allocated_memory; }
void reset_allocated_memory() { _allocated_memory = 0; }
/** /**
* Start tracing * Start tracing
* *
@ -199,21 +217,23 @@ class Genode::Trace::Subject
size_t policy_size, Ram_allocator &ram, size_t policy_size, Ram_allocator &ram,
Region_map &local_rm, size_t size) Region_map &local_rm, size_t size)
{ {
/* check state and throw error in case subject is not traceable */
_traceable_or_throw();
_policy_id = policy_id; _policy_id = policy_id;
if (!_buffer.setup(ram, size) _buffer.setup(ram, size);
|| !_policy.setup(ram, local_rm, policy_ds, policy_size)) if(!_policy.setup(ram, local_rm, policy_ds, policy_size))
throw Already_traced(); throw Already_traced();
/* inform trace source about the new buffer */ /* inform trace source about the new buffer */
Locked_ptr<Source> source(_source); Locked_ptr<Source> source(_source);
if (!source.valid())
throw Source_is_dead();
if (!source->try_acquire(*this)) if (!source->try_acquire(*this))
throw Traced_by_other_session(); throw Traced_by_other_session();
_allocated_memory = policy_size + size;
source->trace(_policy.dataspace(), _buffer.dataspace()); source->trace(_policy.dataspace(), _buffer.dataspace());
} }

View File

@ -82,21 +82,28 @@ void Session_component::trace(Subject_id subject_id, Policy_id policy_id,
size_t const policy_size = _policies.size(*this, policy_id); size_t const policy_size = _policies.size(*this, policy_id);
size_t const required_ram = buffer_size + policy_size; size_t const required_ram = buffer_size + policy_size;
Trace::Subject &subject = _subjects.lookup_by_id(subject_id);
/* revert quota from previous call to trace */
if (subject.allocated_memory()) {
_md_alloc.upgrade(subject.allocated_memory());
subject.reset_allocated_memory();
}
/* /*
* Account RAM needed for trace buffer and policy buffer to the trace * Account RAM needed for trace buffer and policy buffer to the trace
* session. * session.
*/ */
if (!_md_alloc.withdraw(required_ram)) if (!_md_alloc.withdraw(required_ram)) {
throw Out_of_ram(); throw Out_of_ram();
}
try { try {
Trace::Subject &subject = _subjects.lookup_by_id(subject_id);
subject.trace(policy_id, _policies.dataspace(*this, policy_id), subject.trace(policy_id, _policies.dataspace(*this, policy_id),
policy_size, _ram, _local_rm, buffer_size); policy_size, _ram, _local_rm, buffer_size);
} catch (...) { } catch (...) {
/* revert withdrawal or quota */ /* revert withdrawal or quota */
_md_alloc.upgrade(required_ram); _md_alloc.upgrade(required_ram);
throw Out_of_ram(); throw;
} }
} }