From e88e3680aac2577a6e9abe4c42eb02ed8a7d52f2 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Thu, 19 Oct 2023 12:29:33 +0200 Subject: [PATCH] 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 --- repos/os/src/lib/genode_c_api/event.cc | 30 +++++++++++------ repos/os/src/lib/genode_c_api/uplink.cc | 36 ++++++++++++++------- repos/os/src/lib/genode_c_api/usb_client.cc | 12 +++++-- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/repos/os/src/lib/genode_c_api/event.cc b/repos/os/src/lib/genode_c_api/event.cc index 7d0861b311..33928b9749 100644 --- a/repos/os/src/lib/genode_c_api/event.cc +++ b/repos/os/src/lib/genode_c_api/event.cc @@ -20,9 +20,20 @@ using namespace Genode; -static Env *_env_ptr; -static Allocator *_alloc_ptr; -static Registry> _event_sessions { }; +struct Statics +{ + Env *env_ptr; + Allocator *alloc_ptr; + Registry> 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(_event_sessions, *_env_ptr, *_alloc_ptr, + return new (*statics().alloc_ptr) + Registered(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); } diff --git a/repos/os/src/lib/genode_c_api/uplink.cc b/repos/os/src/lib/genode_c_api/uplink.cc index fa5169bd86..761abb75aa 100644 --- a/repos/os/src/lib/genode_c_api/uplink.cc +++ b/repos/os/src/lib/genode_c_api/uplink.cc @@ -20,10 +20,21 @@ using namespace Genode; -static Env *_env_ptr; -static Allocator *_alloc_ptr; -static Signal_context_capability _sigh { }; -static Registry> _uplinks { }; +struct Statics +{ + Env *env_ptr; + Allocator *alloc_ptr; + Signal_context_capability sigh { }; + Registry> 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(_uplinks, *_env_ptr, *_alloc_ptr, _sigh, + return new (*statics().alloc_ptr) + Registered(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); } diff --git a/repos/os/src/lib/genode_c_api/usb_client.cc b/repos/os/src/lib/genode_c_api/usb_client.cc index 18015a4649..1af5e68b78 100644 --- a/repos/os/src/lib/genode_c_api/usb_client.cc +++ b/repos/os/src/lib/genode_c_api/usb_client.cc @@ -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 int usb_client_apply(genode_usb_client_handle_t handle, FUNC const &fn) { Usb_id_space::Id id { .value = handle }; try { - _usb_space.apply(id, fn); + usb_space().apply(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(alloc); Allocator *_md_alloc = static_cast(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(); }