Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base API renovation #1832

Closed
nfeske opened this issue Dec 23, 2015 · 5 comments
Closed

Base API renovation #1832

nfeske opened this issue Dec 23, 2015 · 5 comments
Labels

Comments

@nfeske
Copy link
Member

nfeske commented Dec 23, 2015

Genode's base API evolved over the years. When we started in 2006, our mindset was very much influenced by L4, which regarded synchronous IPC as the only mechanism needed. We used to implement components ("servers") in a procedural programming style with a fully synchronous control flow within the component and across components (IPC).

We eventually realized that the restriction to synchronous IPC was misguided. See Section 3.6.2. "Asynchronous notifications" in http://genode.org/documentation/genode-foundations-15-05.pdf for a detailed discussion of the problems. When we started to embrace the use of asynchronous notifications and to disregard blocking RPC between components, we found ourselves designing components as state machines rather than procedural programs. To promote this programming style, we introduced the so-called server API (os/server.h). See https://github.com/genodelabs/genode/blob/master/repos/os/src/server/nic_loopback/main.cc for a canonical example of such a component.

We found that this new style greatly increased the robustness and flexibility of the components. In particular, it completely alleviates race conditions, which constantly troubled us in the past. Now, following the new paradigm, we may end up on a deadlock, but such a situation is easy to debug compared to sporadic race conditions. Over the past two years we have redesigned all Genode session interfaces to avoid blocking RPC. The only remains are the parent and root interfaces, which we still need to address.

Still, the Genode API retained compatibility to the old (= wrong) style of developing components. We should finally clean the API from our past mistakes.

Hereby I propose the following changes:

Removal of side effects

