diff --git a/repos/hello_tutorial/README b/repos/hello_tutorial/README index 1e1639cb4d..0b90a254da 100644 --- a/repos/hello_tutorial/README +++ b/repos/hello_tutorial/README @@ -1,2 +1,2 @@ -This repository contains the source code of the 'Hello' client-server tutorial -written by Björn Döbel. Please find the document at 'doc/hello_tutorial.txt'. +This repository contains the source code of a simple client-server scenario +using Genode's RPC mechanism. diff --git a/repos/hello_tutorial/config/config b/repos/hello_tutorial/config/config deleted file mode 100644 index 67def090a4..0000000000 --- a/repos/hello_tutorial/config/config +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/hello_tutorial/doc/hello_tutorial.txt b/repos/hello_tutorial/doc/hello_tutorial.txt index 75d391fb49..99b2c44a01 100644 --- a/repos/hello_tutorial/doc/hello_tutorial.txt +++ b/repos/hello_tutorial/doc/hello_tutorial.txt @@ -1,32 +1,25 @@ - Creating your first Genode application + A simple client-server scenario - Björn Döbel and Norman Feske + Björn Döbel and Norman Feske Abstract ######## -This section will give you a step-by-step introduction for writing your first -little client-server application using the Genode OS Framework. We will create +This tutorial will give you a step-by-step introduction for creating your first +little client-server application scenario using the Genode OS Framework. We will create a server that provides two functions to its clients and a client that uses these functions. The code samples in this section are not necessarily complete. -You can download the complete tutorial source code from the link at the bottom -of this page. +You can can find the complete source code at the _repos/hello_tutorial_ +directory within Genode's source tree. Prerequisites ############# -We assume that you know how to write code and have read: - -Norman Feske and Christian Helmuth: -"Design of the Genode OS Architecture", -_TU Dresden technical report TUD-FI06-07, Dresden, Germany, December 2006_. - -[http://genode-labs.com/publications/bastei-design-2006.pdf] - -so that you have a basic understanding of what Genode is and how things work. -Of course, you will also need to check out Genode before going any further. +We assume that you have acquainted yourself with the basic concepts of +Genode and have read the "Getting started" section of the Genode Foundations +book. Our can download the book from [http://genode.org]. Setting up the build environment @@ -46,16 +39,16 @@ following subdirectory structure: ! hello_tutorial/src/hello/client In the remaining document when referring to non-absolute directories, these are -local to 'hello_tutorial'. -Now we tell the Genode build system, that there is a new repository. Therefore -we add the path to our new repository to 'build/etc/build.conf': +local to _hello_tutorial_. +Now we tell the Genode build system that there is a new repository. Therefore +we add the path to our new repository to _build/etc/build.conf_: ! REPOSITORIES += /path/to/your/hello_tutorial -Later we will place build description files into the tutorial subdirectories so -that the build system can figure out what is needed to build your applications. -You can then build these apps from the 'build' directory using one of the -following commands: +Later we will place build description files into the tutorial subdirectories +so that the build system can figure out what is needed to build your custom +components. You can then build these components from the _build_ directory +using one of the following commands: ! make hello ! make hello/server @@ -67,8 +60,8 @@ commands build only the specific target respectively. Defining an interface ##################### -In our example we are going to implement a server providing two functions: -:'void say_hello()': makes the server print "Hello world." +In our example, we are going to implement a server providing two functions: +:'void say_hello()': makes the server print a message, and :'int add(int a, int b)': adds two integers and returns the result. The interface of a Genode service is called a _session_. We will define it as a @@ -77,36 +70,35 @@ C++ class in 'include/hello_session/hello_session.h' !#include !#include ! -!namespace Hello { +!namespace Hello { struct Session; } ! -! struct Session : public Genode::Session -! { -! static const char *service_name() { return "Hello"; } +!struct Hello::Session : Genode::Session +!{ +! static const char *service_name() { return "Hello"; } ! -! virtual void say_hello() = 0; -! virtual int add(int a, int b) = 0; +! virtual void say_hello() = 0; +! virtual int add(int a, int b) = 0; ! -! GENODE_RPC(Rpc_say_hello, void, say_hello); -! GENODE_RPC(Rpc_add, int, add, int, int); -! GENODE_RPC_INTERFACE(Rpc_say_hello, Rpc_add); -! }; -!} +! GENODE_RPC(Rpc_say_hello, void, say_hello); +! GENODE_RPC(Rpc_add, int, add, int, int); +! GENODE_RPC_INTERFACE(Rpc_say_hello, Rpc_add); +!}; As a good practice, we place the Hello service into a dedicated namespace. The _Hello::Session_ class defines the public interface for our service as well as the meta information that Genode needs to perform remote procedure calls (RPC) -accross process boundaries. -Furthermore, we use the interface to specify the name of the -service by using the 'service_name' function. This function will later -be used by both the server for announcing the service at its parent and -the client for requesting the creation of a "Hello" session. +across component boundaries. +Furthermore, we use the interface to specify the name of the service by +providing the 'service_name' method. This method will later be used by both +the server for announcing the service at its parent and the client for +requesting the creation of a "Hello" session. The 'GENODE_RPC' macro is used to declare an RPC function. Its first argument is a type name that is used to refer to the RPC function. The type name can -be choosen freely. However, it is a good practice to prefix the type name +be chosen freely. However, it is a good practice to prefix the type name with 'Rpc_'. The remaining arguments are the return type of the RPC function, the server-side name of the RPC implementation, and the function arguments. -The 'GENODE_RPC_INTERFACE' macros declares the list of RPC functions that the +The 'GENODE_RPC_INTERFACE' macro declares the list of RPC functions that the RPC interface is comprised of. Under the hood, the 'GENODE_RPC*' macros enrich the compound class with the type information used to automatically generate the RPC communication code at compile time. They do not add any members to the @@ -129,21 +121,20 @@ instantiating this template class with the session interface as argument, the 'Session_component' class gets equipped with the communication code that will make the server's functions accessible via RPC. -!#include +!#include !#include !#include ! -!namespace Hello { +!namespace Hello { struct Session_component; } ! -! struct Session_component : Genode::Rpc_object -! { -! void say_hello() { -! PDBG("I am here... Hello."); } +!struct Hello::Session_component : Genode::Rpc_object +!{ +! void say_hello() { +! Genode::log("I am here... Hello."); } ! -! int add(int a, int b) { -! return a + b; } -! }; -!} +! int add(int a, int b) { +! return a + b; } +!}; Getting ready to start @@ -157,82 +148,80 @@ application. Starting a service with Genode works as follows: client to communicate with the server. The class 'Hello::Root_component' is derived from Genode's 'Root_component' -class template. This class defines a '_create_session' method which is called +class template. This class defines a '_create_session' method, which is called each time a client wants to establish a connection to the server. This function is responsible for parsing the parameter string the client hands over to the -server and creating a 'Hello::Session_component' object from these parameters. +server and for creating a 'Hello::Session_component' object from these +parameters. -!#include +!#include !#include ! -!namespace Hello { +!namespace Hello { class Root_component; } ! -! class Root_component : public Genode::Root_component -! { -! protected: -! -! Session_component *_create_session(const char *args) -! { -! PDBG("creating hello session."); -! return new (md_alloc()) Session_component(); -! } -! -! public: -! -! Root_component(Genode::Rpc_entrypoint *ep, -! Genode::Allocator *allocator) -! : Genode::Root_component(ep, allocator) -! { -! PDBG("Creating root component."); -! } -! }; -!} - -Now we only need a main method that announces the service to our parent: - -!#include -!#include -! -!using namespace Genode; -! -!int main(void) +!class Hello::Root_component +!: +! public Genode::Root_component !{ -! /* -! * Get a session for the parent's capability service, so that we -! * are able to create capabilities. -! */ -! Cap_connection cap; +! protected: ! -! /* -! * A sliced heap is used for allocating session objects - thereby we -! * can release objects separately. -! */ -! static Sliced_heap sliced_heap(env()->ram_session(), -! env()->rm_session()); +! Session_component *_create_session(const char *args) +! { +! Genode::log("creating hello session"); +! return new (md_alloc()) Session_component(); +! } ! -! /* -! * Create objects for use by the framework. -! * -! * An 'Rpc_entrypoint' is created to announce our service's root -! * capability to our parent, manage incoming session creation -! * requests, and dispatch the session interface. The incoming RPC -! * requests are dispatched via a dedicated thread. The 'STACK_SIZE' -! * argument defines the size of the thread's stack. The additional -! * string argument is the name of the entry point, used for -! * debugging purposes only. -! */ -! enum { STACK_SIZE = 4096 }; -! static Rpc_entrypoint ep(&cap, STACK_SIZE, "hello_ep"); +! public: ! -! static Hello::Root_component hello_root(&ep, &sliced_heap); -! env()->parent()->announce(ep.manage(&hello_root)); +! Root_component(Genode::Entrypoint &ep, +! Genode::Allocator &alloc) +! : +! Genode::Root_component(ep, alloc) +! { +! Genode::log("creating root component"); +! } +!}; + +Now we only need the actual application code that instantiates the root +component and the service to our parent. It is good practice to represent +the applications as a class called 'Main' with its constructor taking the +component's environment as argument. + +!#include ! -! /* -! * We are done with this and only act upon client requests now. -! */ -! sleep_forever(); +!namespace Hello { struct Main; } ! -! return 0; +!struct Hello::Main +!{ +! Genode::Env &env; +! +! Genode::Sliced_heap sliced_heap { env.ram(), env.rm() }; +! +! Hello::Root_component root { env.ep(), sliced_heap }; +! +! Main(Genode::Env &env) : env(env) +! { +! env.parent().announce(env.ep().manage(root)); +! } +!}; + +The sliced heap is used for the dynamic allocation of session objects. +It interacts with the component's RAM session to obtain the backing store +for the allocations, and the component's region map to make +backing store visible within its virtual address space. + +The announcement of the service is performed by the body of the constructor by +creating a capability for the root component as return value of the 'manage' +method, and passing this capability to the parent. + +The 'Component::construct' function of the hello server simply constructs a singleton +instance of 'Hello::Main' as a _static_ local variable. + +!Genode::size_t Component::stack_size() { return 64*1024; } +! +!void Component::construct(Genode::Env &env) +!{ +! static Hello::Main main(env); !} @@ -248,13 +237,12 @@ create a 'target.mk' file in 'src/hello/server': ! SRC_CC = main.cc ! LIBS = base -To tell the init process to start the new program, we have to add a '' +To tell the init component to start the new program, we have to add a '' entry to init's 'config' file, which is located at 'build/bin/config'. ! ! ! -! ! ! ! @@ -265,53 +253,51 @@ entry to init's 'config' file, which is located at 'build/bin/config'. ! ! -For information about the configuring the init process, please refer -to [http://genode.org/documentation/developer-resources/init]. - -Now rebuild 'core', 'init', and 'hello/server', go to 'build/bin', run './core'. +For information about the configuring concept, please refer to the +"System configuration" section of the Genode Foundations book. Writing client code ################### -In the next part we are going to have a look at the client-side implementation. +In the next part, we are going to have a look at the client-side implementation. The most basic steps here are: -* Get a capability for the "Hello" service from our parent +* Obtain a capability for the "Hello" service from our parent * Invoke RPCs via the obtained capability A client object =============== -We will encapsulate the Genode IPC interface in a 'Hello::Session_client' class. +We will encapsulate the Genode RPC interface in a 'Hello::Session_client' class. This class derives from 'Hello:Session' and implements a client-side object. Therefore edit 'include/hello_session/client.h': !#include !#include -!#include +!#include ! -!namespace Hello { +!namespace Hello { struct Session_client; } ! -! struct Session_client : Genode::Rpc_client +! +!struct Hello::Session_client : Genode::Rpc_client +!{ +! Session_client(Genode::Capability cap) +! : Genode::Rpc_client(cap) { } +! +! void say_hello() ! { -! Session_client(Genode::Capability cap) -! : Genode::Rpc_client(cap) { } +! Genode::log("issue RPC for saying hello"); +! call(); +! Genode::log("returned from 'say_hello' RPC call"); +! } ! -! void say_hello() -! { -! PDBG("Saying Hello."); -! call(); -! } -! -! int add(int a, int b) -! { -! return call(a, b); -! } -! }; -!} - +! int add(int a, int b) +! { +! return call(a, b); +! } +!}; A 'Hello::Session_client' object takes a 'Capability' as constructor argument. This capability is tagged with the session type and gets passed to the @@ -320,51 +306,26 @@ code via the 'call' template function. The template argument for 'call' is the RPC type as declared in the session interface. -Client implementation -===================== +A connection object +=================== -The client-side implementation using the 'Hello::Session_client' object is pretty -straightforward. We request a capability for the Hello service from our parent. -This call blocks as long as the service has not been registered at the parent. -Afterwards, we create a 'Hello::Session_client' object with it and invoke calls. In -addition, we use the Timer service that comes with Genode. This server -enables us to sleep for a certain amount of milliseconds. +Whereas the 'Hello::Session_client' is able to perform RPC calls to an RPC +object when given a capability for such an object, the question of how +the client obtains this capability is still open. +Here, the so-called connection object enters the picture. A connection +object has the purposes: -Put this code into 'src/hello/client/main.cc': +* It transforms session-specific parameters into a format that can be + passed to the server along with the session request. The connection + object thereby hides the details of how the session parameters are + represented "on the wire". -!#include -!#include -!#include -!#include -! -!using namespace Genode; -! -!int main(void) -!{ -! Capability h_cap = -! env()->parent()->session("foo, ram_quota=4K"); -! -! Hello::Session_client h(h_cap); -! -! Timer::Connection timer; -! -! while (1) { -! h.say_hello(); -! timer.msleep(1000); -! -! int foo = h.add(2,5); -! PDBG("Added 2 + 5 = %d", foo); -! timer.msleep(1000); -! } -! -! return 0; -!} +* It issues a session request to the parent and retrieves a session + capability as response. + +* It acts as a session-client object such that the session's RPC functions + can directly be called on the connection object. -Compared to the creation of the Timer session, the creation of "Hello" session -looks rather inconvenient and takes multiple lines of code. For this reason, it -is a good practice to supply a convenience wrapper for creating sessions as -used for the timer session. This wrapper is also the right place to for -documenting session-construction arguments and assembling the argument string. By convention, the wrapper is called 'connection.h' and placed in the directory of the session interface. For our case, the file 'include/hello_session/connection.h' looks like this: @@ -372,27 +333,44 @@ of the session interface. For our case, the file !#include !#include ! -!namespace Hello { +!namespace Hello { struct Connection; } ! -! struct Connection : Genode::Connection, Session_client -! { -! Connection() -! : -! /* create session */ -! Genode::Connection(session("foo, ram_quota=4K")), +!struct Hello::Connection : Genode::Connection, Session_client +!{ +! Connection(Genode::Env &env) +! : +! /* create session */ +! Genode::Connection(env, session(env.parent(), +! "ram_quota=4K")), +! /* initialize RPC interface */ +! Session_client(cap()) { } +!}; + + +Client implementation +===================== + +The client-side implementation using the 'Hello::Connection' object is pretty +straightforward. Put this code into 'src/hello/client/main.cc': + +!#include +!#include +!#include ! -! /* initialize RPC interface */ -! Session_client(cap()) { } -! }; +!Genode::size_t Component::stack_size() { return 64*1024; } +! +!void Component::construct(Genode::Env &env) +!{ +! Hello::Connection hello(env); +! +! hello.say_hello(); +! +! int const sum = hello.add(2, 5); +! Genode::log("added 2 + 5 = ", sum); +! +! Genode::log("hello test completed"); !} -With the 'Connection' class in place, we can now use Hello sessions -by just instantiating 'Hello::Connection' objects and invoke -functions directly on such an object. For example: - -!Hello::Connection hello; -!int foo = hello.add(2, 5); - Ready, set, go... ================= @@ -403,19 +381,56 @@ Add a 'target.mk' file with the following content to 'src/hello/client/': ! SRC_CC = main.cc ! LIBS = base -Extend your 'config' file as follows. +Extend your init _config_ as follows to also start the hello-client component: -# Add start entries for 'Timer' service and hello client: +! +! +! - ! - ! - ! - ! - ! - ! - ! -Build 'drivers/timer', and 'hello/client', go to 'build/bin', and run './core' -again. You have now successfully implemented your first Genode client-server -scenario. +Creating a run script to automate your work flow +================================================ +The procedure of building, configuring, integrating, and executing Genode +system scenarios across different kernels can be automated using a run +script, which can be executed directly from within your build directory. +A run script for the hello client-server scenario should be placed +at the _run/hello.run_ and look as follows: + +!build { core init hello } +! +!create_boot_directory +! +!install_config { +! +! +! +! +! +! +! +! +! +! +! +! +! +! +!} +! +!build_boot_image { core init hello_client hello_server } +! +!append qemu_args " -nographic " +! +!run_genode_until "hello test completed.*\n" 10 + +When executed via 'make run/hello', it performs the given steps in sequence. +Note that the run script is kernel-agnostic. Hence, you can execute the system +scenario on all the different kernels supported by Genode without any +modification. The regular expression specified to the 'run_genode_until' step +is used as pattern for detecting the success of the step. If the log output +produced by the scenario matches the pattern, the run script completes +successfully. If the pattern does not appear within the specified time (in +this example ten seconds), the run script aborts with an error. By creating +the run script, we have not just automated our work flow but have actually +created an automated test case for our components. diff --git a/repos/hello_tutorial/include/hello_session/client.h b/repos/hello_tutorial/include/hello_session/client.h index 2415cd41e7..2165836aab 100644 --- a/repos/hello_tutorial/include/hello_session/client.h +++ b/repos/hello_tutorial/include/hello_session/client.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2008-2013 Genode Labs GmbH + * Copyright (C) 2008-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -16,26 +16,27 @@ #include #include -#include +#include -namespace Hello { +namespace Hello { struct Session_client; } - struct Session_client : Genode::Rpc_client + +struct Hello::Session_client : Genode::Rpc_client +{ + Session_client(Genode::Capability cap) + : Genode::Rpc_client(cap) { } + + void say_hello() { - Session_client(Genode::Capability cap) - : Genode::Rpc_client(cap) { } + Genode::log("issue RPC for saying hello"); + call(); + Genode::log("returned from 'say_hello' RPC call"); + } - void say_hello() - { - PDBG("Saying Hello."); - call(); - } - - int add(int a, int b) - { - return call(a, b); - } - }; -} + int add(int a, int b) + { + return call(a, b); + } +}; #endif /* _INCLUDE__HELLO_SESSION_H__CLIENT_H_ */ diff --git a/repos/hello_tutorial/include/hello_session/connection.h b/repos/hello_tutorial/include/hello_session/connection.h index 364444392f..dffb9a3934 100644 --- a/repos/hello_tutorial/include/hello_session/connection.h +++ b/repos/hello_tutorial/include/hello_session/connection.h @@ -17,18 +17,19 @@ #include #include -namespace Hello { +namespace Hello { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection() - : - /* create session */ - Genode::Connection(session("foo, ram_quota=4K")), - /* initialize RPC interface */ - Session_client(cap()) { } - }; -} +struct Hello::Connection : Genode::Connection, Session_client +{ + Connection(Genode::Env &env) + : + /* create session */ + Genode::Connection(env, session(env.parent(), + "ram_quota=4K")), + + /* initialize RPC interface */ + Session_client(cap()) { } +}; #endif /* _INCLUDE__HELLO_SESSION__CONNECTION_H_ */ diff --git a/repos/hello_tutorial/include/hello_session/hello_session.h b/repos/hello_tutorial/include/hello_session/hello_session.h index 63f27bb112..a50b19ea10 100644 --- a/repos/hello_tutorial/include/hello_session/hello_session.h +++ b/repos/hello_tutorial/include/hello_session/hello_session.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2008-2013 Genode Labs GmbH + * Copyright (C) 2008-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -17,25 +17,25 @@ #include #include -namespace Hello { - - struct Session : Genode::Session - { - static const char *service_name() { return "Hello"; } - - virtual void say_hello() = 0; - virtual int add(int a, int b) = 0; +namespace Hello { struct Session; } - /******************* - ** RPC interface ** - *******************/ +struct Hello::Session : Genode::Session +{ + static const char *service_name() { return "Hello"; } - GENODE_RPC(Rpc_say_hello, void, say_hello); - GENODE_RPC(Rpc_add, int, add, int, int); + virtual void say_hello() = 0; + virtual int add(int a, int b) = 0; - GENODE_RPC_INTERFACE(Rpc_say_hello, Rpc_add); - }; -} + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_say_hello, void, say_hello); + GENODE_RPC(Rpc_add, int, add, int, int); + + GENODE_RPC_INTERFACE(Rpc_say_hello, Rpc_add); +}; #endif /* _INCLUDE__HELLO_SESSION__HELLO_SESSION_H_ */ diff --git a/repos/hello_tutorial/run/hello.run b/repos/hello_tutorial/run/hello.run index 09c7d292f8..0dd52d8ca4 100644 --- a/repos/hello_tutorial/run/hello.run +++ b/repos/hello_tutorial/run/hello.run @@ -2,7 +2,7 @@ # Build # -build { core init hello drivers/timer } +build { core init hello } create_boot_directory @@ -14,27 +14,13 @@ install_config { - - - - - - - - - - - - - - - + @@ -45,8 +31,8 @@ install_config { # Boot image # -build_boot_image { core init hello_client hello_server timer } +build_boot_image { core init hello_client hello_server } append qemu_args " -nographic " -run_genode_until forever +run_genode_until "hello test completed.*\n" 10 diff --git a/repos/hello_tutorial/src/hello/client/main.cc b/repos/hello_tutorial/src/hello/client/main.cc index 6808b5e9f0..f600117a02 100644 --- a/repos/hello_tutorial/src/hello/client/main.cc +++ b/repos/hello_tutorial/src/hello/client/main.cc @@ -1,38 +1,33 @@ /* * \brief Test client for the Hello RPC interface * \author Björn Döbel + * \author Norman Feske * \date 2008-03-20 */ /* - * Copyright (C) 2008-2013 Genode Labs GmbH + * Copyright (C) 2008-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include -#include -#include +#include +#include #include -#include -using namespace Genode; +Genode::size_t Component::stack_size() { return 64*1024; } -int main(void) + +void Component::construct(Genode::Env &env) { - Hello::Connection h; + Hello::Connection hello(env); - Timer::Connection timer; + hello.say_hello(); - while (1) { - h.say_hello(); + int const sum = hello.add(2, 5); + Genode::log("added 2 + 5 = ", sum); - int foo = h.add(2, 5); - PDBG("Added 2 + 5 = %d", foo); - timer.msleep(1000); - } - - return 0; + Genode::log("hello test completed"); } diff --git a/repos/hello_tutorial/src/hello/server/main.cc b/repos/hello_tutorial/src/hello/server/main.cc index 6dc2771318..9b0ae07832 100644 --- a/repos/hello_tutorial/src/hello/server/main.cc +++ b/repos/hello_tutorial/src/hello/server/main.cc @@ -1,93 +1,91 @@ /* * \brief Main program of the Hello server * \author Björn Döbel + * \author Norman Feske * \date 2008-03-20 */ /* - * Copyright (C) 2008-2013 Genode Labs GmbH + * Copyright (C) 2008-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include -#include -#include -#include +#include +#include #include #include #include namespace Hello { - - struct Session_component : Genode::Rpc_object - { - void say_hello() { - PDBG("I am here... Hello."); } - - int add(int a, int b) { - return a + b; } - }; - - class Root_component : public Genode::Root_component - { - protected: - - Hello::Session_component *_create_session(const char *args) - { - PDBG("creating hello session."); - return new (md_alloc()) Session_component(); - } - - public: - - Root_component(Genode::Rpc_entrypoint *ep, - Genode::Allocator *allocator) - : Genode::Root_component(ep, allocator) - { - PDBG("Creating root component."); - } - }; + struct Session_component; + struct Root_component; + struct Main; } -using namespace Genode; - -int main(void) +struct Hello::Session_component : Genode::Rpc_object { - /* - * Get a session for the parent's capability service, so that we - * are able to create capabilities. - */ - Cap_connection cap; + void say_hello() { + Genode::log("I am here... Hello."); } + + int add(int a, int b) { + return a + b; } +}; + + +class Hello::Root_component +: + public Genode::Root_component +{ + protected: + + Session_component *_create_session(const char *args) + { + Genode::log("creating hello session"); + return new (md_alloc()) Session_component(); + } + + public: + + Root_component(Genode::Entrypoint &ep, + Genode::Allocator &alloc) + : + Genode::Root_component(ep, alloc) + { + Genode::log("creating root component"); + } +}; + + +struct Hello::Main +{ + Genode::Env &env; /* * A sliced heap is used for allocating session objects - thereby we * can release objects separately. */ - static Sliced_heap sliced_heap(env()->ram_session(), - env()->rm_session()); + Genode::Sliced_heap sliced_heap { env.ram(), env.rm() }; - /* - * Create objects for use by the framework. - * - * An 'Rpc_entrypoint' is created to announce our service's root - * capability to our parent, manage incoming session creation - * requests, and dispatch the session interface. The incoming RPC - * requests are dispatched via a dedicated thread. The 'STACK_SIZE' - * argument defines the size of the thread's stack. The additional - * string argument is the name of the entry point, used for - * debugging purposes only. - */ - enum { STACK_SIZE = 4096 }; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "hello_ep"); + Hello::Root_component root { env.ep(), sliced_heap }; - static Hello::Root_component hello_root(&ep, &sliced_heap); - env()->parent()->announce(ep.manage(&hello_root)); + Main(Genode::Env &env) : env(env) + { + /* + * Create a RPC object capability for the root interface and + * announce the service to our parent. + */ + env.parent().announce(env.ep().manage(root)); + } +}; - /* We are done with this and only act upon client requests now. */ - sleep_forever(); - return 0; +Genode::size_t Component::stack_size() { return 64*1024; } + + +void Component::construct(Genode::Env &env) +{ + static Hello::Main main(env); }