genode_c_api: remove global-static constructors

The execution of global-static constructors in Genode is optional for
native components or determined in the libc for libc components. By
convention, we avoid static constructors wherever possible but in rare
cases the component can tweak the point when constructors are executed
and initialize an environment beforehand. The wifi_drv applies this
pattern for the uplink initialization, but is a libc component on the
other hand, and, thus, statics in the Genode C API for uplink are
constructed later by the libc. So, the prior initialization is reverted,
i.e. the signal-handler capability becomes invalid.

This addresses a regression exposed by the following commit.

  drivers/wifi: perform multi-staged construction

Related to #3509
Fixes #5024
This commit is contained in:
Christian Helmuth 2023-10-19 12:29:33 +02:00
parent 0a001443e9
commit e88e3680aa
3 changed files with 54 additions and 24 deletions

View File

@ -20,9 +20,20 @@
using namespace Genode;
static Env *_env_ptr;
static Allocator *_alloc_ptr;
static Registry<Registered<genode_event>> _event_sessions { };
struct Statics
{
Env *env_ptr;
Allocator *alloc_ptr;
Registry<Registered<genode_event>> event_sessions { };
};
static Statics & statics()
{
static Statics instance { };
return instance;
};
struct genode_event : private Noncopyable, private Interface
@ -56,8 +67,8 @@ struct genode_event : private Noncopyable, private Interface
void genode_event_init(genode_env *env_ptr,
genode_allocator *alloc_ptr)
{
_env_ptr = env_ptr;
_alloc_ptr = alloc_ptr;
statics().env_ptr = env_ptr;
statics().alloc_ptr = alloc_ptr;
}
@ -146,18 +157,19 @@ void genode_event_generate(struct genode_event *event_session,
struct genode_event *genode_event_create(struct genode_event_args const *args)
{
if (!_env_ptr || !_alloc_ptr) {
if (!statics().env_ptr || !statics().alloc_ptr) {
error("genode_event_create: missing call of genode_event_init");
return nullptr;
}
return new (*_alloc_ptr)
Registered<genode_event>(_event_sessions, *_env_ptr, *_alloc_ptr,
return new (*statics().alloc_ptr)
Registered<genode_event>(statics().event_sessions,
*statics().env_ptr, *statics().alloc_ptr,
Session_label(args->label));
}
void genode_event_destroy(struct genode_event *event_ptr)
{
destroy(*_alloc_ptr, event_ptr);
destroy(*statics().alloc_ptr, event_ptr);
}

View File

@ -20,10 +20,21 @@
using namespace Genode;
static Env *_env_ptr;
static Allocator *_alloc_ptr;
static Signal_context_capability _sigh { };
static Registry<Registered<genode_uplink>> _uplinks { };
struct Statics
{
Env *env_ptr;
Allocator *alloc_ptr;
Signal_context_capability sigh { };
Registry<Registered<genode_uplink>> uplinks { };
};
static Statics & statics()
{
static Statics instance { };
return instance;
};
struct genode_uplink : private Noncopyable, private Interface
@ -177,15 +188,15 @@ void genode_uplink_init(genode_env *env_ptr,
genode_allocator *alloc_ptr,
genode_signal_handler *sigh_ptr)
{
_env_ptr = env_ptr;
_alloc_ptr = alloc_ptr;
_sigh = cap(sigh_ptr);
statics().env_ptr = env_ptr;
statics().alloc_ptr = alloc_ptr;
statics().sigh = cap(sigh_ptr);
}
void genode_uplink_notify_peers()
{
_uplinks.for_each([&] (genode_uplink &uplink) {
statics().uplinks.for_each([&] (genode_uplink &uplink) {
uplink.notify_peer(); });
}
@ -210,7 +221,7 @@ bool genode_uplink_rx(struct genode_uplink *uplink_ptr,
struct genode_uplink *genode_uplink_create(struct genode_uplink_args const *args)
{
if (!_env_ptr || !_alloc_ptr) {
if (!statics().env_ptr || !statics().alloc_ptr) {
error("genode_uplink_create: missing call of genode_uplink_init");
return nullptr;
}
@ -219,13 +230,14 @@ struct genode_uplink *genode_uplink_create(struct genode_uplink_args const *args
for (unsigned i = 0; i < sizeof(args->mac_address); i++)
mac.addr[i] = args->mac_address[i];
return new (*_alloc_ptr)
Registered<genode_uplink>(_uplinks, *_env_ptr, *_alloc_ptr, _sigh,
return new (*statics().alloc_ptr)
Registered<genode_uplink>(statics().uplinks, *statics().env_ptr,
*statics().alloc_ptr, statics().sigh,
mac, Session_label(args->label));
}
void genode_uplink_destroy(struct genode_uplink *uplink_ptr)
{
destroy(*_alloc_ptr, uplink_ptr);
destroy(*statics().alloc_ptr, uplink_ptr);
}

View File

@ -127,14 +127,20 @@ struct Usb_client : Usb::Connection
};
static Usb_id_space _usb_space { };
static Usb_id_space & usb_space()
{
static Usb_id_space instance { };
return instance;
}
template <typename FUNC>
int usb_client_apply(genode_usb_client_handle_t handle, FUNC const &fn)
{
Usb_id_space::Id id { .value = handle };
try {
_usb_space.apply<Usb_client>(id, fn);
usb_space().apply<Usb_client>(id, fn);
} catch (Usb_id_space::Id_space::Unknown_id) {
error("Invalid handle: ", handle);
return -1;
@ -154,7 +160,7 @@ genode_usb_client_create(struct genode_env *env,
Range_allocator *_alloc = static_cast<Range_allocator*>(alloc);
Allocator *_md_alloc = static_cast<Allocator *>(md_alloc);
Usb_client *client = new (_md_alloc) Usb_client(_env, _usb_space, label,
Usb_client *client = new (_md_alloc) Usb_client(_env, usb_space(), label,
_alloc, cap(handler));
return client->handle();
}