Right now, most components rely on the globally available Genode::env() singleton object for interacting with its environment. When calling a function or method, one never knows for sure if the called code interacts with the env. E.g., we can simply create an instance of Timer::Connection. Under the hood, the Connection object accesses the env to open a timer session at the parent. In the spirit of capability-based security, let us drop the global env. Instead, let us pass all materials that are needed by the called code explicitly to the called code (e.g., by passing a reference to a Parent & as argument. This way, someone inspecting the calling code can immediately see the possible reach of the called code. Another prominent example is the latent use of env()->heap(), which allows any code to arbitrary consume memory. Instead, let us pass an Allocator & to the called code. This way, we re-enforce that library code stays clean from the policy where memory is allocated from. If no Allocator & is passed, we know that no dynamic memory allocation is performed. If an Allocator & is required, the called code needs to explain (in the form of its documentation) why the allocator is actually needed. Moreover, by passing an Allocator_guard, the calling code can impose a limit of the memory consumption on the called code.

Granted, the explicit passing of such arguments may lead to slightly more verbose code. But in my opinion, this inconvenience is greatly outweighed by the benefits of alleviating side effects. Furthermore, I think that the inconvenience isn't actually increasing much in practice, thanks to C++11-style member initializers.

Component API

Traditionally, components started their execution at a main function because, well, this is how it's supposed to be, right? The program exits as soon as main returns. With the introduction of the server API (http://genode.org/documentation/release-notes/13.11#New_server_API), I experimented with different approach: The execution of a component starts at a construct function that takes a form of the Genode environment as argument. The function is expected to initialize the component. Upon completion of the initialization, the function returns. Now, the component is ready to respond to incoming RPC requests or signals. Each time such a request/signal comes in, a handler is executed. The handler applies the component-internal state changes and returns immediately. No blocking call is performed. We have essentially a state machine.

Over the past two years, we have applied this new approach to all new components - to a great success. So it is time to promote this API to become Genode's base API. The major benefits are:

  • Servers will become easier to develop as the API is much simpler. Previously, a server had to manually create a CAP connection and an RPC entrypoint. Now, each component has an entrypoint.
  • Signals and RPC requests are handled in the context of the same thread, which alleviates the need for locking as long as the component is single threaded, which is actually the case for most components.
  • The notion of Thread, Signal_receiver, Rpc_entrypoint are no longer needed by the developer of a component. There is simply an Entrypoint, which is able to handle both RPC requests and signals.

Shunning pointers

The Genode API has still a lot of places where pointers are taken as arguments or exposed from objects. We didn't know better when we started with Genode. Now we do. So let us clean up the API in this respect. Just a simple example, right now Heap takes an RM-session pointer and an RAM-session pointer as arguments. These should be references. Pointers should be used only in situation where a nullptr is a reasonable argument, or when dealing with string literals as char const *.

@nfeske nfeske added the cleanup label Dec 23, 2015
nfeske added a commit to nfeske/genode that referenced this issue Dec 23, 2015
This commit introduces the new `Component` interface in the form of the
headers base/component.h and base/entrypoint.h. The os/server.h API
has become merely a compatibilty wrapper and will eventually be removed.
The same holds true for os/signal_rpc_dispatcher.h. The mechanism has
moved to base/signal.h and is now called 'Signal_handler'.

This patch has been tested on base-linux, base-okl4, base-hw, base-nova,
and base-sel4.

Since the patch shuffles headers around, please do a 'make clean' in the
build directory.

Note that this patch changes the default behavior of components. Each
component opens a CAP and SIGNAL session during startup in order to
create the component's 'Entrypoint'. So we have to make sure to adjust
the session routing policies correspondingly. I did this for the
printf.run script but other run scripts may be affected as well.

Issue genodelabs#1832
@nfeske
Copy link
Member Author

nfeske commented Dec 23, 2015

As a first step, 1ca0676 introduces the Component and Entrypoint interfaces. See the commit message for more information.

nfeske added a commit to nfeske/genode that referenced this issue Jan 14, 2016
nfeske added a commit to nfeske/genode that referenced this issue Jan 20, 2016
With this patch, the platform differences reside solely in the
implementation of the base library.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 20, 2016
This patch establishes a common organization of header files
internal to the base framework. The internal headers are located at
'<repository>/src/include/base/internal/'. This structure has been
choosen to make the nature of those headers immediately clear when
included:

  #include <base/internal/lock_helper.h>

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 22, 2016
Those headers remained unused outside the internal framework. So it is
better to remove them from the public API.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 22, 2016
By moving the stub implementation to rm_session_client.cc, we can use
the generic base/include/rm_session/client.h for base-linux and
base-nova and merely use platform-specific implementations.

Issue genodelabs#1832

rm session client nova
nfeske added a commit to nfeske/genode that referenced this issue Jan 25, 2016
By moving the stub implementation to rm_session_client.cc, we can use
the generic base/include/rm_session/client.h for base-linux and
base-nova and merely use platform-specific implementations.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 25, 2016
On seL4 and L4/Fiasco, we employ a simple yielding spinlock as lock
implementation. Consequently these base platforms used to have a
simplified header. However, since the regular cancelable_lock has all
the member variables needed to implement a spinlock, we can simply use
the generic header on those two platforms too, just leaving some other
parts of the generic header unused. So at API level, the difference is
not visible.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 25, 2016
nfeske added a commit to nfeske/genode that referenced this issue Jan 25, 2016
The interfaces linux_cpu_session, local_capability, linux_dataspace,
linux_native_pd are mere implementation necessities. They are meant for the
internal use by the framework only. So it is appropriate to move them to
base/internal/.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 25, 2016
This patch moves details about the stack allocation and organization
the base-internal headers. Thereby, I replaced the notion of "thread
contexts" by "stacks" as this term is much more intuitive. The fact that
we place thread-specific information at the bottom of the stack is not
worth introducing new terminology.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 28, 2016
nfeske added a commit to nfeske/genode that referenced this issue Jan 28, 2016
This patch moves those definitions from the Genode API header
(native_types.h) to foc/cap_selectors.h and base/internal/utcb_regs.h.
The former needs to stay at a publicly accessible location because
it is needed by L4Linux. By placing it in a 'foc/' subdirectory, we
distinguish it from the Genode API.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 28, 2016
Since the ASSERT macro is Fiasco.OC-specific, this patch moves it to a
Fiasco.OC-specific place (foc/assert.h) and prefixes it with "FOC_".

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Jan 28, 2016
This patch prepares the unification of the capability types across the
various base platforms. The template that is used on most traditional
(non-capability) kernels has been moved to native_types_tpl.h for now.
Once all platforms use the new type (which will resemble the definition
currently used on base-sel4), we will remove the template.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
This commit introduces the new `Component` interface in the form of the
headers base/component.h and base/entrypoint.h. The os/server.h API
has become merely a compatibilty wrapper and will eventually be removed.
The same holds true for os/signal_rpc_dispatcher.h. The mechanism has
moved to base/signal.h and is now called 'Signal_handler'.

This patch has been tested on base-linux, base-okl4, base-hw, base-nova,
and base-sel4.

Since the patch shuffles headers around, please do a 'make clean' in the
build directory.

Note that this patch changes the default behavior of components. Each
component opens a CAP and SIGNAL session during startup in order to
create the component's 'Entrypoint'. So we have to make sure to adjust
the session routing policies correspondingly. I did this for the
printf.run script but other run scripts may be affected as well.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
With this patch, the platform differences reside solely in the
implementation of the base library.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
This patch establishes a common organization of header files
internal to the base framework. The internal headers are located at
'<repository>/src/include/base/internal/'. This structure has been
choosen to make the nature of those headers immediately clear when
included:

  #include <base/internal/lock_helper.h>

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
Those headers remained unused outside the internal framework. So it is
better to remove them from the public API.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
By moving the stub implementation to rm_session_client.cc, we can use
the generic base/include/rm_session/client.h for base-linux and
base-nova and merely use platform-specific implementations.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
On seL4 and L4/Fiasco, we employ a simple yielding spinlock as lock
implementation. Consequently these base platforms used to have a
simplified header. However, since the regular cancelable_lock has all
the member variables needed to implement a spinlock, we can simply use
the generic header on those two platforms too, just leaving some other
parts of the generic header unused. So at API level, the difference is
not visible.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
The interfaces linux_cpu_session, local_capability, linux_dataspace,
linux_native_pd are mere implementation necessities. They are meant for the
internal use by the framework only. So it is appropriate to move them to
base/internal/.

Issue genodelabs#1832
chelmuth pushed a commit to chelmuth/genode that referenced this issue Mar 1, 2016
This patch moves details about the stack allocation and organization
the base-internal headers. Thereby, I replaced the notion of "thread
contexts" by "stacks" as this term is much more intuitive. The fact that
we place thread-specific information at the bottom of the stack is not
worth introducing new terminology.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Mar 2, 2016
With this patch, the platform differences reside solely in the
implementation of the base library.

Issue genodelabs#1832
nfeske added a commit to nfeske/genode that referenced this issue Mar 2, 2016
This patch establishes a common organization of header files
internal to the base framework. The internal headers are located at
'<repository>/src/include/base/internal/'. This structure has been
choosen to make the nature of those headers immediately clear when
included:

  #include <base/internal/lock_helper.h>

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
This patch removes the support for executing subsystems of CLI monitor
within the GDB monitor. There are multiple reasons: First, the feature
remained unused for multiple years. Second, it relied on the base/elf.h
header to determine whether the started binary is dynamically or
statically linked. This header, however, is going to be removed from the
Genode API. Third, the feature will eventually break with the upcoming
changes of how components are bootstrapped. Finally, there is the plan
to turn CLI monitor into a sole front end of a dynamically configurable
init component. Once we pursue this plan, we'd need to reconsider the
GDB support anyway.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
With this patch, the platform differences reside solely in the
implementation of the base library.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
This patch establishes a common organization of header files
internal to the base framework. The internal headers are located at
'<repository>/src/include/base/internal/'. This structure has been
choosen to make the nature of those headers immediately clear when
included:

  #include <base/internal/lock_helper.h>

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
Those headers remained unused outside the internal framework. So it is
better to remove them from the public API.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
By moving the stub implementation to rm_session_client.cc, we can use
the generic base/include/rm_session/client.h for base-linux and
base-nova and merely use platform-specific implementations.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
On seL4 and L4/Fiasco, we employ a simple yielding spinlock as lock
implementation. Consequently these base platforms used to have a
simplified header. However, since the regular cancelable_lock has all
the member variables needed to implement a spinlock, we can simply use
the generic header on those two platforms too, just leaving some other
parts of the generic header unused. So at API level, the difference is
not visible.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
The interfaces linux_cpu_session, local_capability, linux_dataspace,
linux_native_pd are mere implementation necessities. They are meant for the
internal use by the framework only. So it is appropriate to move them to
base/internal/.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
This patch moves details about the stack allocation and organization
the base-internal headers. Thereby, I replaced the notion of "thread
contexts" by "stacks" as this term is much more intuitive. The fact that
we place thread-specific information at the bottom of the stack is not
worth introducing new terminology.

Issue genodelabs#1832
ehmry pushed a commit to ehmry/genode that referenced this issue Apr 22, 2016
This commit moves the parameters of the stack area to the base-internal
header 'stack_area.h'.

Issue genodelabs#1832
chelmuth pushed a commit that referenced this issue Apr 25, 2016
Besides unifying the Msgbuf_base classes across all platforms, this
patch merges the Ipc_marshaller functionality into Msgbuf_base, which
leads to several further simplifications. For example, this patch
eventually moves the Native_connection_state and removes all state
from the former Ipc_server to the actual server loop, which not only
makes the flow of control and information much more obvious, but is
also more flexible. I.e., on NOVA, we don't even have the notion of
reply-and-wait. Now, we are no longer forced to pretend otherwise.

Issue #1832
nfeske added a commit to nfeske/genode that referenced this issue Apr 27, 2016
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.

Issue genodelabs#1832
cproc pushed a commit to cproc/genode that referenced this issue Apr 28, 2016
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.

Issue genodelabs#1832
cproc pushed a commit to cproc/genode that referenced this issue Apr 28, 2016
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.

Issue genodelabs#1832
nfeske added a commit that referenced this issue Apr 29, 2016
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.

Issue #1832
chelmuth pushed a commit that referenced this issue May 9, 2016
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.

Issue #1832
nfeske added a commit that referenced this issue Jan 21, 2017
This file is unused since the commit "CLI monitor: remove unused GDB
command".

Issue #1832
chelmuth pushed a commit that referenced this issue Jan 23, 2017
This file is unused since the commit "CLI monitor: remove unused GDB
command".

Issue #1832
nfeske added a commit that referenced this issue Jan 31, 2017
This file is unused since the commit "CLI monitor: remove unused GDB
command".

Issue #1832
ssumpf added a commit to ssumpf/genode that referenced this issue Feb 23, 2017
ssumpf added a commit to ssumpf/genode that referenced this issue Feb 23, 2017
ssumpf added a commit to ssumpf/genode that referenced this issue Feb 23, 2017
@ssumpf
Copy link
Member

ssumpf commented Feb 23, 2017

@nfeske: Please move 639cb88, 20d1ecd, and 3b383c3 to staging.

@nfeske
Copy link
Member Author

nfeske commented Dec 13, 2017

The revised API is now in use for more than a year. We can rest the case.

@nfeske nfeske closed this as completed Dec 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants