Added tech-note 18
authorpravin@inf.ethz.ch <pravin@inf.ethz.ch>
Fri, 6 Dec 2013 18:10:56 +0000 (19:10 +0100)
committerpravin@inf.ethz.ch <pravin@inf.ethz.ch>
Fri, 6 Dec 2013 18:10:56 +0000 (19:10 +0100)
doc/018-Practical-guide/Hakefile [new file with mode: 0644]
doc/018-Practical-guide/PracticalGuide.tex [new file with mode: 0644]
doc/018-Practical-guide/cleanTex.awk [new file with mode: 0755]
doc/018-Practical-guide/generate_readme_tex.sh [new file with mode: 0755]
doc/018-Practical-guide/helloWorld2.pdf [new file with mode: 0644]
doc/018-Practical-guide/helloWorldApp.tex [new file with mode: 0644]

diff --git a/doc/018-Practical-guide/Hakefile b/doc/018-Practical-guide/Hakefile
new file mode 100644 (file)
index 0000000..806bd4b
--- /dev/null
@@ -0,0 +1,16 @@
+----------------------------------------------------------------------
+-- Copyright (c) 2010-13 ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /doc/018-Practical-guide
+--
+----------------------------------------------------------------------
+
+[ buildTechNote "PracticalGuide.tex" "TN-018-PracticalGuide.pdf" False False
+                    [ "helloWorldArch" ]
+]
+
diff --git a/doc/018-Practical-guide/PracticalGuide.tex b/doc/018-Practical-guide/PracticalGuide.tex
new file mode 100644 (file)
index 0000000..6805e54
--- /dev/null
@@ -0,0 +1,66 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Copyright (c) 2013 ETH Zurich.
+% All rights reserved.
+%
+% This file is distributed under the terms in the attached LICENSE file.
+% If you do not find this file, copies can be found by writing to:
+% ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\documentclass[a4paper,twoside]{report} % for a report (default)
+
+\usepackage{bftn,color} % You need this
+\usepackage{subfig}
+\usepackage{listings}
+\usepackage{verbatim}
+
+\usepackage{ifthen}
+\ifthenelse{\isundefined{\hypersetup}}{
+  \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+  \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+
+
+
+\title{Barrelfish Practical Guide}   % title of report
+\author{Team Barrelfish}       % author
+\tnnumber{018}  % give the number of the tech report
+\tnkey{Barrelfish Practical guide} % Short title, will appear in footer
+
+% \date{Month Year} % Not needed - will be taken from version history
+
+%% \newcommand{\note}[1]{}
+\newcommand{\note}[1]{[\textcolor{red}{\textit{#1}}]}
+
+\begin{document}
+\maketitle
+
+%
+% Include version history first
+%
+\begin{versionhistory}
+\vhEntry{1.0}{06.12.2013}{Pravin}{Initial version}
+\end{versionhistory}
+
+% \intro{Abstract}             % Insert abstract here
+% \intro{Acknowledgements}     % Uncomment (if needed) for acknowledgements
+\tableofcontents               % Uncomment (if needed) for final draft
+% \listoffigures               % Uncomment (if needed) for final draft
+% \listoftables                        % Uncomment (if needed) for final draft
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\chapter{Barrelfish compilation and installation}\label{chap:compilationInstallation}
+\input{readme}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{Writing Hello World application}\label{chap:helloWorldApp}
+\input{helloWorldApp}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\bibliographystyle{abbrvnat}
+\bibliography{paper}
+
+\end{document}
diff --git a/doc/018-Practical-guide/cleanTex.awk b/doc/018-Practical-guide/cleanTex.awk
new file mode 100755 (executable)
index 0000000..ad032f0
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/gawk -f
+
+BEGIN {
+    pr = 0
+}
+
+/KNOWN ISSUES/ {
+    pr = 0
+}
+
+/{SUPPORTED} HARDWARE/ {
+    pr = 1
+}
+
+{
+    if (pr ==1) {
+       print
+    }
+}
+
+
diff --git a/doc/018-Practical-guide/generate_readme_tex.sh b/doc/018-Practical-guide/generate_readme_tex.sh
new file mode 100755 (executable)
index 0000000..c95e484
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+set -x
+README="./README.rst"
+CONVERTER="rst2latex"
+# Generate html from restructured text (assuming docutils are installed)
+${CONVERTER} ${README} tmp.tex
+
+# Replace class="title" attribute from H1 tag as it was clashing with something
+# in Drupal
+#sed -i 's/<h1 class="title">/<h1>/g' tmp.tex
+
+# Remove all lines before <body> tag and after </body> tag.
+./cleanTex.awk tmp.tex > readme.tex
+
+rm tmp.tex
+
diff --git a/doc/018-Practical-guide/helloWorld2.pdf b/doc/018-Practical-guide/helloWorld2.pdf
new file mode 100644 (file)
index 0000000..408d31f
Binary files /dev/null and b/doc/018-Practical-guide/helloWorld2.pdf differ
diff --git a/doc/018-Practical-guide/helloWorldApp.tex b/doc/018-Practical-guide/helloWorldApp.tex
new file mode 100644 (file)
index 0000000..365f453
--- /dev/null
@@ -0,0 +1,435 @@
+
+\section{Writing A Sample Barrelfish Application}
+
+Here we show how to write a simple program on Barrelfish.  \textbf{XXX:} no
+error handling yet.  Refer to \texttt{usr/tests/idctest} for code with proper
+error handling.
+
+\subsection{A Simple Hello World Program}
+
+The source for user domains is stored under \begin{verbatim}/usr\end{verbatim}.
+
+A simple hello world domain consists of a source file, and a Hakefile. e.g.,
+\begin{verbatim}
+usr/myapp
+    myapp.c
+    Hakefile
+\end{verbatim}
+
+For a simple hello world app, the source is trivial: a simple printf in main
+will suffice (note that for output printf either uses a debug syscall to print
+to the serial output, or a proper serial server if one is available).
+
+\begin{verbatim}
+#include <stdio.h>
+int main(void) {
+    printf("Hello World\n");
+    return 0;
+}
+\end{verbatim}
+
+To build the domain, call hake.sh in the build directory. This will create a
+Config.hs, Makefile, and symbolic\_targets.mk. You can add myapp in the
+symbolic\_tagets, then run make to build everything. You can also explicitly ask
+make to build the domain. e.g.:
+\begin{verbatim}
+make x86_64/sbin/myapp
+\end{verbatim}
+
+After all is built, the menu.lst needs to be modified to add the domain and have
+it started. Run everything in a simulator using:
+
+\begin{verbatim}
+make sim
+\end{verbatim}
+
+\section{A Simple Hello World Program Using IDC}
+
+In this section, we talk how we can write an application that uses Barrelfish
+IDC mechanism to communicate with other applications.  For purpose of this
+section, we will develop simple \textbf{Hello World} client and server
+application.  The client running on core-0 will send an IDC message to a
+server running on core-1.  This message will contain a string with contents
+\texttt{"Hello World"}.
+
+Adding IDC (inter-dispatcher communication) is a bit more complicated. It
+requires defining an interface in Flounder IDL, updating the interfaces
+Hakefile, updating the domain's (myapp) Hakefile, and then adding initialization
+code as well as appropriate callbacks to the source file.
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.8\columnwidth]{helloWorld2.pdf}
+  \end{center}
+  \caption{Hello world application overview}
+  \label{fig:helloWorld}
+\end{figure}
+
+\subsection{Interface}
+
+In this subsection, we will create a new interface
+for our use.  We do this by creating a new interface file called
+\texttt{hello.if} in the \texttt{if\\} directory. Following is simple interface
+that will suffice for our requirements of sending single string as a message.
+
+
+\verbatiminput{if/hello.if}
+\begin{verbatim}
+interface hello "Hello World interface" {
+    message hello_msg(string s);
+};
+\end{verbatim}
+
+You can find out more about how to write such interfaces by referring
+\href{http://www.barrelfish.org/TN-011-IDC.pdf}{IDC-Technote}.
+
+You also need to modify the \texttt{if/Hakefile} to add this newly created
+interface into the compilation process.
+
+\begin{verbatim}
+[ flounderGenDefs (options arch) f
+      | f <- [ "ahci_mgmt",
+                ...
+                ...
+              "hello"],
+             arch <- allArchitectures
+] ++
+\end{verbatim}
+
+Adding the name of your interface here will make sure that the communication
+stubs will be automatically generated for by the compilation process.  These
+can be found in following location in your build directory:
+
+\begin{verbatim}
+BUILD/ARCH/include/if/hello_defs.h
+BUILD/ARCH/include/if/hello_lmp_defs.h
+BUILD/ARCH/include/if/hello_ump_defs.h
+BUILD/ARCH/include/if/hello_multihop_defs.h
+\end{verbatim}
+
+There will be one for each type of communication mechanism supported by
+the Barrelfish. You don't need to worry about these files as build mechanism
+will take care of these files.  Only things developers need to do is
+write the interface file and include appropriate headers in the application
+code (discussed in following section)
+
+
+\subsection{Application}
+
+In this section, we discuss how would we write the application code,
+and how to compile it.  For sake of simplicity, we will write both server and
+client code in same application.  Following is the code for the \texttt{main}
+function, which runs the client code or server code based on the
+command line argument.
+
+
+\begin{verbatim}
+int main(int argc, char *argv[]) {
+    errval_t err;
+    if ((argc >= 2) && (strcmp(argv[1], "client") == 0)) {
+        start_client();
+    } else if ((argc >= 2) && (strcmp(argv[1], "server") == 0)) {
+        start_server();
+    } else {
+        return EXIT_FAILURE;
+    }
+    /* The dispatch loop */
+    struct waitset *ws = get_default_waitset();
+    while (1) {
+        err = event_dispatch(ws); /* get and handle next event */
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "in event_dispatch");
+            break;
+        }
+    }
+    return EXIT_FAILURE;
+}
+\end{verbatim}
+
+The important part of the above is in the dispatch loop where application
+will wait for events on the default wait-set and handle those events
+in infinite while loop.
+
+\subsection{Server side}
+
+In this section, we will develop the server code in steps of
+"exporting service", "registering the service" and "handling actual requests".
+
+
+\subsubsection{Exporting service}
+As a first step, server needs to export the service it wants to provide
+by calling export function on the service interface.  In this case, server
+will call \texttt{hello\_export} as we are providing \textit{Hello World}
+service.
+
+\begin{verbatim}
+static void start_server(void)
+{
+    errval_t err;
+    err = hello_export(NULL /* state for callbacks */,
+            export_cb, /* Callback for export */
+            connect_cb,  /* Callback for client connects */
+            get_default_waitset(), /* waitset where events will be sent */
+            IDC_EXPORT_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "export failed");
+    }
+}
+\end{verbatim}
+
+This call also registers two callback handles.  Once the service
+is successfully exported, then the export callback provided.  When any client
+connects with the service then the connect callback will be called.
+We will see the use of these callbacks in next few steps.
+
+
+\subsubsection{Registering service}
+Server also need to register the service so that other applications can find
+it.  Following code registers the \texttt{"hello\_service"} on the callback
+from successful completion of export:
+
+
+\begin{verbatim}
+const char *service_name = "hello_service";
+static void export_cb(void *st, errval_t err, iref_t iref)
+{
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "export failed");
+    }
+    err = nameservice_register(service_name, iref);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "nameservice_register failed");
+    }
+}
+\end{verbatim}
+
+The \texttt{nameservice\_register} is a blocking call which will connect
+to the global nameserver and publish the service name.
+
+\subsubsection{Connect and handling messages}
+This section describes how exactly the connection is established and
+requests are handled.
+
+\begin{verbatim}
+static void rx_hello_msg(struct hello_binding *b, char *str)
+{
+    printf("server: received hello_msg:\n\t%s\n", str);
+    free(str);
+}
+
+static struct hello_rx_vtbl rx_vtbl = {
+    .hello_msg = rx_hello_msg,
+};
+
+static errval_t connect_cb(void *st, struct hello_binding *b)
+{
+    b->rx_vtbl = rx_vtbl;
+    return SYS_ERR_OK;
+}
+\end{verbatim}
+
+The above code defines a function \texttt{rx\_hello\_msg} which will be
+responsible to actually handle the requests.  In our case, we are just
+printing out the string we received as part of the message.
+
+We need to create a list of function pointers where one function pointer
+is assigned for every possible incoming message. So we are creating
+an instance \texttt{rx\_vtbl} of type \texttt{hello\_rx\_vtbl}.
+
+On arrival of new connection, we provide this list of function pointers
+to register which functions to call for handling particular type of message.
+
+
+\subsection{Client side}
+Client needs to find the service and connect to it.  Once the connection
+is successfully established then it can send the actual requests. In this
+section, we show how it can be done.
+
+
+\subsubsection{Find and Bind}
+Following code finds the desired service with given name and binds with
+the service.
+
+\begin{verbatim}
+static void start_client(void)
+{
+    errval_t err;
+    iref_t iref;
+    err = nameservice_blocking_lookup(service_name,
+            &iref);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err,
+                "nameservice_blocking_lookup failed");
+    }
+    err = hello_bind(iref, bind_cb, /* Callback function */
+            NULL /* State for the callback */,
+            get_default_waitset(),
+            IDC_BIND_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "bind failed");
+    }
+}
+\end{verbatim}
+
+As the name suggests  \texttt{nameservice\_blocking\_lookup} is a blocking
+call which will connect with the nameserver and query for the given
+service name.  The \texttt{iref} handle returned by this call can be used
+for binding with the service.
+
+The \texttt{hello\_bind} is part of the code generated from the interface
+file and will try and connect with the server on appropriate channel.
+
+Following code is callback function which will be called when client
+successfully connects with the server.  This code also creates a client
+state which stores pointer to the communication channel binding.  This code
+then calls a function \texttt{run\_client} with the client state.
+
+
+\begin{verbatim}
+struct client_state {
+    struct hello_binding *binding;
+    int count;
+};
+
+static void bind_cb(void *st, errval_t err, struct hello_binding *b)
+{
+    struct client_state *myst = malloc(sizeof(struct client_state));
+    assert(myst != NULL);
+    myst->binding = b;
+    myst->count = 0;
+    run_client(myst);   /* calling run_client for first time */
+}
+\end{verbatim}
+
+
+\subsubsection{Sending messages}
+
+Most of the actual work of sending message is done from the \texttt{run\_client}
+function which is described bellow:
+
+\begin{verbatim}
+static void run_client(void *arg)
+{
+    errval_t err;
+    struct client_state *myst = arg;
+    struct hello_binding *b = myst->binding;
+
+    /* Creating a continuation which will call run_client */
+    struct event_closure txcont = MKCONT(run_client, myst);
+
+    errval_t err = b->tx_vtbl.hello_msg(b, txcont, "Hello World");
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "error sending message %d\n", myst->count);
+    }
+}
+\end{verbatim}
+
+This function first creates a continuation which calls itself
+and will be used as a callback function. The next step is to actually
+send the message by calling an appropriate function on the send side of
+interface binding (\texttt{tx\_vtbl.hello\_msg}) with actual message
+and above created continuation.  This call will register a message to be sent
+and a callback that will be triggered when message is successfully.
+
+As you can notice, callback function is calling \texttt{run\_client} again,
+leading an infinite loop of sending messages.
+
+\subsection{Building and running the application}
+
+In this section, we talk about how build your application.  For this, you
+will need to create a \texttt{Hakefile} in the code directory which should
+look something like bellow:
+
+\begin{verbatim}
+    [ build application { target = "hello-cs",
+                          cFiles = [ "hello.c" ],
+                          flounderBindings = [ "hello" ]
+                        }
+    ]
+\end{verbatim}
+
+This \texttt{Hakefile} specifies that you want to build an application
+with name \texttt{hello\-cs} from the \texttt{hello.c} file, and also
+it marks the dependency on the communication interface \texttt{hello}.
+
+The next step is to modify the \texttt{barrelfish/hake/symbolic\_targets.mk}
+file to include your newly created application into the build process.
+Here you can choose an architecture for which your application should be
+compiled, or you can also add your application in \texttt{MODULES\_COMMON}
+list so that your application will be compiled for all architectures.
+
+\begin{verbatim}
+MODULES_COMMON= \
+       sbin/init_null \
+        ...
+        ...
+       sbin/xcorecapbench \
+       sbin/hello-cs \
+
+\end{verbatim}
+
+After this, rebuild the Barrelfish to include newly added application.  On
+successful compilation the binary will be created in sbin directory of
+desired architecture.
+
+
+% ########### Editing menu.lst
+Next step is to edit one of the \texttt{barrelfish/hake/menu.lst.*} file based
+on which architecture you are targeting.  Bellow is the minimal
+\texttt{menu.lst.x86\_64} file to be able to run this newly created application.
+
+\begin{verbatim}
+title  Barrelfish
+root   (nd)
+kernel /x86_64/sbin/elver loglevel=4
+module /x86_64/sbin/cpu loglevel=4
+module /x86_64/sbin/init
+
+# Domains spawned by init
+module /x86_64/sbin/mem_serv
+module /x86_64/sbin/monitor
+
+# Special boot time domains spawned by monitor
+module  /x86_64/sbin/ramfsd boot
+module  /x86_64/sbin/skb boot
+modulenounzip /skb_ramfs.cpio.gz nospawn
+module  /x86_64/sbin/kaluga boot
+module  /x86_64/sbin/acpi boot
+module  /x86_64/sbin/spawnd boot
+#bootapic-x86_64=1-15
+module  /x86_64/sbin/startd boot
+module /x86_64/sbin/routing_setup boot
+
+# Drivers
+module /x86_64/sbin/pci auto
+module /x86_64/sbin/ahcid auto
+
+# General user domains
+module /x86_64/sbin/serial
+
+# Your hello world application (both server and client)
+module /x86_64/sbin/hello-cs core=0 server
+module /x86_64/sbin/hello-cs core=1 client
+\end{verbatim}
+
+Now, you can build your application and verify that binary is created as
+follows:
+
+\begin{verbatim}
+$ make
+$ ls x86_64/sbin/hello-cs
+\end{verbatim}
+
+If everything goes fine, you can run the application in \texttt{qemu} simulator
+with following command:
+\begin{verbatim}
+$ make sim
+\end{verbatim}
+
+At this moment, you should be able see Barrelfish booting and starting your
+applications which are then able to communicate by sending "Hello World"
+message in infinite loop.
+
+
+
+