Skip to content

Commit

Permalink
Remove exceptions from TRACE session interface
Browse files Browse the repository at this point in the history
- Use attempt pattern for error handling
- Replace lookup of pointers by with_ pattern
- Remove virtual Trace::Session methods
- Merge client.h into connection.h

Issue genodelabs#5245
  • Loading branch information
nfeske committed Jun 11, 2024
1 parent ec3e456 commit 1f76453
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 366 deletions.
23 changes: 3 additions & 20 deletions repos/base/include/base/trace/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,7 @@

namespace Genode { namespace Trace {

/*********************
** Exception types **
*********************/

struct Policy_too_large : Exception { };
struct Nonexistent_subject : Exception { };
struct Source_is_dead : Exception { };
struct Nonexistent_policy : Exception { };
struct Traced_by_other_session : Exception { };
struct Subject_not_traced : Exception { };

typedef String<32> Thread_name;
using Thread_name = String<32>;

struct Policy_id;
struct Subject_id;
Expand All @@ -48,10 +37,7 @@ namespace Genode { namespace Trace {
*/
struct Genode::Trace::Policy_id
{
unsigned id;

Policy_id() : id(0) { }
Policy_id(unsigned id) : id(id) { }
unsigned id { };

bool operator == (Policy_id const &other) const { return id == other.id; }
};
Expand All @@ -62,10 +48,7 @@ struct Genode::Trace::Policy_id
*/
struct Genode::Trace::Subject_id
{
unsigned id;

Subject_id() : id(0) { }
Subject_id(unsigned id) : id(id) { }
unsigned id { };

bool operator == (Subject_id const &other) const { return id == other.id; }
};
Expand Down
131 changes: 0 additions & 131 deletions repos/base/include/trace_session/client.h

This file was deleted.

136 changes: 122 additions & 14 deletions repos/base/include/trace_session/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,36 @@
#define _INCLUDE__TRACE_SESSION__CONNECTION_H_

#include <util/retry.h>
#include <trace_session/client.h>
#include <trace_session/trace_session.h>
#include <base/rpc_client.h>
#include <base/connection.h>
#include <base/attached_dataspace.h>

namespace Genode { namespace Trace { struct Connection; } }


struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
Genode::Trace::Session_client
Genode::Rpc_client<Genode::Trace::Session>
{
/**
* Shared-memory buffer used for carrying the payload of subject infos
*/
Attached_dataspace _argument_buffer;

size_t const _max_arg_size;

template <typename ERROR>
auto _retry(auto const &fn) -> decltype(fn())
{
return retry_with_upgrade(Ram_quota{8*1024}, Cap_quota{2}, fn);
for (;;) {
bool retry = false;
auto const result = fn();
if (result == ERROR::OUT_OF_CAPS) { upgrade_caps(2); retry = true; }
if (result == ERROR::OUT_OF_RAM) { upgrade_ram(8*1024); retry = true; }

if (!retry)
return result;
}
}

/**
Expand All @@ -39,31 +57,121 @@ struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
:
Genode::Connection<Session>(env, Label(), Ram_quota { 10*1024 + ram_quota },
Args("arg_buffer_size=", arg_buffer_size)),
Session_client(env.rm(), cap())
Genode::Rpc_client<Session>(cap()),
_argument_buffer(env.rm(), call<Rpc_dataspace>()),
_max_arg_size(arg_buffer_size)
{ }

Policy_id alloc_policy(size_t size) override
/**
* Allocate policy-module backing store
*/
Policy_id alloc_policy(size_t size)
{
return _retry([&] () {
return Session_client::alloc_policy(size); });
if (size > _max_arg_size)
warning("attempt to alloc policy larger than ", _max_arg_size, " bytes");

Alloc_policy_result const result = _retry<Alloc_error>([&] {
return call<Rpc_alloc_policy>(min(size, _max_arg_size)); });

return result.convert<Policy_id>(
[&] (Policy_id const id) { return id; },
[&] (Alloc_policy_result) { return Policy_id(); });
}

void trace(Subject_id s, Policy_id p, size_t buffer_size) override
/**
* Request policy-module backing store
*
* \return dataspace capability, or invalid capability if ID does not
* refer to a known policy
*/
Dataspace_capability policy(Policy_id id) { return call<Rpc_policy>(id); }

/**
* Remove a policy module from the TRACE service
*/
void unload_policy(Policy_id id) { call<Rpc_unload_policy>(id); }

/**
* Start tracing of a subject
*/
Trace_result trace(Subject_id s, Policy_id p, size_t buffer_size)
{
_retry([&] () { Session_client::trace(s, p, buffer_size); });
return _retry<Trace_error>([&] () -> Trace_result {
return call<Rpc_trace>(s, p, buffer_size); });
}

size_t subjects(Subject_id *dst, size_t dst_len) override
/**
* Retrieve subject directory
*/
Num_subjects subjects(Subject_id * const dst, Num_subjects const dst_num_subjects)
{
return _retry([&] () {
return Session_client::subjects(dst, dst_len); });
Subjects_result const result = _retry<Alloc_error>([&] {
return call<Rpc_subjects>(); });

return result.convert<Num_subjects>(

[&] (Num_subjects const num_subjects) {
auto const n = min(num_subjects.value, dst_num_subjects.value);
memcpy(dst, _argument_buffer.local_addr<char>(), n*sizeof(Subject_id));
return Num_subjects { n };
},

[&] (Alloc_error) { return Num_subjects { 0 }; });
}

struct For_each_subject_info_result { unsigned count; unsigned limit; };

/**
* Call 'fn' for each trace subject with 'Subject_info' as argument
*/
For_each_subject_info_result for_each_subject_info(auto const &fn)
{
return _retry([&] () {
return Session_client::for_each_subject_info(fn); });
Infos_result const result = _retry<Alloc_error>([&] {
return call<Rpc_subject_infos>(); });

return result.convert<For_each_subject_info_result>(
[&] (Num_subjects const n) -> For_each_subject_info_result {

size_t const subject_bytes = sizeof(Subject_info) + sizeof(Subject_id);

unsigned const max_subjects = unsigned(_argument_buffer.size() / subject_bytes);

Subject_info * const infos = _argument_buffer.local_addr<Subject_info>();
Subject_id * const ids = reinterpret_cast<Subject_id *>(infos + max_subjects);

for (unsigned i = 0; i < n.value; i++)
fn(ids[i], infos[i]);

return { .count = n.value, .limit = max_subjects };
},

[&] (Alloc_error) { return For_each_subject_info_result { }; });
}

/**
* Release subject and free buffers
*
* If the source still exists, the buffers are freed but the subject
* stays intact.
*
* \throw Nonexistent_subject
*/
void free(Subject_id id) { call<Rpc_free>(id); }

/**
* Pause generation of tracing data
*/
void pause(Subject_id id) { call<Rpc_pause>(id); }

/**
* Resume generation of tracing data
*/
void resume(Subject_id id) { call<Rpc_resume>(id); }

/**
* Obtain trace buffer of given subject
*/
Dataspace_capability buffer(Subject_id id) { return call<Rpc_buffer>(id); }
};

#endif /* _INCLUDE__TRACE_SESSION__CONNECTION_H_ */
Loading

0 comments on commit 1f76453

Please sign in to comment.