code:
\begin{tikzpicture}[node distance=10ex]

	%
	% init
	%
	\labeledcompoundnode{init}
	                    {component}
	                    {Init}{

		\rpcobjectrnode{parentgui}{node distance=3.5ex}{}{Parent}
		\node[capability, right of=parentgui] (rootcap) {};
		\upwardthreadnode{initthread}{below=0ex of rootcap}
		\rpcobjectrnode{parentlauncher}{node distance=3.5ex, xshift=7ex,
		                               right of=rootcap, opacity=0.5}{}{Parent}
	}

	%
	% launcher
	%
	\labeledcompoundnode{launcher}
	                    {component, above=5ex of init, xshift=15ex}
	                    {Launcher}{
		\rpcobjectrnode{parentapplication}{node distance=3.5ex}{}{Parent}
		\downwardthreadnode{launcherthread}{below of=parentapplication,
		                                    node distance=4ex}
		\node[capability, below=0ex of launcherthread] (launcherparentcap) {};
	}

	%
	% application
	%
	\labeledcompoundnode{application}
	                    {component, above=5ex of launcher, xshift=8ex,
	                     minimum width=15ex}
	                    {Application}{
		\downwardthreadnode{applicationthread}{}
		\node[capability, below=0ex of applicationthread] (applicationparentcap) {};
		\node[capability, below=0ex of applicationthread, xshift=-6ex] (sessioncap) {};
	}

	%
	% gui
	%
	\labeledcompoundnode{gui}
	                    {component, above=5ex of init, xshift=-12ex}
	                    {GUI}{
		\rpcobjectrnode{guisession}{node distance=6.5ex}{}{GUI session}
		\rpcobjectrnode{guiroot}{below of=guisession, yshift=-5ex, node distance=5ex}{}{GUI root}
		\downwardthreadnode{guithread}{below of=guiroot, text opacity=0, node distance=4ex}
		\node[capability, below=0ex of guithread] (guiparentcap) {};
	}

	% session call from application to launcher
	\path[arrow] (applicationparentcap) .. controls +(0,-4ex) and +(0,4ex)
	                            .. node [sloped=false, pos=0.6, text opacity=0]
	                            {$session$("GUI", label:browser)} (parentapplicationobj);

	% session call from launcher to init
	\path[arrow] (launcherparentcap) .. controls +(0,-4ex) and +(0,4ex)
	                            .. node [sloped=false, pos=0.6, xshift=8ex, text opacity=0]
	                            {$session$("GUI", label:arora)} (parentlauncherobj);

	% root call from init to gui
	\path[arrow] (rootcap) .. controls +(0,4ex) and +(4ex,-4ex)
	                            .. node [sloped=false, pos=0.3, xshift=-6ex]
	                            {$session$(label:arora)} (guirootobj);

	% session creation
	\path[arrow] (guirootobj) -- node [sloped=false, pos=0.3]
	                            {$create$} (guisessionobj);

	% invisible, just for keeping the layout consistent with announce.tikz
	\path (guiparentcap) .. controls +(0,-4ex) and +(0,4ex)
	                            .. node [sloped=false, pos=0.6, xshift=-10ex, text opacity=0]
	                            {$announce$("GUI", 3)} (parentguiobj);

	% capability delegations
	\path [draw, dashed, opacity=0.3] (guirootcap)           .. controls +(5ex,-5ex) and +(0,5ex) .. (rootcap);
	\path [draw, dashed, opacity=0.3] (guiparentcap)         .. controls +(0ex,-8ex) and +(0,5ex) .. (parentguicap);
	\path [draw, dashed, opacity=0.3] (applicationparentcap) .. controls +(0ex,-5ex) and +(0,5ex) .. (parentapplicationcap);
	\path [draw, dashed, opacity=0.3] (launcherparentcap)    .. controls +(0ex,-5ex) and +(0,5ex) .. (parentlaunchercap);

	\path [draw, dashed] (guisessioncap) -- (sessioncap);

\end{tikzpicture}


code:
\begin{tikzpicture}

	\begin{timelinediagram}

		\renewcommand{\timestepvector}{0,-0.4}

		% initial timelines

		\node[minimum width=15ex, font=\normalsize]                                           (clientlabel) {Client};
		\node[minimum width=30ex, font=\normalsize, right of=clientlabel, node distance=30ex] (corelabel)   {Core};
		\node[minimum width=15ex, font=\normalsize, right of=corelabel,   node distance=30ex] (serverlabel) {Server};

		\path (clientlabel)+(-3ex,-3ex) node (timelineanchor) {};
		\newtimeline{client}

		\path (corelabel)+(-10ex,-3ex) node (timelineanchor) {};
		\newtimeline{corerm}
		\path (corerm) node {PD};

		\path (corelabel)+(10ex,-3ex) node (timelineanchor) {};
		\newtimeline{corepd}
		\path (corepd) node {PD};

		\path (serverlabel)+(3ex,-3ex) node (timelineanchor) {};
		\newtimeline{server}

		\activate{server}
		\timestep

		% allocate dataspace

		\transition{server}{corepd}{allocate dataspace}
		\renewcommand{\timestepvector}{0,-0.3}
		\timestep
		\node[dataspace, below=1.3 of corelabel] (physdataspace) {Data \\space};
		\draw[timelinemessage, dashed, above] (corepd) -- node {$create$} (physdataspace);
		\timestep
		\transition{corepd}{server}{}
		\node[align=center] at (transitionlabel) {return \\ capability \textbf{$cap_{ds}$}};
		\renewcommand{\timestepvector}{0,-1.4}
		\timestep

		% server attaches dataspace

		\transition{server}{corerm}{}
		\node[align=center] at (transitionlabel) {attach \\ dataspace \textbf{$cap_{ds}$}};
		\renewcommand{\timestepvector}{0,-0.8}
		\timestep
		\path (server)+(-1,0) node[dataspace, dotted] (serverdataspace) {Data \\space};
		\path[dataspacemapped] (serverdataspace.north east) -- (physdataspace.north east);
		\path[dataspacemapped] (serverdataspace.south west) -- (physdataspace.south west);
		\timestep
		\transition{corerm}{server}{return server-local address}
		\renewcommand{\timestepvector}{0,-0.6}
		\timestep

		% server delegates dataspace to client

		\draw[timelinemessage, dashed] (server) -- node[above] {$delegate$ \textbf{$cap_{ds}$}} (client);
		\activate{client}
		\renewcommand{\timestepvector}{0,-0.4}
		\timestep

		% client attaches dataspace

		\transition{client}{corerm}{}
		\node[align=center] at (transitionlabel) {attach \\ dataspace \textbf{$cap_{ds}$}};
		\renewcommand{\timestepvector}{0,-0.8}
		\timestep
		\path (client)+(1,0) node[dataspace, dotted] (clientdataspace) {Data \\space};
		\path[dataspacemapped] (clientdataspace.north west) -- (physdataspace.north west);
		\path[dataspacemapped] (clientdataspace.south east) -- (physdataspace.south east);
		\timestep
		\transition{corerm}{client}{}
		\path (transitionlabel)+(4ex,0) node[align=center] {return \\ client-local address};

		% server access

		\draw[timelinemessage, dashed, below] (server) .. controls +(-1,0) and +(0,-1) ..
			node {$access$} (serverdataspace);

		\renewcommand{\timestepvector}{0,-1.2}
		\timestep

		% client access

		\draw[timelinemessage, dashed, below] (client) .. controls +(1,0) and +(0,-1) ..
			node {$access$} (clientdataspace);
		\renewcommand{\timestepvector}{0,-0.4}
		\timestep

	\end{timelinediagram}

	\begin{scope}[on background layer]
	\node[timelinegroup, fit=(clientlabel) (clientdataspace) (client)] {};
	\node[timelinegroup, fit=(corelabel)   (corerm) (corepd)] {};
	\node[timelinegroup, fit=(serverlabel) (serverdataspace) (server)] {};
	\end{scope}

\end{tikzpicture}

repo_name: Fhiss/genode


code:
\begin{tikzpicture}

	\begin{timelinediagram}

		\renewcommand{\timestepvector}{0,-0.4}

		% initial timelines

		\node[minimum width=22ex, font=\normalsize]
			(producerlabel) {Signal producer};
		\node[minimum width=32ex, font=\normalsize, right of=producerlabel,
		     node distance=31ex]
			(handlerlabel)  {Signal handler};

		\path (producerlabel)+(8ex,-3ex) node (timelineanchor) {};
		\newtimeline{producer}

		\path (handlerlabel)+(-12ex,-3ex) node (timelineanchor) {};
		\newtimeline{handler}

		\node[minimum width=10ex, font=\normalsize, right of=handlerlabel,
		      node distance=28ex] (corelabel) {Core};
		\path (corelabel)+(0ex,-3ex) node (timelineanchor) {};
		\path (corelabel.south) node[below, font=\normalsize] (corepdlabel) {PD};
		\newtimeline{coresignal}

		\activate{producer}
		\activate{handler}
		\timestep

		% entrypoint

		\path (handler)+(2.5,0) node (timelineanchor) {};
		\newtimeline{ep}
		\node[draw, fill=white, align=center, dropshadow] at (ep) {Entrypoint};
		\renewcommand{\timestepvector}{0,-1}
		\timestep

		% create signal context

		\path (handler)+(4,0) node[draw, fill=white, align=center, dropshadow]
			(context) {Signal\\ context \textbf{c}};
		\draw[timelinemessage, dashed] (handler) -- node[above] {$create$} (context);
		\renewcommand{\timestepvector}{0,-0.7}
		\timestep

		% manage context

		\transition{handler}{ep}{manage \textbf{c}}
		\renewcommand{\timestepvector}{0,-0.3}
		\timestep
		\transition{ep}{coresignal}{allocate capability}
		\timestep
		\transition{coresignal}{ep}{}
		\timestep
		\transition{ep}{handler}{}
		\path (transitionlabel)+(1ex,0)
			node[align=center, below] {signal-context \\ capability \textbf{$cap_c$}};
		\renewcommand{\timestepvector}{0,-0.3}
		\timestep

		% delegate context capability

		\draw[timelinemessage, dashed] (handler) -- node[align=center]
			{$delegate$ \\ {\textbf{$cap_c$}}} (producer);
		\timestep

		% create signal transmitter

		\path (producer)+(-13ex,0) node (timelineanchor) {};
		\newtimeline{transmitter}
		\node[draw, fill=white, align=center, dropshadow] at (transmitter)
			(signaltransmitter) {Signal\\ transmitter\\ for \textbf{$cap_c$}};
		\draw[timelinemessage, dashed] (producer) -- node[above] {$create$} (signaltransmitter);
		\timestep

		\deactivate{producer}
		\deactivate{handler}
		\renewcommand{\timestepvector}{0,-1}
		\timestep

		% second part

		\activate{producer}
		\activate{handler}
		\renewcommand{\timestepvector}{0,-0.4}
		\timestep

		% producer submits two signals

		\renewcommand{\timestepvector}{0,-0.2}
		\transition{producer}{transmitter}{submit} \timestep
		\renewcommand{\timestepvector}{0,-0.4}
		\transition{transmitter}{producer}{} \timestep

		\renewcommand{\timestepvector}{0,-0.2}
		\transition{producer}{transmitter}{submit} \timestep
		\renewcommand{\timestepvector}{0,-0.4}
		\transition{transmitter}{producer}{} \timestep

		% handler receives 2 signals

		\renewcommand{\timestepvector}{0,-0.2}
		\transition{handler}{ep}{block} \timestep
		\renewcommand{\timestepvector}{0,-0.6}
		\transition{ep}{handler}{} \timestep
		\path (transitionlabel)+(1ex,0)
			node[align=center, below] {context {\textbf{c}} count {\textbf{2}}};
		\timestep

		% handler waits for signal

		\renewcommand{\timestepvector}{0,-0.8}
		\transition{handler}{ep}{block} \timestep

		% producer submits one signal and immediately wakes up handler

		\transition{producer}{transmitter}{submit}
		\renewcommand{\timestepvector}{0,-0.1}
		\timestep
		\transition{ep}{handler}{}
		\path (transitionlabel)+(1ex,0)
			node[align=center, below] {context {\textbf{c}} count {\textbf{1}}};
		\draw[timelinemessage, dotted, pos=0.75] (transmitter) -- node[above] {$wake$ $up$} (handler);
		\timestep
		\renewcommand{\timestepvector}{0,-0.4}
		\transition{transmitter}{producer}{} \timestep
		\timestep

	\end{timelinediagram}

	\begin{scope}[on background layer]
	\node[timelinegroup, fit=(producerlabel) (transmitter) (producer)] {};
	\node[timelinegroup, fit=(handlerlabel) (context)  (handler)] {};
	\node[timelinegroup, fit=(corelabel) (corepdlabel) (coresignal)] {};
	\end{scope}

\end{tikzpicture}


code:
\begin{tikzpicture}

	\tikzstyle{treenode} = [component, path fading=flow fade, align=center,
	                        rounded corners=1, minimum width=12ex,
	                        minimum height=5ex]

	%
	% Components
	%

	% parent
	\node[treenode] (parent) {Parent};

	% server
	\node[treenode, above=6ex of parent, xshift=-7ex] (server) {Server};
	\node[treenode, above=6ex of parent, xshift=7ex]  (client) {Client};

	%
	% Parent-child relationships
	%

	\tikzstyle{treechildarrow} = [arrow, thick, opacity=0.2]

	\path[treechildarrow] (parent) -- (server.south);
	\path[treechildarrow] (parent) -- (client.south);

	%
	% Session relationship
	%

	\tikzstyle{treesessionarrow} = [arrow, thick, densely dashed]

	% client -> server
	\path[treesessionarrow] (client.220)
		.. controls +(-1ex,-3ex) and +(1ex,-3ex) .. (server.320);

\end{tikzpicture}


code:
\begin{tikzpicture}

	\definecolor{appcolor}        {rgb}{1,1,0.7}
	\definecolor{defaultcolor}    {rgb}{1,1,1}
	\definecolor{criticalcolor}   {rgb}{0.9,0.5,0.4}
	\definecolor{kernelcolor}     {rgb}{0.6,0.8,0.7}
	\definecolor{drivercolor}     {rgb}{0.6,0.7,0.8}

	\tikzstyle{treenode} = [component, path fading=flow fade, align=center,
	                        rounded corners=1, minimum height=6ex]

	\tikzstyle{service} = [draw=black, draw opacity=0.4, ball color=defaultcolor, fill opacity=0.2,
	                       rounded corners=0, shape=semicircle,
	                       inner sep=1.3ex, outer sep=0, above]

	\tikzstyle{drivernode}   = [treenode, bottom color=drivercolor]
	\tikzstyle{criticalnode} = [treenode, bottom color=criticalcolor]

	\tikzstyle{treesessionarrow} = [arrow, thick]

	%
	% Components
	%

	% platform driver
	\node[criticalnode, minimum width=36ex, align=center]
	     (platformdrv) {};

	\path (platformdrv) node[align=center] {Platform Driver};

	\path (platformdrv.north) node[service, scale=0.4, xshift=-4ex]  (platformservice) {};
	\path (platformservice) node[scale=0.7, yshift=-2ex] {Platform};

	% pio driver
	\node[criticalnode, minimum width=18ex, above=6ex of platformdrv, xshift=9ex, align=center]
	     (piodrv) {};

	\path (piodrv) node[align=center] {PIO Driver};

	\path (piodrv.north) node[service, scale=0.4, xshift=-12ex]  (pincontrolservice) {};
	\path (piodrv.north) node[service, scale=0.4, xshift=8ex] (pinirqservice)  {};
	\path (piodrv.north) node[service, scale=0.4, xshift=16ex] (pinstateservice)  {};
	\path (pincontrolservice) node[align=center, scale=0.5, yshift=-3.2ex] {Pin\\control};
	\path (pinirqservice)     node[scale=0.7, yshift=-2ex] {IRQ};
	\path (pinstateservice)   node[align=center, scale=0.5, yshift=-3.2ex] {Pin\\state};

	\node[drivernode, minimum width=18ex, above=6ex of piodrv.north west,
	      align=center, anchor=south west, xshift=0ex]
	     (touchscreen) {};

	\path (touchscreen) node[align=center] {Touchscreen\\Driver};

	\node[drivernode, minimum width=17.5ex, above=6ex of piodrv.north east,
	      align=center, anchor=south east, xshift=-18.5ex]
	     (framebuffer) {};

	\path (framebuffer) node[align=center] {Framebuffer\\Driver};

	% devices

	\tikzstyle{device} = [drivernode, rounded corners=0, minimum height=2ex, rotate=45, scale=0.5]

	\path (platformdrv.south)+(0ex,-3ex) coordinate (devices) { };
	\path (devices)+(-3ex*1,0) node[device] (ccu)  {CCU};
	\path (devices)+(3ex*0,0) node[device] (rsb)  {R\_RSB};
	\path (rsb)+(0,-4ex) node[device] (pmic) {PMIC};
	\path (devices)+(3ex*1,0)  node[device] (rccu)   {R\_CCU};

	\path (piodrv.south)+(0ex,-3ex) coordinate (devices) { };
	\path (devices)+(3ex*1,0) node[device] (pio)  {PIO};
	\path (devices)+(3ex*2,0) node[device] (rpio) {R\_PIO};

	% device access

	\tikzstyle{accessarrow} = [arrow]
	\path[accessarrow] (pio |- piodrv.south) -- (pio);
	\path[accessarrow] (rpio |- piodrv.south) -- (rpio);
	\path[accessarrow] (ccu |- platformdrv.south) -- (ccu);
	\path[accessarrow] (rccu |- platformdrv.south) -- (rccu);
	\path[accessarrow] (rsb |- platformdrv.south) -- (rsb);
	\path[accessarrow] (rsb) -- (pmic);

	% sessions
	\path[treesessionarrow] (piodrv.south) .. controls +(0,-2ex) and +(2ex,2ex) .. (platformservice);

	\path[treesessionarrow] (pincontrolservice |- touchscreen.south)  -- (pincontrolservice);
	\path[treesessionarrow] (pinstateservice   |- framebuffer.south) -- (pinstateservice);
	\path[treesessionarrow] (pinirqservice     |- framebuffer.south) -- (pinirqservice);

	\path[treesessionarrow] (touchscreen.203) .. controls +(-1ex,-2ex) and +(0ex,12ex) .. (platformservice);
	\path[treesessionarrow] (framebuffer.250) .. controls +(0ex,-2ex) and +(-4ex,4ex) .. (platformservice);
	\path[treesessionarrow] (framebuffer.290) .. controls +(2ex,-2ex) and +(-2ex,2ex) .. (pincontrolservice);

	\tikzstyle{risk} = [rectangle callout, fill=red!80!black, rounded corners=3, text=white]
	\tikzstyle{details} = [rectangle callout, draw opacity=0.3, fill=white, fill opacity=0.2,
	                       text opacity=1, rounded corners=3, draw]

\end{tikzpicture}


code:
\begin{tikzpicture}

	\begin{timelinediagram}

		\renewcommand{\timestepvector}{0,-0.4}

		% initial timelines

		\node[minimum width=10ex, font=\normalsize]
			(clientlabel) {Client};
		\node[minimum width=10ex, font=\normalsize, right of=clientlabel,
		      node distance=9cm]
			(serverlabel) {Server};

		\path (clientlabel)+(0,-3ex) node (timelineanchor) {};
		\newtimeline{client}

		\path (serverlabel)+(0,-3ex) node (timelineanchor) {};
		\newtimeline{server}

		\activate{client}
		\activate{server}

		% server creates and attaches dataspace

		\path (client) -- node[dataspace, below=2.5] (dataspace) {Data\\space} (server);
		\timestep
		\draw[timelinemessage, dashed] (server)
			.. controls +(-2,0) and +(1,2) .. node[above] {$create$, $attach$} (dataspace);
		\timestep
		\deactivate{server}
		\timestep

		% client requests dataspace from server

		\transition{client}{server}{}
		\path (transitionlabel)+(-1.5,0) node[above] {request dataspace};
		\renewcommand{\timestepvector}{0,-0.2}
		\timestep
		\transition{server}{client}{}
		\path (transitionlabel)+(-1.5,0) node[below] {return dataspace capability};

		\renewcommand{\timestepvector}{0,-0.7}
		\timestep

		% client attached dataspace

		\draw[timelinemessage, dashed] (client)
			.. controls +(2,0) and +(-1,0.5) .. node[above] {$attach$} (dataspace);

		\renewcommand{\timestepvector}{0,-0.3}
		\timestep
		\deactivate{client}

		\renewcommand{\timestepvector}{0,-1.2}
		\timestep
		\renewcommand{\timestepvector}{0,-0.4}

		% client writes

		\activate{client}
		\renewcommand{\timestepvector}{0,-0.4}
		\timestep
		\draw[timelinemessage, dashed] (client)
			.. controls +(2,0) and +(-1,0) .. node[above] {$write$} (dataspace);
		\timestep

		% client notifies server via RPC call

		\transition{client}{server}{RPC call}
		\renewcommand{\timestepvector}{0,-0.6}
		\timestep
		\node at (server) (serverdispatch) {};
		\timestep
		\transition{server}{client}{RPC reply}
		\node[rotate=90] at (serverdispatch) {dispatch};
		\draw[timelinemessage, dashed] (serverdispatch)
			.. controls +(-2,0) and +(1,0) .. node[above] {$read$, $write$} (dataspace);

		% client reads

		\renewcommand{\timestepvector}{0,-0.2}
		\timestep
		\draw[timelinemessage, dashed] (client)
			.. controls +(2,0) and +(-1,-0.5) .. node[above, pos=0.6] {$read$} (dataspace);
		\timestep

	\end{timelinediagram}

	\begin{scope}[on background layer]
	\node[timelinegroup, fit=(clientlabel) (client)] {};
	\node[timelinegroup, fit=(serverlabel) (server)] {};
	\end{scope}

\end{tikzpicture}


code:
%%
%% Tikz styles used for diagrams
%%

\tikzstyle{every node}+=[font=\footnotesize \sffamily]

\tikzstyle{dropshadow} = [blur shadow={shadow blur steps=5,shadow xshift=.0ex,
                                       shadow yshift=-0.3ex,opacity=0.9,
                                       shadow blur radius=0.5ex}]

\tikzstyle{compound} = [rectangle, draw, text centered,
                         rounded corners,
                         top color=white,
                         bottom color=black!5,
                         dropshadow,
                         draw=black!10]

\tikzstyle{component} = [compound, draw=black!70]

\tikzstyle{compoundlabel} = [below right,
                             text opacity=0.6, inner sep=0, outer sep=0.7ex]

\tikzstyle{capability} = [circle, draw, fill, thick,
                          inner color=white,
                          outer color=blue!30,
                          inner sep=1pt,
                          minimum size=2.8ex,
                          fill opacity=1.0, dropshadow,
                          anchor=mid]

\tikzstyle{capslot} = [minimum size=2.5ex, inner sep=0ex, outer sep=0ex,
                       fill=white, draw=black!70]

\tikzstyle{kernelobj} = [draw, tape, tape bend top=none,
                         draw=black!70, align=center, fill=white, dropshadow]

\tikzstyle{arrow} = [draw=black!80, ->, >= stealth, sloped, above]

\tikzstyle{userland} = [fill=green]

\tikzstyle{kernel} = [fill=yellow]

\tikzstyle{thread} = [font=\normalsize]

\tikzstyle{nodecompound} = [rectangle, draw, align=center,
                            minimum height=2em, minimum width=2em,
                            inner sep=1.5ex, outer sep=1ex,
                            rounded corners,
                            top color=white,
                            bottom color=black!20,
                            dropshadow,
                            draw=black!10, thick]

\tikzstyle{ownership} = [draw, single arrow, draw=black!10, minimum height=4ex,
                         bottom color=white, top color=red!70,
                         single arrow head extend=1ex]

\tikzstyle{every picture}+=[remember picture]

\newcommand\kernelred{black!20!red!100}

\tikzstyle{dataspace} = [tape, draw, tape bend top=none, fill=white,
                         dropshadow, minimum height=6ex, align=center,
                         tape bend height=0.5ex, fill opacity=0.95]

% dotted line that connects dataspaces mapped in different address spaces
\tikzstyle{dataspacemapped} = [draw, draw, dotted]

% style representing a hardware component
\tikzstyle{hardware} = [draw=black!50, dropshadow, align=center,
                        path fading=flow fade, thin,
                        top color=black!5, bottom color=black!20]

%%
%% Styles for flow charts
%%
\tikzstyle{flowborder} = [draw=black!50]

\tikzstyle{flowbox} = [flowborder, fill=white, dropshadow,
                       rounded corners=0.5ex,
                       fill=yellow!20,
                       path fading=flow fade]

\tikzstyle{flowdecision} = [flowborder, diamond, fill=blue!20,
                           text badly centered, align=center,
                           inner sep=0.5ex,
                           dropshadow, path fading=flow fade]

%%
%% Styles for timeline diagrams
%%

\tikzstyle{activetimeline} = [draw,
                              blur shadow={shadow blur steps=5},
                              shadow yshift=-0.3ex, shadow xshift=0em,
                              rounded corners=0.4ex,
                              color=black!30,
                              path fading=timeline fade right,
                              left color=yellow!90!white!50,
                              right color=yellow!100!white!50,
                              minimum width=2.5ex]

\tikzstyle{timelinemessage} = [draw=black!80, ->, >= stealth, sloped,
                               shorten >= 0.8ex, shorten <= 0.8ex]

\tikzstyle{timelinegroup} = [draw=black!50, dashed,
                             rounded corners, fill=black, fill opacity=0.05]

%%
%% Styles for UML class diagrams
%%

\tikzstyle{umlclass}  = [draw, fill=white, dropshadow, align=left]
\tikzstyle{umlclass2} = [umlclass, rectangle split, rectangle split parts=2]
\tikzstyle{umlclass3} = [umlclass, rectangle split, rectangle split parts=3]

\tikzstyle{umlinfo} = [umlclass,
                       chamfered rectangle,
                       chamfered rectangle corners=north east,
                       text opacity=0.5, draw opacity=0.5, align=center]

\tikzstyle{umlinfoline} = [draw, draw opacity=0.5, dotted, thick]
\tikzstyle{umlinherit} = [draw, ->, >= open triangle 60]
\tikzstyle{umlrelated} = [draw, above]
\tikzstyle{umloperate} = [arrow, dashed, above]

%%
%% Functions for constructing Tikz nodes
%%

%%
% Create capability space node
%
% argument 1: node name, also used as prefix for the individual slots
% argument 2: maximum index
% argument 3: node arguments
%
% Uses tikz style "capslot"
%
\newcommand\capspacenode[3]{
	\node[#3] (#1) {
		\begin{tikzpicture}
			\begin{scope}[start chain,node distance=0,rounded corners=0]
				\foreach \i in {0,1,...,#2} {
					\node [on chain,capslot,draw] (#1\i) {};
					\path (#1\i) node[yshift=0.5ex, xshift=-0.5ex, inner sep=0.5ex,
					                  text=black!60] {\tiny \i};
				}
				\node [on chain,capslot, fill=none, draw=none, outer sep=0.5ex] {$\ldots$};
			\end{scope}
		\end{tikzpicture}
	};
}

%%
% Create RPC object node
%
% argument 1: node name, also used as prefix for the individual slots
% argument 2: node arguments
% argument 3: capability name
% argument 4: node content
% argument 5: capability node arguments
%
% The capability node will be named #1cap.
% The object node will be named #1obj.
%
\newcommand\rpcobjectnodebase[5] {
	\node[#2] (#1) {
		\begin{tikzpicture}
			\node [draw, left color=blue!20, right color=white, minimum size=0pt,
			       thick, inner sep=1ex, rounded corners=0.5ex, dropshadow]
			       (#1obj) {#4};
			\node [outer sep=0pt, capability, #5]
			       (#1cap) {#3};
			\path [draw, dropshadow, very thick] (#1cap) -- node (#1link) {} (#1obj);
		\end{tikzpicture}
	};
}

%%
% Create RPC object node with the capability to the right of the object
%
% The four arguments are the same as for 'rpcobjectnodebase'.
%
\newcommand\rpcobjectrnode[4] {
	\rpcobjectnodebase{#1}{#2}{#3}{#4}{right=1.5ex of #1obj} }

%%
% Create RPC object node with the capability to the left of the object
%
% The four arguments are the same as for 'rpcobjectnodebase'.
%
\newcommand\rpcobjectlnode[4] {
	\rpcobjectnodebase{#1}{#2}{#3}{#4}{left=1.5ex of #1obj} }

%%
% Create compounding node
%
% argument 1:  node name
% argument 2:  node style
% argument 3:  node content
%
\newcommand\compoundnode[3] {
	\node[#2] (#1) {
		\begin{tikzpicture}[xshift=0, yshift=0, outer sep=0, inner sep=0,
		                    rounded corners=0]
			#3
		\end{tikzpicture}
	};
}

%%
% Create labeled compounding box node
%
% argument 1:  node name
% argument 2:  node style
% argument 3:  label to appear at the north-west corner
% argument 4:  content of the box
%
\newcommand\labeledcompoundnode[4] {
	\compoundnode{#1}{inner sep=3ex, #2}{#4}
	\path (#1.north west) node[compoundlabel] {#3};
}

%%
% Create kernel-user boundary
%
% argument 1:  nodes that are contained in the kernel,
%              specified as tikz style, e.g., 'fit=(node1) (node2)...'
%
\newcommand\kernelboundary[1] {
	\node [inner sep=4ex, #1] (kernelboundary) {};
	\draw [dashed, very thick, color=\kernelred] (kernelboundary.north west)
	      -- (kernelboundary.north east)
	      node[below left] {kernel};
}

%%
% Create node for an upward pointing thread
%
% argument 1:  node name
% argument 2:  node style
%
\newcommand\upwardthreadnode[2] {
	\node [thread, #2] (#1) {$\uplsquigarrow$}; }

%%
% Create node for an downward pointing thread
%
% argument 1:  node name
% argument 2:  node style
%
\newcommand\downwardthreadnode[2] {
	\node [thread, #2] (#1) {$\downrsquigarrow$}; }

%%
% Create entrypoint node
%
% argument 1:  node name
% argument 2:  node style
% argument 3:  component where the entrypoint resides
%
% The command creates sub nodes for the semicircle called #1ep and the
% thread called #1thread.
%
\newcommand\entrypointnode[3]{
	\node [above, inner sep=0, outer sep=0, #2] at (#3.south) (#1) {
		\begin{tikzpicture}

			\node [draw=black, draw opacity=0.4, ball color=blue, fill opacity=0.2,
			       rounded corners=0, shape=semicircle,
			       inner sep=1.3ex, outer sep=0, above]
			(#1ep) {};

			\path (#1ep.arc end) node[compoundlabel, right, yshift=1ex] {EP};

			\path (#1ep.arc start) [thread]
				node [left, xshift=-0.3ex, yshift=1ex] (#1thread) {$\uplsquigarrow$};

		\end{tikzpicture}
	};
}

%%
% Create path that illustrates a capability delegation
%
\newcommand\delegationpath{
	\path [color=black!30!blue!30, text=black,
	       decoration={markings,
	                   mark=between positions 0.03 and 1 step 1ex with {\arrow{latex}}},
	       postaction={decorate}]}

\newcommand\capability[1]{
	\begin{tikzpicture}[baseline=-0.6ex]
	\node [capability] {#1};
	\end{tikzpicture}
}

%%
%% Timeline diagrams
%%

\newcounter{numtimelines}

%%
% Create new vertical timeline
%
% argument: timeline name
%
\newcommand{\newtimeline}[1] {

	\stepcounter{numtimelines}

	\path (timelineanchor) node (#1)     {};
	\path (timelineanchor) node (last#1) {};

	\pgfkeyssetvalue{/timeline\thenumtimelines/name}{#1}

	\pgfkeyssetvalue{/timeline #1/state}{idle}
}

%%
% Draw vertical state representation of the specified timeline (internal)
%
% argument: timeline name
%
\newcommand{\finishtimeline}[1] {

	\def\state{\pgfkeysvalueof{/timeline #1/state}}

	\ifthenelse{\equal{\state}{idle}}{

		\draw[dashed, thick, draw opacity=0.1] (last#1) -- (#1);
	}{}

	\ifthenelse{\equal{\state}{active}}{

		\path (last#1)+(0,-0.1) node (top)    {};
		\path     (#1)+(0, 0.1) node (bottom) {};

		\path (last#1) node[inner sep=0pt, fit=(top) (bottom), activetimeline] {};
	}{}

	\path (#1) node (last#1) {};
}

%%
% Timeline environment
%
% The environment can only be used within a tikzpicture environment
%
\newenvironment{timelinediagram} {

	% reset timeline counter
	\setcounter{numtimelines}{0}

	% reset anchor used for next call of 'newtimeline'
	\path (0,0) node (timelineanchor) {};

	\newcommand{\timestepvector}{0,-1}

	%%
	% Add time step
	%
	\newcommand{\timestep} {

		\foreach \i in {1,...,\thenumtimelines}{

			\def\name{\pgfkeysvalueof{/timeline\i/name}}

			% move timeline forward in time
			\path (\name)+(\timestepvector) node (\name) {};
		}
	}

	%%
	% Activate timeline
	%
	\newcommand{\activate}[1] {
		\finishtimeline{##1}
		\pgfkeyssetvalue{/timeline ##1/state}{active}
	}

	%%
	% Deactivate timeline
	%
	\newcommand{\deactivate}[1] {
		\finishtimeline{##1}
		\pgfkeyssetvalue{/timeline ##1/state}{idle}
	}

	%%
	% Create transition from one timeline to another
	%
	\newcommand{\transition}[3] {
		%
		% The named 'transitionlabel' node can be used to attach further
		% information to the message. The unnamed second node is designated
		% for labeling simple transitions.
		%
		\draw[timelinemessage] (##1) -- node (transitionlabel) {} node[above] {##3} (##2);
		\deactivate{##1}
		\activate{##2}
	}

} {
	% finish all timelines
	\foreach \i in {1,...,\thenumtimelines}{
		\def\name{\pgfkeysvalueof{/timeline\i/name}}
		\finishtimeline{\name}
	}
}

%%
%% Tools for creating illustrations of memory ranges
%%

\newenvironment{memrange} {

	\newcommand{\alloc}[2]{
		\path (memrangeanchor) node[right=0ex, minimum width=##1, ##2] (currmemrangeanchor) {};
		\path (currmemrangeanchor.east) coordinate (memrangeanchor) {};
	}

	\newcommand{\remembersouth}[1]{
		\path (currmemrangeanchor.south) coordinate (##1) {}; }

	\newcommand{\remembersoutheast}[1]{
		\path (currmemrangeanchor.south east) coordinate (##1) {}; }

	\newcommand{\remembersouthwest}[1]{
		\path (currmemrangeanchor.south west) coordinate (##1) {}; }

	\begin{tikzpicture}[outer sep=0]
		% reset anchor used for appending allocations
		\path (0,0) coordinate (memrangeanchor) {};

} {
		% add some spacing to the right
		\path (memrangeanchor) node[right=0ex, minimum height=0, inner sep=0,
		                            minimum width=1ex] {};
	\end{tikzpicture}
}

% styles used for illustrating heap partitioning
\tikzstyle{heapalloc}  = [rectangle, minimum height=3ex, very thin, draw, draw opacity=0.5]
\tikzstyle{heapalloc1} = [heapalloc, top color=red!10!lightgray,
                                     bottom color=red!50!lightgray]
\tikzstyle{heapalloc2} = [heapalloc, top color=yellow!10!lightgray,
                                     bottom color=yellow!50!lightgray]
\tikzstyle{heapempty}  = [heapalloc, top color=white!10!lightgray,
                                     bottom color=white!50!lightgray]

% styles used for illustrating the component creation
\tikzstyle{memtype}     = [rectangle, minimum height=1ex, very thin, draw,
                           draw opacity=0.5]
\tikzstyle{memtext}     = [memtype, top color=red!10!lightgray,
                                    bottom color=red!50!lightgray]
\tikzstyle{memdata}     = [memtype, top color=yellow!10!lightgray,
                                    bottom color=yellow!50!lightgray]
\tikzstyle{memrodata}   = [memtype, top color=yellow!10!white,
                                    bottom color=yellow!50!white]
\tikzstyle{memavail}    = [memtype, top color=white!10!lightgray,
                                    bottom color=white!50!lightgray]
\tikzstyle{memmanaged}  = [memtype, top color=blue!10!lightgray,
                                    bottom color=blue!50!lightgray]
\tikzstyle{memreserved} = [memtype, top color=white!80!lightgray,
                                    bottom color=white!80!lightgray,
                                    pattern=north east lines,
                                    pattern color=black]

%%
%% Wheel used for illustrating the audio-out session interface
%%

\newenvironment{wheel}[1] {

	%%
	% Draw slices
	%
	% argument 1: range to iterate over the angles, in steps of 10
	% argument 2: style used for drawing the slices
	%
	\newcommand{\slices}[2]{
		\foreach \i in {##1} {
			\path[##2]
				(\i + 2:#1*0.2)  -- (\i + 2:#1*0.95) --
				(\i + 8:#1*0.95) -- (\i + 8:#1*0.2) --cycle;
		}
	}

	%%
	% Remember slice as tikz coordinate
	%
	% argument 1: angle
	% argument 2: name of coordinate
	%
	\newcommand{\rememberouter}[2]{
		\path (##1 + 5:#1*0.95) coordinate (##2) {}; }

	\newcommand{\rememberinner}[2]{
		\path (##1 + 5:#1*0.85) coordinate (##2) {}; }

	\begin{tikzpicture}

		\path[draw, draw opacity=0.4, inner color=white, outer color=white!80!black, even odd rule]
			(0,0) circle (#1);

		\foreach \i in {0, 10,...,350} {
			\path[white, draw, draw opacity=0.5] (0,0) -- (\i:#1); }

} {
	\end{tikzpicture}
}

%%
%% API specification
%%

%
% Common color definitions for the API spec
%
\definecolor{apinamespace} {rgb}{1.0,0.95,0.78}
\definecolor{apimethod}    {rgb}{0.8,0.9,0.7}
\definecolor{apiclass}     {rgb}{0.8,0.85,0.9}
\definecolor{apifunction}  {rgb}{1.0,0.85,0.6}

%
% Tikz style definitions used in the API spec
%
\tikzstyle{apioutline}    = [draw=black!15]
\tikzstyle{apititlelabel} = [shape=signal, draw, inner sep=0.5ex,
                             minimum height=3ex, top color=white,
                             draw opacity=0.3,
                             signal to=east]

\tikzstyle{apinamespacelabel} = [apititlelabel, bottom color=apinamespace]
\tikzstyle{apiclasslabel}     = [apititlelabel, bottom color=apiclass]
\tikzstyle{apimethodlabel}    = [apititlelabel, bottom color=apimethod]
\tikzstyle{apifunctionlabel}  = [apititlelabel, bottom color=apifunction]

\tikzstyle{apisectionlabel} = [at=(leftanchor), inner xsep=1ex, inner ysep=0.8ex,
                               text=apibg!20!black, font=\bfseries \small]

%%
% API description box
%
% argument 1: initial background color in r,g,b
%
\newenvironment{apibox}[1] {

	\path (0,1ex) node {}; % enforce a bit of spacing above the box

	\path (0,0)        coordinate (leftanchor);
	\path (leftanchor) coordinate (origleftanchor);

	\path (1.0\textwidth,0) coordinate (righttop);

	\definecolor{apibg} {rgb}{#1}

	\tikzstyle{apibg} = [fill=apibg!50!white]

	\newcommand{\apiboxtitle}[2]{

		% execute argument
		##1

		%
		% Define orig anchor (the background starts here), and anchor
		% (the position of the background to be processed)
		%
		\path (leftanchor |- namespacelabel.east)  coordinate (origleftanchor);
		\path (leftanchor |- namespacelabel.south) coordinate (leftanchor);

		%
		% Annotation at the right-top corner
		%
		\node[at=(righttop |- origleftanchor), anchor=north east,
		      text opacity=0.8, minimum size=2ex, inner sep=2ex] (annotation) {##2};

		% process first part of the background, including right counded corner
		\begin{scope}[on background layer]
			\path[apibg]               (origleftanchor)
			   {[rounded corners=5] -- (righttop |- origleftanchor)}
			                        -- (righttop |- leftanchor)
			                        -- (leftanchor) --cycle;
			\path[apioutline]          (origleftanchor)
			   {[rounded corners=5] -- (righttop |- origleftanchor)}
			                        -- (righttop |- leftanchor);
		\end{scope}

		% advance origleftanchor to be used as start pos for next bg step
		\path (leftanchor) coordinate (origleftanchor);
	}

	%%
	% Create API box title for a global namespace overview
	%
	% argument 1: annotation (at the top-right corner)
	%
	\newcommand{\apiglobalnamespaceboxtitle}[1]{

		\apiboxtitle{

			%
			% Invisible namespacelabel
			%
			\node[at=(leftanchor), anchor=north west]
				(namespacelabel) {};

		}{##1}
	}

	%%
	% Create API box title for a namespace overview
	%
	% argument 1: namespace
	% argument 2: annotation (at the top-right corner)
	%
	\newcommand{\apinamespaceboxtitle}[2]{

		\apiboxtitle{

			%
			% Segmented title label
			%
			\node[apinamespacelabel, at=(leftanchor), anchor=north west]
				(namespacelabel) {##1};

		}{##2}
	}

	%%
	% Create API box title for a global-function description
	%
	% argument 1: namespace
	% argument 2: function name
	% argument 3: annotation (at the top-right corner)
	%
	\newcommand{\apifunctionboxtitle}[3]{

		\apiboxtitle{

			%
			% Segmented title label
			%
			\node[apinamespacelabel, at=(leftanchor), anchor=north west, text opacity=0.5]
				(namespacelabel) {##1};
			\node[apifunctionlabel, at=(namespacelabel.east), anchor=west, signal from=west]
				(classlabel) {##2};

		}{##3}
	}

	%%
	% Create API box title for a class description
	%
	% argument 1: namespace
	% argument 2: class
	% argument 3: annotation (at the top-right corner)
	%
	\newcommand{\apiclassboxtitle}[3]{

		\apiboxtitle{

			%
			% Segmented title label
			%
			\node[apinamespacelabel, at=(leftanchor), anchor=north west, text opacity=0.5]
				(namespacelabel) {##1};
			\node[apiclasslabel, at=(namespacelabel.east), anchor=west, signal from=west]
				(classlabel) {##2};

		}{##3}
	}

	%%
	% Create API box title for a class method
	%
	% argument 1: namespace
	% argument 2: class
	% argument 3: function
	% argument 4: annotation (at the top-right corner)
	%
	\newcommand{\apimethodboxtitle}[4]{

		\apiboxtitle{

			%
			% Segmented title label
			%
			\node[apinamespacelabel, at=(leftanchor), anchor=north west, text opacity=0.5]
				(namespacelabel) {##1};
			\node[apiclasslabel, at=(namespacelabel.east), anchor=west, text opacity=0.5, signal from=west]
				(classlabel) {##2};
			\node[apimethodlabel, at=(classlabel.east), anchor=west, signal from=west]
				(functionlabel) {##3};
		}{##4}
	}

	%%
	% Append left-aligned content to API box
	%
	% argument: content
	%
	\newcommand{\apiboxcontent}[1]{

		\node[at=(leftanchor), anchor=north west, minimum size=1ex,
		      inner sep=1ex] (content) {##1};

		\path (leftanchor |- content.south) coordinate (leftanchor);
	}

	%%
	% Add vertical space to API box
	%
	% argument: space
	%
	\newcommand{\apiboxvspace}[1]{

		\path (leftanchor)+(0,-##1) coordinate (leftanchor);
	}

	%%
	% Append centered content to API box
	%
	% argument: content
	%
	\newcommand{\apiboxcenteredcontent}[1]{

		\path (leftanchor) -- coordinate (mid) (righttop |- leftanchor);
		\node[at=(mid), anchor=north, minimum size=1ex,
		      inner sep=1.5ex] (content) {##1};

		\path (leftanchor |- content.south) coordinate (leftanchor);
	}

	%%
	% Append section to API box
	%
	% argument 1: section label text
	% argument 2: section background color as r,g,b
	%
	\newcommand{\apisection}[2]{

		% create section label with transparent text to obtain its bounding box
		\node[apisectionlabel, at=(leftanchor), text opacity=0, anchor=north west]
			(sectionlabel) {##1};

		% advance anchor to extend the old background to the south of the tab
		\path (sectionlabel.south west) coordinate (leftanchor);

		%
		% Complete the background of the previous part of the API box
		%
		\begin{scope}[on background layer]
			\path[apibg] (origleftanchor)
			          -- (righttop |- origleftanchor)
			          -- (righttop |- leftanchor)
			          -- (leftanchor)
			          --cycle;

		\end{scope}

		% switch to using the new color
		\definecolor{apibg} {rgb}{##2}

		% helper coordinates for drawing the tab
		\path (sectionlabel.south east)+(4ex,1ex) coordinate (mid);
		\path (sectionlabel.south west)+(0,-2ex)  coordinate (below);

		%
		% Draw tab hosting the section label
		%
		\path [top color=apibg!90!black, bottom color=apibg!50!white]
		      (sectionlabel.north west)
		         {[rounded corners=7] -- (sectionlabel.north east)
		                              -- (mid)}
		                              -- (righttop |- mid)
		                              -- (righttop |- below)
		                              -- (sectionlabel.south west |- below)
		                              --cycle;

		\path[apioutline] (origleftanchor)
		               -- (leftanchor);
		\path[apioutline] (righttop |- origleftanchor)
		               -- (righttop |- leftanchor);

		\path [draw=apibg!80!black]
		      (sectionlabel.north west)
		         {[rounded corners=7] -- (sectionlabel.north east)
		                              -- (mid)
		                              -- (righttop |- mid)};

		%
		% Another instance of the section label with visible text
		%
		\node[apisectionlabel, at=(sectionlabel.north west), anchor=north west] {##1};

		\path (leftanchor)                       coordinate (origleftanchor);
		\path (leftanchor |- sectionlabel.south) coordinate (leftanchor);
	}
} {
	% make sure the box is large enough to fit the annotation
	\node[fit=(leftanchor) (annotation.south)] (maxhelper) {};
	\path (leftanchor |- maxhelper.south) coordinate (leftanchor);

	%
	% Finalize background up to the current leftanchor
	%
	\begin{scope}[on background layer]
		\path[apibg]               (origleftanchor)
		                        -- (righttop |- origleftanchor)
		  {[rounded corners=5]  -- (righttop |- leftanchor)
		                        -- (leftanchor)} --cycle;
	\end{scope}

	\path[apioutline]          (righttop |- origleftanchor)
	  {[rounded corners=5]  -- (righttop |- leftanchor)
	                        -- (leftanchor)
	                        -- (origleftanchor)};

	\path (leftanchor)+(0,-0.5ex) node {}; % enforce a bit of spacing below the box
}


code:
%%
%% Libraries and packages used by the tikz files
%%

\usepackage{fdsymbol}

\usepackage{tikz}
\usepackage{ifthen}
\usepackage{circuitikz}

% listings package used for verbatim environments
\usepackage{listings}
\lstset{basicstyle=\ttfamily}

\usetikzlibrary{shapes,
                arrows,
                shadows.blur,
                fit,
                chains,
                fadings,
                patterns,
                decorations.pathmorphing,
                decorations.markings,
                shapes,
                scopes,
                backgrounds}

%%
%% TikZ fading definitions
%%

%%
% Fading used in timeline diagrams
%
\begin{tikzfadingfrompicture}[name=timeline fade right]
	\shade[left color=transparent!0,
	       right color=transparent!60] (0,0) rectangle (2,2);
\end{tikzfadingfrompicture}

%%
% Fading used in flow charts
%
\begin{tikzfadingfrompicture}[name=flow fade]
	\shade[left color=transparent!0,
	       right color=transparent!60] (0,0) rectangle (2,2);
\end{tikzfadingfrompicture}

\newcounter{decrhelper}


code:
%%
%% Header used for building a stand-alone version of a Tikz image
%%

\documentclass{article}

\input{tikz-preamble.tex}

% use the bounding box of the Tikz image as PDF size
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}

\begin{document}

% include the common tikz styles and commands used throughout the manual
\input{tikz-common.tex}


code:
\begin{tikzpicture}[remember picture,overlay]

	\definecolor{titlecolor}   {rgb}{0.75,0.75,1.0}

	\draw [top color=black!70, bottom color=titlecolor]
		(current page.south west) rectangle (current page.north east);

	%%
	% Calculate coordinates for a single logo stripe
	%
	% argument 1: base angle of the stripe
	% argument 2: fan angle
	%
	% In addition to the arguments, the function relies on the prior
	% definition of the coordinates 'leftbase', 'rightbase', and 'righttop'.
	%
	\newcommand\calccoordinates[2]{

		\def\baseangle{#1}
		\def\steepangle{#2}

		\path (rightbase)+(\baseangle+90:10cm) coordinate (rightfarup);

		\path (lefttop)+(\steepangle+\baseangle+270:100cm) coordinate (tmp);
		\coordinate (touchpoint) at (intersection of leftbase--rightbase
		                                         and lefttop--tmp);

		\path (touchpoint)+(\steepangle+\baseangle:100cm) coordinate (tmp);
		\coordinate (righttop) at (intersection of rightbase--rightfarup
		                                         and touchpoint--tmp);
	}

	\tikzstyle{logospike} = [fill, black, opacity=0.9,
	                         path fading=flow fade]

	\path (current page.south west) -- coordinate[pos=0.15] (midleft) (current page.north west);
	\path (current page.south east) -- coordinate[pos=0.15] (midright) (current page.north east);

	\path (midleft)           coordinate (leftbase);
	\path (midright)          coordinate (rightbase);
	\path (leftbase)+(90:7cm) coordinate (lefttop);

	\def\maxiterations{5}
	\foreach \i in {0,...,\maxiterations} {

		\calccoordinates{0 + \i*11}{11}

		% draw polygon
		\ifthenelse{\i = 0} {
			% let lowest spoke go right to the bottom of the page
			\path[logospike]
			                 (current page.south west)
			              -- (current page.south east)
			              -- (righttop) -- (touchpoint)
			              -- (lefttop) --cycle;
		} {
			\path[logospike]
				(leftbase) -- (rightbase) -- (righttop) -- (touchpoint)
				           -- (lefttop) --cycle;
		}

		% init coordinates for next iteration

		\def\nextangle{0 + 11 + \i*11}
		\def\nextspace{2cm - \i*0.3cm}

		\path (touchpoint) -- ++(\nextangle:\nextspace)
		                   -- ++(\nextangle + 90:\nextspace)
		                   coordinate (leftbase);

		\path (righttop) -- ++(\nextangle + 90:\nextspace)
		                 coordinate (rightbase);

		\path (lefttop) -- ++(\nextangle:\nextspace)
		                -- ++(\nextangle + 90:0.6*\nextspace)
		                coordinate (lefttop);
	}

	\definecolor{titlecol} {rgb}{1,1,1}

	\path (current page.north)
		node[below=1cm, font=\normalsize \sffamily, color=titlecol, scale=10,
		     opacity=0.8] (genode) {GENODE};

	\path (genode)
		node[below=2cm, font=\normalsize \sffamily, color=titlecol,
		     opacity=0.8, scale=2.65] (osf) {Operating System Framework 22.05};

	\definecolor{subtitlecol} {rgb}{0.95,0.90,0.5}

	\path (current page.south)
		node[above=1.8cm, font=\normalsize \sffamily, color=subtitlecol,
		     scale=5] (subtitle) {Foundations};

	\path (current page.south)+(0cm,0.8cm)
		node[anchor=south, font=\normalsize \sffamily, color=black,
		     opacity=0.7, scale=2] {Norman Feske};

\end{tikzpicture}


code:
\begin{tikzpicture}

	\tikzstyle{partition} = [rectangle, draw, text centered,
	                         top color=white,
	                         bottom color=black!5,
	                         dropshadow,
	                         inner sep=0.2ex,
	                         outer sep=0,
	                         minimum height=7ex,
	                         minimum width=5ex,
	                         align=center,
	                         draw=black!50]

	\node[partition, minimum width=25ex] (genodepartition)
		{genode\\\\\em{\tiny ext2}};
	\node[partition, minimum width=25ex,right=0 of genodepartition] (homepartition)
		{home\\(LUKS encrypted)\\\em{\tiny ext4}};
	\node[partition,right=0 of homepartition] (rescuepartition)
		{boot / rescue\\\\\em{\tiny ext4 4GiB}};

	\path (genodepartition.south)
		node[below=1ex, inner sep=1ex, anchor=north, align=left] (genodecontent) {
			\texttt{/boot} \\
			\texttt{/genode} \\
			\texttt{linux.vdi}
		};

	\path (genodecontent.south)+(0,1ex) coordinate (genodecontent);

	\path (rescuepartition.south west)
		node[below=1ex, inner sep=1ex, anchor=north west, align=left] {
			- GRUB \\
			- GNU/Linux \\
			- X11 \\
			- VirtualBox \\
			- mount home \\
			- mount genode \\
		};

	\path (genodepartition.south west)
		node[partition, minimum width=20ex, below=18ex, anchor=north west] (vmrootpartition)
			{Rich GNU/Linux\\\em{\tiny ext3}};
	\node[partition, minimum width=25ex,right=0 of vmrootpartition] (vmhomepartition)
		{home\\(LUKS encrypted)\\\em{\tiny ext4}};

	\draw[densely dotted] (vmrootpartition.north west) -- (genodecontent.south);
	\draw[densely dotted] (vmrootpartition.north east) -- (genodecontent.south);

	\draw[densely dotted] (vmhomepartition.north west) -- (homepartition.south west);
	\draw[densely dotted] (vmhomepartition.north east) -- (homepartition.south east);

	\path (genodepartition.north west)
		node[color=black!50, anchor=south west, inner sep=0.2ex]
			{Partitions of physical disk};

	\path (vmrootpartition.north west)
		node[color=black!50, anchor=south west, inner sep=0.2ex]
			{Virtual-machine disks};

\end{tikzpicture}


code:
\begin{tikzpicture}

	\definecolor{appcolor}       {rgb}{1,1,0.7}
	\definecolor{nitpickercolor} {rgb}{0.9,0.5,0.4}

	\tikzstyle{treenode} = [component, path fading=flow fade, align=center,
	                        rounded corners=1]

	\tikzstyle{basenode}     = [treenode, minimum width=12ex, minimum height=6ex, bottom color=nitpickercolor]
	\tikzstyle{minibasenode} = [basenode, minimum size=2ex]
	\tikzstyle{appnode}      = [treenode, minimum width=12ex, minimum height=6ex, bottom color=appcolor]
	\tikzstyle{miniappnode}  = [appnode, minimum size=2ex]

	%
	% Components
	%

	% init
	\node[treenode, minimum width=12ex, minimum height=5ex] (init) {Init};

	% base components
	\node[basenode, above=8ex of init, xshift=-14ex] (nitpicker) {Nitpicker\\GUI};
	\node[basenode, above=8ex of init, xshift=0ex]  (wm)        {Window\\Manager};
	\node[minibasenode, left=1ex of nitpicker] (base1) {};
	\node[minibasenode, left=1ex of base1] (base2) {};
	\node[minibasenode, left=1ex of base2] (base3) {};
	\node[basenode, above=8ex of init, xshift=14ex] (climonitor) {CLI monitor};

	\node[umlinfo, align=left, left=1ex of base3, scale=0.5] {
		timer \\
		acpi\_drv \\
		acpi\_report\_rom \\
		platform\_drv \\
		ahci\_drv \\
		part\_blk \\
		log\_file\_terminal \\
		log \\
		rump\_fs \\
		wifi\_drv \\
		ps2\_drv \\
		usb\_drv \\
		fb\_drv \\
		rtc\_drv \\
		trace\_subject\_reporter \\
		input\_merger \\
		report\_rom \\
		nitpicker \\
		wm\_report\_rom \\
		wm \\
		layouter \\
		decorator \\
		vbox\_pointer \\
		shared\_fs \\
		config\_fs \\
		config\_rom \\
		rom \\
		cli\_nit\_fb \\
		cli\_terminal
	};

	% apps
	\node[appnode, above=8ex of climonitor, xshift=-7ex] (vbox) {VirtualBox};
	\node[appnode, above=8ex of climonitor, xshift=7ex] (noux) {Noux};
	\node[miniappnode, left=1ex of vbox] (app1) {};
	\node[miniappnode, left=1ex of app1] (app2) {};
	\node[miniappnode, left=1ex of app2] (app3) {};

	%
	% Parent-child relationships
	%

	\tikzstyle{treechildarrow} = [arrow, thick, opacity=0.2]

	\path[treechildarrow] (init) -- (nitpicker.south);
	\path[treechildarrow] (init) -- (wm.south);
	\path[treechildarrow] (init) -- (climonitor.south);

	\path[treechildarrow] (climonitor) -- (vbox.south);
	\path[treechildarrow] (climonitor) -- (noux.south);

	%
	% Session relationships
	%

	\tikzstyle{treesessionarrow} = [arrow, thick, densely dashed]

	% cli monitor -> wm
	\path[treesessionarrow] (climonitor.220)
		.. controls +(0,-3ex) and +(0,-3ex) .. (wm.320);

	% window manager -> nitpicker
	\path[treesessionarrow] (wm.220)
		.. controls +(0,-3ex) and +(0,-3ex) .. (nitpicker.320);

	% nitpicker to base component
	\path[treesessionarrow] (nitpicker.south)
		.. controls +(0,-3ex) and +(0,-6ex) .. (base2.south);

\end{tikzpicture}


code:
\begin{tikzpicture}

	\tikzstyle{treenode} = [component, path fading=flow fade, align=center,
	                        rounded corners=1,
	                        minimum width=12ex, minimum height=5ex]
	\tikzstyle{vfs} = [align=center, draw, opacity=0.4, scale=0.7,
	                   rounded corners=1, fill=white,
	                   minimum width=5ex, minimum height=2ex]

	%
	% Components
	%

	\node[treenode] (init) {Init};

	\node[treenode, above=8ex of init, xshift=-14ex] (vfs) {VFS server\\\\};
	\node[treenode, above=8ex of init] (fsrom) {fs\_rom};
	\node[treenode, above=8ex of init, xshift=14ex] (bash) {bash\\\\};
	\node[treenode, above=4ex of bash] (vim) {Vim\\\\};

	\node[vfs, above=1ex of vfs.south, xshift=5ex] (vfsvfs) {VFS};
	\node[left=1ex of vfsvfs, scale=0.5, yshift=-2ex] (devterminal) {Terminal};
	\node[left=1ex of vfsvfs, scale=0.5, yshift=0ex] (bashtar) {ROM bash.tar};
	\node[left=1ex of vfsvfs, scale=0.5, yshift=2ex] (vimtar) {ROM vim.tar};

	\path[arrow] (devterminal.east) -- (vfsvfs);
	\path[arrow] (bashtar.east) -- (vfsvfs);
	\path[arrow] (vimtar.east) -- (vfsvfs);

	\node[vfs, above=1ex of bash.south, xshift=0ex] (bashvfs) {VFS};
	\node[vfs, above=1ex of vim.south, xshift=0ex] (vimvfs) {VFS};

	%
	% Parent-child relationships
	%

	\tikzstyle{treechildarrow} = [arrow, thick, opacity=0.2]

	\path[treechildarrow] (init) -- (vfs.south);
	\path[treechildarrow] (init) -- (fsrom.south);
	\path[treechildarrow] (init) -- (bash.south);
	\path[treechildarrow] (bash) -- (vim.south);

	%
	% Session relationships
	%

	\tikzstyle{treesessionarrow} = [arrow, thick, densely dashed]

	\path[treesessionarrow] (fsrom.250)
		.. controls +(250:4ex) and +(320:4ex) .. (vfs.320);

	\path[treesessionarrow] (bash.230)
		.. controls +(230:4ex) and +(320:4ex) .. (fsrom.320);

	\path[treesessionarrow] (bashvfs.270)
		.. controls +(257:8ex) and +(310:7ex) .. (vfs.310);

	\path (bash.center)+(3ex,0) coordinate (midvimvfs) {};

	\path[treesessionarrow] (vimvfs.290)
		.. controls +(290:4ex) and +(90:4ex) .. (midvimvfs)
		.. controls +(270:14ex) and +(300:8ex) .. (vfs.300);

	\path[treesessionarrow] (devterminal)
		.. controls +(270:3ex) and +(90:7ex) .. (init.230);

\end{tikzpicture}


code:
\begin{tikzpicture}

	\definecolor{arrowcol} {rgb}{0.8,0.9,0.7}

	\node[draw, dropshadow, path fading=flow fade, shape=double arrow,
	      draw opacity=0.5,
	      top color=arrowcol, bottom color=black!50!arrowcol,
	      double arrow head extend=1.5ex,
	      inner xsep=5ex, inner ysep=1.5ex]
	      (arrow) { };

	\node[left=0ex  of arrow, minimum width=30ex] {};
	\node[right=0ex of arrow, minimum width=30ex] {};

	\node[left=2ex  of arrow, yshift=0.1ex] { \Large Utilization };
	\node[right=2ex of arrow, yshift=-0.3ex] { \Large Accountability };

\end{tikzpicture}


code:
\begin{tikzpicture}

	\definecolor{appcolor}        {rgb}{1,1,0.7}
	\definecolor{defaultcolor}    {rgb}{1,1,1}

	\tikzstyle{treenode} = [component, path fading=flow fade, align=center,
	                        rounded corners=1, minimum height=6ex]

	\tikzstyle{service} = [draw=black, draw opacity=0.4, ball color=defaultcolor, fill opacity=0.2,
	                       rounded corners=0, shape=semicircle,
	                       inner sep=1.3ex, outer sep=0, above]

	\tikzstyle{appnode}    = [treenode, bottom color=appcolor]

	%
	% Components
	%

	\coordinate (anchor);

	% pkg/drivers_fpga-zynq
	\node[treenode, minimum width=26ex, at=(anchor)] (fpga) {pkg/drivers\_fpga-zynq};
	\path (fpga.north) node[service, scale=0.4] (platformservice) {};
	\path (fpga.north) node[scale=0.7, yshift=-1.5ex] {Platform};

	% driver manager
	\node[appnode, minimum width=26ex, above right=2ex and 20ex of fpga] (drvmanager)  {Zynq Driver Manager};

	% drivers subsystem
	\node[treenode, minimum width=26ex, above left=2ex and 20ex of drvmanager] (drivers)  {Drivers Subsystem};

	% config / state information flow
	\tikzstyle{infoflow} = [opacity=0.5,
	                        decoration={markings,
	                        mark=between positions 0.03 and 1 step 1ex with {\arrow{latex}}},
	                        postaction={decorate}]

	\path[infoflow] (fpga.-170)+(0,-10ex) -- node[pos=-0.2] {devices} (fpga.-160);
	\path[infoflow] (fpga.-150)+(0,-11ex) -- node[pos=-0.2] {fpga.bit} (fpga.-140);
	\path[infoflow] (fpga.-30) +(0,-11ex) -- node[pos=-0.2] {fpga\_devices} (fpga.-40);
	\path[infoflow] (fpga.-10) +(0,-10ex) -- node[pos=-0.2] {policy} (fpga.-20);

	\path[infoflow] (fpga.east)
		.. controls +(10ex,0) and +(0ex,-10ex) ..
		   coordinate[pos=0.3] (annotation) node[below] {devices} (drvmanager.south);

	\path[infoflow] (drvmanager.north)
		.. controls +(0,10ex) and +(10ex,0) ..
		   coordinate[pos=0.3] (annotation) node[above] {init.config} (drivers.east);

	%
	% Sessions
	%
	\tikzstyle{treesessionarrow} = [arrow, thick]
	\path[treesessionarrow] (drivers) -- (platformservice);

\end{tikzpicture}


code:
GENODE_VERSION = 22.05
PDF = genode-platforms-$(subst .,-,$(GENODE_VERSION)).pdf

all: $(PDF)

TEXFILE := misc.tmp
SHELL = bash

#
# Definition of the order of chapters
#
# Lines can be commented-out by prefixing them with '#'.
#
define CHAPTERS
title
intro
porting_guide
preparations
warmup
serial
kernel_skeleton
debugging
user_land
testing
device_access
platform_driver
linux
dts_pruning
networking
display
touchscreen
trimming_drivers
telephony
endef

default: $(PDF)

$(PDF): manual.gosh
	ln -s ../foundations

# concatenate chapters except for those that are commented out
$(PDF:.pdf=.txt): $(addsuffix .txt,$(patsubst #%,,$(strip $(CHAPTERS))))
	cat $^ > $@

$(PDF): $(PDF:.pdf=.txt) manual.gosh Makefile \
       $(wildcard img/*.pdf) \
       $(wildcard img/*.tikz)
	gosh --style manual.gosh $(PDF:.pdf=.txt) > $(TEXFILE).tex
	pdflatex $(TEXFILE).tex
	pdflatex $(TEXFILE).tex
	pdflatex $(TEXFILE).tex
	cp $(TEXFILE).pdf $@
	rm -f $(TEXFILE) $(TEXFILE).*

$(PDF): img

img:
	ln -sf ../img

clean_manual:
	rm -f $(TEXFILE) $(TEXFILE).* $(PDF:.pdf=.txt) $(PDF)
	rm -f img

clean: clean_manual

path: platforms/Makefile


code:
Low-level debugging
===================

Some kids from the city once told me about programs called "debuggers". They
also use a technology named "green light" to cross the streets. City kids. As
we are still far away from urban territory, we are in need of the rural ways
of debugging. What are our options?

Remember, at the end of the previous section,
we were greeted with the first life sign of the kernel:

! Error: Assertion failed: id < _count && _cpus[id].constructed()
! Error:   File: /.../repos/base-hw/src/core/kernel/cpu.cc:205
! Error:   Function: Kernel::Cpu& Kernel::Cpu_pool::cpu(unsigned int)

This raises the questions: What is the trouble about? How did we get there?
What went wrong?
Thankfully, the message gives us a concrete reference to the code _cpu.cc_ at
line 205.

! Cpu & Cpu_pool::cpu(unsigned const id)
! {
!     assert(id < _count && _cpus[id].constructed());
!     return *_cpus[id];
! }

By looking at this code, I'm tempted to draw the connection to the corners we
cut regarding the 'Board::Cpu::wake_up_all_cpus' method, which we deliberately
left empty. But let us leave this speculation for later.

To get hold of the situation, it is useful to know which part of the condition
fails. This can be revealed by adding the following instrumentation at the
beginning of the method.

! Genode::log("cpu: id=", id, " _count=", _count, " "
!             "constructed=", _cpus[id].constructed());

The 'Genode::log' function is declared in the _base/log.h_ header. Note that
it relies on a fair bit of framework infrastructure such as synchronization
primitives. In desperate situations during the debugging of lowest-level
framework code, the 'Genode::raw' function can become handy as a drop-in
replacement. In contrast to 'log', the 'raw' function relies on less
infrastructure. In practice, I use 'log' by default and 'raw' as last resort.
After rebuilding the system image and rebooting the board, it turns out that
the 'log' function works well at this point.

! ...
! cpu: id=0 _count=4 constructed=0
! Error: Assertion failed: id < _count && _cpus[id].constructed()

The instrumentation tells us that the first element of the '_cpus' array has
not been properly constructed. But how to find out why? We ultimately need to
know the call chain that led to execution of the 'Cpu_pool::cpu' method.

Option 1: Walking the source code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The most obvious approach is studying the source code, and determining the
immediate callers of the method using 'grep'.

! repos/base-hw$ grep -r "\<cpu("

Unfortunately, "cpu" is a pretty bad pattern to grep for. It is too generic.
However, we know that the code in question must reside inside _repos/base-hw/_
and can thereby restrict the search to only this part of the source tree.
Furthermore, by using "\<" (match only the start of a word) and appending "("
to the pattern (as expected at the caller site), we can narrow down the number
of matches to a useful level.

! src/test/cpu_quota/main.cc:                  env.cpu()),
! src/test/cpu_quota/main.cc:       Cpu_session::Quota quota = env.cpu().quota();
! src/core/spec/arm_v8/virtualization/kernel/vm.cc: _vcpu_context(cpu_pool().cpu(cpu))
! src/core/spec/arm_v8/virtualization/kernel/vm.cc: affinity(cpu_pool().cpu(cpu));
! src/core/spec/arm_v7/virtualization/kernel/vm.cc: _vcpu_context(cpu_pool().cpu(cpu))
! src/core/spec/arm_v7/virtualization/kernel/vm.cc: affinity(cpu_pool().cpu(cpu));
! src/core/kernel/kernel.cc:    Cpu &cpu = cpu_pool().cpu(Cpu::executing_id());
! src/core/kernel/cpu_mp.cc:    Irq(Board::Pic::IPI, cpu), cpu(cpu)
! src/core/kernel/cpu.h:        Cpu & cpu(unsigned const id);
! src/core/kernel/cpu.h:        Cpu & primary_cpu() { return cpu(Cpu::primary_id()); }
! src/core/kernel/cpu.h:        Cpu & executing_cpu() { return cpu(Cpu::executing_id()); }
! src/core/kernel/cpu.h:            for (unsigned i = 0; i < _count; i++) func(cpu(i));
! src/core/kernel/cpu.cc:Cpu & Cpu_pool::cpu(unsigned const id)
! src/core/kernel/cpu_up.cc:Kernel::Cpu::Ipi::Ipi(Kernel::Cpu & cpu) : ...
! src/core/kernel/cpu_context.h:        void cpu(Cpu &cpu) { _cpu = &cpu; }
! src/core/kernel/thread.cc:    Cpu & cpu = cpu_pool().cpu(user_arg_2());

From these results, we can immediately disregard the lines referring to
_src/test/_. Also the virtualization-related matches are most likely not of
interest. When inspecting the remaining lines, the number of potential callers
comes down to 5:

! src/core/kernel/kernel.cc:    Cpu &cpu = cpu_pool().cpu(Cpu::executing_id());
! src/core/kernel/cpu.h:        Cpu & primary_cpu() { return cpu(Cpu::primary_id()); }
! src/core/kernel/cpu.h:        Cpu & executing_cpu() { return cpu(Cpu::executing_id()); }
! src/core/kernel/cpu.h:            for (unsigned i = 0; i < _count; i++) func(cpu(i));
! src/core/kernel/thread.cc:    Cpu & cpu = cpu_pool().cpu(user_arg_2());

With such a low amount of callers, we can apply brute force by adding
the following line just before each call.

! Genode::log(__FILE__, ":", __LINE__);

The compiler replaces '__FILE__' with a string of the file name of the source
code and '__LINE__' with a string of the line number where '__LINE__' appears
within the source file. Another useful magic macro is '__PRETTY_FUNCTION__',
which expands to the name of the surrounding function.

After rebooting the board with the instrumentations in place, we see the
origin of the call:

! /.../repos/base-hw/src/core/kernel/kernel.cc:25

A look at the surrounding code reveals that the function call originates from
a function called 'kernel':

! extern "C" void kernel()
! {
!   ...
!   Cpu &cpu = cpu_pool().cpu(Cpu::executing_id());
!   ...
! }

You might guess what's next?

! repos/base-hw$ grep -r "\<kernel(" *

There is only one caller, which is at _src/core/kernel/init.cc_ and
brings the 'kernel_init' function to our attention.

Granted, this step-wise instrumentation may feel a bit like chopping wood with
a nail clipper. But I sometimes enjoy the process anyway. By following call
chains in reverse by browsing and instrumenting the code, one develops some
kind of peripheral vision for the code around the call path, which fosters
the sense of familiarity with the code base.

Of course, using 'grep' manually as described above may be too archaic for
your taste. There exist plenty of dedicated tools (like ctags, cscope) and
IDEs for aiding source-code discovery after all. Personally, I prefer simple
tools. As a small life hack, I have put the following snippet in my Vim
configuration:

! nnoremap <leader>g :execute
!          \ "grep! -R -I --exclude-dir=.git
!                       \ --exclude=*.orig
!                       \ --exclude=.*.swp
!                       \ --exclude=*.rej
!                       \ --exclude=*~ "
!                       \ . shellescape("\\<" . expand("<cword>") . "\\>")
!                       \ . " ."<cr>:copen<cr><cr>

Similar to how the '*' and '#' commands search for the word under the cursor
in the current buffer, the '<leader>g' command above allows me to grep the
word under the cursor in the source tree and presents the results in a
quickfix window. So I can quickly jump to each occurrence and travel across
source files like a poor man's hypertext system.

That all said, once when ending up in a situation with many callers, the
approach of manually instrumenting all caller sites becomes a nuisance, which
leads us to the second option.

Option 2: One step of ground truth at a time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Instead of instrumenting all potential caller sites, we can let the return
addresses as found on the stack guide us by using the following line as
instrumentation:

! Genode::log("called from ", __builtin_return_address(0));

When executed, this line prints us the return address of the current function
scope. This address corresponds to the caller. By placing this line into the
'Cpu_pool::cpu' method, we get the following output.

! Starting kernel ...
!
! called from 0xffffffc000058720
! Error: Assertion failed: id < _count && _cpus[id].constructed()

The high number immediately tells us that the executed code
resides somewhere high up in virtual memory. That means, we have already passed
the bootstrap stage, the MMU is enabled, and core/kernel code is executed.
As explained in the
Section [Kernel skeleton],
the corresponding ELF binary resides at _build/arm_v8a/var/run/log.core_
and can be inspected via 'readelf'.

! build/arm_v8a$ readelf -l var/run/log.core | grep LOAD
!   LOAD           0x0000000000001000 0xffffffc000000000 0xffffffc000000000
!   LOAD           0x00000000000c1000 0xffffffc0000c0000 0xffffffc0000c0000
!   LOAD           0x00000000000ef5c0 0x0000000000000000 0x0000000000000000

The addresses of the ELF segments correlate nicely with the value printed by
our instrumentation. To determine the exact source-code location for the given
return address, the *objdump* tool becomes handy. It allows one to
disassemble an ELF binary while displaying the source-code intermixed. The
tool is specific to the used CPU architecture. That is, for 64-bit ARM, it is
called _genode-aarch64-objdump_. To use it interactively from the shell, the
tool chain's _bin/_ directory should be added to the shell's PATH variable:

! $ export PATH=/usr/local/genode/tool/current/bin/:$PATH

With the PATH variable set, we can disassemble the log.core ELF
binary and pipe the result to 'less' for inspection:

! build/arm_v8a$ genode-aarch64-objdump -lSd var/run/log.core | less

Note that the amount of output generated by objdump can be huge. By
replacing 'less' by 'wc -l' one can see that the output comprises
more than 300,000 lines! Still, this amount of data leaves 'less' unimpressed,
which leaves me impressed. We can simply search for our address
'ffffffc000058720' (with the 0x prefix stripped away) via the slash ('/')
command and end up at the following section of output:

! kernel():
! /.../base-hw/src/core/kernel/kernel.cc:25
! ffffffc000058718:       12001c21        and     w1, w1, #0xff
! ffffffc00005871c:       97fff8e3        bl      ffffffc000056aa8 <_ZN6Kernel8Cpu
! _pool3cpuEj>
! ffffffc000058720:       aa0003f4        mov     x20, x0
! /.../base-hw/src/core/kernel/kernel.cc:29
!         Cpu_job * new_job;

The source location _kernel.cc_ line 25 looks familiar.

Alternatively to going though the disassembled output of objdump,
the *addr2line* utility can be used to streamline the lookup of a source-code
location by a given instruction address.

! $ genode-aarch64-addr2line -e var/run/log.core 0xffffffc000058720
! /.../base-hw/src/core/kernel/kernel.cc:25

This is fast and convenient. But sometimes, in particular when code is
excessively inlined, the contextual information given by the objdump output
can be valuable. Most often, I scroll upwards until hitting the next
occurrence of a '.cc' file and watch silently the lines - header-file names
and fragments of source code - that scroll by. Again, peripheral vision at
play.

Option 3: Backtraces
~~~~~~~~~~~~~~~~~~~~

The '__builtin_return_address' feature of the compiler allows us to follow
the call chain one step at a time. Each step involves a manual
instrumentation, a compile-test cycle, and the invocation of the
'addr2line' utility.

To avoid such repetitive work, Genode provides the utility function
'Genode::backtrace()' to walk the stack and print the return addresses along
the way. This function is declared in the _os/backtrace.h_ header.
An instrumentation of the 'Cpu_pool::cpu' method would look as follows.

! #include <os/backtrace.h>
!
! Cpu & Cpu_pool::cpu(unsigned const id)
! {
!   Genode::backtrace();
!   ...
! }

To assist the 'backtrace()' function to parse stack frames correctly, the
Genode build system must be instructed to preserve frame-pointer information.
This can be achieved by placing the following line to the build directory's
_etc/tools.conf_ file. Note that by default there is no such file. So you will
have to create one containing this line.

! CC_OPT += -fno-omit-frame-pointer

After rebuilding and running the system image the next time, we are greeted
with quite a lot of output:

! Starting kernel ...
!
! 0xffffffc000058738
! 0xffffffc00000085c
! 0xffffffc0000568e0
! 0xffffffc000056a60
! 0xffffffc000057e44
! 0x400273d8
! 0x40026754
! 0x40010068
! 0xffffffc000058738

Each of the values starting with '0xfff...' is a valid return address and
can be used with objdump or addr2line as described above. To make matters
more convenient, the addr2line utility can be used in an "interactive" fashion
be running the following command in a separate terminal.

! build/arm_v8a$ genode-aarch64-addr2line -e var/run/log.core

With no address specified at the command line, the tool simply waits for
standard input. So we can paste multiple lines of the 'Genode::backtrace()'
output directly into it and get the following result:

! 0xffffffc000058738
! 0xffffffc00000085c
! 0xffffffc0000568e0
! 0xffffffc000056a60
! 0xffffffc000057e44
! /.../base-hw/src/core/kernel/kernel.cc:25
! :?
! /.../base-hw/src/core/spec/arm/virtualization/gicv2.h:22
! /.../base/include/util/reconstructible.h:56
! /.../base-hw/src/core/kernel/init.cc:64 (discriminator 1)

We can spot both of the familiar locations _kernel.cc_ line 25 and _init.cc_
line 64.

As shown above, the standard GNU binutils and compiler features can bring us
quite far without using a debugger. We have gathered a lot of input for
investigating the error. Our next job will be using this information to
discharge it.


code:
Device access from the user level
=================================

Genode's peripheral device drivers live outside the kernel and have the form of
regular user-level components. This article presents how the device-hardware
access works under these conditions, while taking the general-purpose I/O pins
of the Pine-A64-LTS single-board computer as playground.

In the previous section, we reached a
solid base line of functionality for the kernel and Genode framework on the
Pine-A64-LTS board. Now it is time to turn out attention to the main topic
of our SoC porting effort, which is the interaction with peripheral devices.

As a warm-up, there is no better peripheral than a general-purpose-I/O pin
(GPIO) controller. It is a relatively simple device while enabling us to
observe very satisfying physical effects. Despite the simplicity, we are faced
with the two most important device-driver-related topics, namely accessing
device registers and dispatching interrupts.

The investigation starts with the quest of finding a suitable pin at one
of the various connectors present on the board. The board
[https://files.pine64.org/doc/SOPINE-A64/PINE%20A64-TLS-20180130.pdf - schematics]
as found in the
[https://wiki.pine64.org/wiki/PINE_A64-LTS/SOPine - PINE64 Wiki]
are our guide.
While skimming the 19 pages of the document and glancing at the headlines
above the very technical looking drawings, the so-called Euler connector
at page 12 catches my attention because this name appears besides a
prominently visible 34-pin header on the board.

[image schematics_pb2 100%]

By looking at the schematics, it is easy to guess that the box with the 34
connectors corresponds to this pin header. The pins have labels, which give us
clues about their designated purposes. E.g., some pins are wired to fixed
voltages like 5V or 3.3V or ground. Some others hint at specific functionality
present in the SoC or another component on the board, e.g., those prefixed with
I2S or UART or EAROUT. Some pins however, stand out by being named PB2, PB8,
PD7 and such. The prefix 'P' presumably stands for pin. Other usual
signal-labeling schemes as found in schematics documents contain the pattern
"IO" or "GPIO". Let's settle on the pin PB2 and see where this leads us. By
searching the document for "PB2", we can see that the same signal appears at a
box labeled "R18" (on the page for the Pi-2 connector). By searching for the
ominous component "R18", we quickly learn that this label refers to the
Allwinner SoC. So the pin is directly connected to the SoC. Did we ask for
more? To sum up our findings, the following pins of the Euler connector are
of interest to us:

* Pin 8: 5V
* Pin 27: PB2 (wired to the SoC)
* Pin 34: ground

The label PB2 has to have a meaning for the SoC, which is hopefully cleared
up in the SoC's
[https://linux-sunxi.org/images/b/b4/Allwinner_A64_User_Manual_V1.1.pdf - documentation].
For SoCs with no public documentation, the most compelling alternative source
for such information are device-tree source (dts) files as usually provided by
the SoC vendors for the Linux kernel and U-Boot. But let us save the
device-tree topic for later. Being lucky that the Allwinner A64 SoC
documentation is public, we can search it for "PB2", which brings us to Page
377, specifically to the description of a bit field named "PB2_SELECT" at a
so-called "PB Configure Register 0".

[image pb_cfg0 100%]

The surrounding Section 3.21 "Port Controller(CPUx-PORT)" gives us the
insights we need. PB2 is apparently one of the 10 input/output pins of Port B
of the PIO peripheral, which presumably stands for Pin I/O. There exist plenty
of device registers that are mirrored for different ports (B, C, D, ...).

Using a GPIO pin for sensing a digital signal
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As a first exercise, let's write a little program at
_allwinner/src/test/pin_state/main.cc_ that accesses the
PB Configure Register 0.

! #include <base/component.h>
! #include <base/log.h>
! #include <base/attached_io_mem_dataspace.h>
! #include <util/mmio.h>
!
! namespace Test {
!     using namespace Genode;
!     struct Main;
! }
!
!
! struct Test::Main
! {
!     Env &_env;
!
!     Attached_io_mem_dataspace _pio_ds { _env, 0x1c20800u, 0x400u };
!
!     struct Pio : Mmio
!     {
!         struct Pb_cfg0 : Register<0x24, 32>
!         {
!             struct Pb2_select : Bitfield<8, 3> { };
!         };
!
!         Pio(addr_t base) : Mmio(base)
!         {
!             log("PB2_SELECT: ", read<Pb_cfg0::Pb2_select>());
!         }
!     };
!
!     Pio _pio { (addr_t)_pio_ds.local_addr<void>() };
!
!     Main(Env &env) : _env(env) { }
! };
!
!
! void Component::construct(Genode::Env &env)
! {
!     static Test::Main main(env);
! }

The following details are worth noting.

* The program comes in the form of a 'Main' object as opposed to a
  'main()' function. To learn more about this structure, please refer
  to the article
  [https://genodians.org/nfeske/2019-01-22-conscious-c++ - Genode's Conscious C++ dialect].

* The 'Env' interface allows the code to interact with the environment of
  the Genode component such as allocating memory, or opening a connection to a
  service provided by another component.

* The '_pio_ds' member opens a connection to an IO_MEM service and obtains
  a virtual-memory mapping of the specified range of the system bus.
  The numbers are taken from the Allwinner A64 manual.

* The 'Pio' struct represents a memory-mapped I/O region, inheriting the 'Mmio'
  type. The 'Mmio' constructor takes the base address of the underlying
  device-register range as argument. The structs defined in the scope
  of the 'Pio' struct mirrors the register structure of the memory-mapped
  I/O range:
  There exists a 32-bit wide register 'Pb_cfg0' at offset 0x24.
  ! struct Pb_cfg0 : Register<0x24, 32>
  The bits 8 to 10 of this register correspond to the bit field 'Pb2_select'.
  ! struct Pb2_select : Bitfield<8, 3> { };
  These declarations correspond one-to-one with the register definitions
  as found in the SoC user manual.

* In tho 'Pio' constructor, we print the value of the 'Pb2_select' bitfield
  by using the 'Mmio::read' method.
  ! log("PB2_SELECT: ", read<Pb_cfg0::Pb2_select>());
  Note that the code is completely free of (often bug-prone)
  bit-masking/shifting operations.

To build the program, we have to accompany it with a _target.mk_ file as
follows.

! TARGET := test-pin_state
! SRC_CC := main.cc
! LIBS   += base

Finally, we need to embed the program into a Genode system scenario. The
following run script accomplishes this.

! build { core init test/pin_state }
!
! create_boot_directory
!
! install_config {
!   <config>
!     <parent-provides>
!       <service name="LOG"/>
!       <service name="PD"/>
!       <service name="CPU"/>
!       <service name="ROM"/>
!       <service name="IO_MEM"/>
!       <service name="IRQ"/>
!     </parent-provides>
!
!     <default caps="100"/>
!
!     <start name="test-pin_state">
!       <resource name="RAM" quantum="1M"/>
!       <route> <any-service> <parent/> </any-service> </route>
!     </start>
!   </config>
! }
!
! build_boot_image { core ld.lib.so init test-pin_state }
!
! run_genode_until forever

When executing this run script, we can observe the following output:

! kernel initialized
! ROM modules:
!  ROM: [000000004012c000,000000004012c17f) config
!  ROM: [0000000040006000,0000000040007000) core_log
!  ROM: [00000000401eb000,000000004022c260) init
!  ROM: [000000004012d000,00000000401e4bd0) ld.lib.so
!  ROM: [0000000040004000,0000000040005000) platform_info
!  ROM: [00000000401e5000,00000000401ea0d0) test-pin_state
!
! Genode 21.02-61-g446df00d0d8
! 2010 MiB RAM and 64533 caps assigned to init
! [init -> test-pin_state] PB2_SELECT: 7

The PB2_SELECT bits have the value 7, which is the default value (I/O disable)
according to the documentation. You may ask, what's behind those bits?
The number of connectors of a chip is physically limited by the space of the
chip's package and the practicalities of PCB routing. To make one SoC applicable to a wide
variety of products, SoC vendors implement a feature set much larger than
the pin count would allow and leave the selection of a board-specific subset
of those features to the board vendor. So different boards can use the same
SoC but with different functionality exposed. The ultimate meaning of the
physical pins is left to a software configuration.
This multiplexing of pins to multiple SoC functionalities is often referred to
as I/O muxing or pin muxing. On some SoCs, the I/O mux configuration is
presented as a distinct device. On the Allwinner A64, it is part of the PIO
device. For the pin PB2, the SoC provides the following options.

! 000: Input
! 010: UART2_RTS
! 100: JTAG_DO0
! 110: PB_EINT2
! 001: Output
! 011: Reserved
! 101: SIM_VPPEN
! 111: IO Disable    <- default

To sample the state of pin 27 of the Euler connector, we have to change the
configuration value to 0 (input). Let's set the configuration value and
validate that the change has the desired effect by changing the body of the
'Pio' struct as follows.

! struct Pb_cfg0 : Register<0x24, 32>
! {
!     struct Pb2_select : Bitfield<8, 3>
!     {
!         enum { IN = 0 };
!     };
! };
!
! Pio(addr_t base) : Mmio(base)
! {
!     log("PB2_SELECT: ", read<Pb_cfg0::Pb2_select>());
!
!     write<Pb_cfg0::Pb2_select>(Pb_cfg0::Pb2_select::IN);
!
!     log("PB2_SELECT: ", read<Pb_cfg0::Pb2_select>());
! }

Note the 'enum' value definition for 'IN', which helps us to self-document the
code as opposed to just writing the value 0. The output looks as expected.
We read back the value that we have just written.

! [init -> test-pin_state] PB2_SELECT: 7
! [init -> test-pin_state] PB2_SELECT: 0

With the PB2 pin configured as input, let's see if we can observe a signal
change at the Euler connector pin 27. The pin state is captured by the
so-called PB Data Register (PB_DATA_REG) at offset 0x34. The register hosts
one bit for each pin of the port B. For the PB2 pin, we have to poll bit 2.
Or, to put it in other words:

! ...
! struct Pb_data : Register<0x34, 32>
! {
!     struct Pb2 : Bitfield<2, 1> { };
! };
!
! Pio(addr_t base) : Mmio(base)
! {
!     write<Pb_cfg0::Pb2_select>(Pb_cfg0::Pb2_select::IN);
!
!     while (true)
!         log("PB2_STATE: ", read<Pb_data::Pb2>());
! }

This gives us the following output:

! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1

The pattern looks interesting, like if the PB2 pin is not quite sure about
its state. For the experiment, let's try to connect the PB2 pin to ground.
That is shorting the pins 27 (PB2) with 34 (GND).
As a matter of courtesy, it is good to avoid connecting the pins directly
but instead placing a resistor of a few hundred Ohm between both pins.
Should we have done a mistake along our way and accidentally connect a 5V
pin to GND, the current will flow nicely through our resistor instead of
producing a short circuit. So what happens when connecting both pins?

! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! [init -> test-pin_state] PB2_STATE: 0
! ...

That looks clean! What about connecting pin 27 (PB2) to pin 8 (5V)?

! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! [init -> test-pin_state] PB2_STATE: 1
! ...

Isn't that wonderful?

The following picture summarizes our scenario.

[tikz img/pine_pin_state]

The pin 27 of the Euler connector goes to the PB2 pin of the SoC.
Via the PB_CFG0 register, we configure this pin to be used as general-purpose
I/O pin reflected by bit 2 in the PB_DATA register. The register set of the
PIO device unit is visible at physical address 0x1c20800 at the system
bus. Thanks to the MMIO service of Genode's core, our test component
becomes able to access this register range as part of its virtual address
space. So what's this PB_PULL0 register shown in the picture?

This register can be used to prevent the fluctuating state when leaving
the PB2 pin unconnected. Jargon speaks of _high impedance_, which sounds
super educated but means the same thing.
In real-world applications, this floating state is often not wanted.
After all, digital means 0 or 1 but not maybe. Fortunately, the state
can easily be avoided by connecting the PB2 pin via a very high resistor
to ground (or 5V). This resistor pulls the floating potential _down_ to
ground (or _up_ to 5V). Since this is such a common need, the SoC comes
readily equipped with pull-down or pull-up resistors. We just need to enable
either option, which can be done via the PB PULL Register 0 (PB_PULL0).

! ...
! struct Pb_pull0 : Register<0x40, 32>
! {
!     enum { PULL_DOWN = 2 };
!
!     struct Pb2 : Bitfield<4, 2> { };
! };
!
! Pio(addr_t base) : Mmio(base)
! {
!     ...
!     write<Pb_pull0::Pb2>(Pb_pull0::PULL_DOWN);
!     ...
! }

With this little change, the output stays at 0 even when leaving the pin 27
(PB2) disconnected.

Driving an LED via a GPIO pin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Let's try the reverse, using the PB2 pin as a digital output signal.
At this point, it is easy to connect the dots at the software side.

# Configure the PB2_SELECT bits of the PB_CFG0 register to operate
  the pin in output mode, which is value 1.

# Write the desired state to the bit 2 of the PB_DATA register.

The following code sets up the PB_CFG0 register and equips the 'Pio'
struct with a 'toggle_pb2' method that reads the PB2 state from the
PB_DATA register and writes back the inverted state.

! struct Pio : Mmio
! {
!     struct Pb_cfg0 : Register<0x24, 32>
!     {
!         struct Pb2_select : Bitfield<8, 3>
!         {
!             enum { OUT = 1 };
!         };
!     };
!
!     struct Pb_data : Register<0x34, 32>
!     {
!         struct Pb2 : Bitfield<2, 1> { };
!     };
!
!     Pio(addr_t base) : Mmio(base)
!     {
!         /* configure PB2 pin to output mode */
!         write<Pb_cfg0::Pb2_select>(Pb_cfg0::Pb2_select::OUT);
!     }
!
!     void toggle_pb2()
!     {
!         bool const value = read<Pb_data::Pb2>();
!
!         /* write back inverted value */
!         write<Pb_data::Pb2>(!value);
!     }
! };

To let the test program blink the LED at a visible rate, we need a timer
mechanism. Here, Genode's 'Timer::Connection' becomes handy. By adding
following few lines to the 'Main' object, the 'toggle_pb2' method gets
called every 250 milliseconds.

! #include <timer_session/connection.h>
! ...
! struct Main
! {
!     Timer::Connection _timer { _env };
!
!     void _handle_timeout(Duration)
!     {
!         _pio.toggle_pb2();
!     }
!
!     Timer::Periodic_timeout<Main> _timout_handler {
!         _timer, *this, &Main::_handle_timeout, Microseconds { 250*1000 } };
! };

Until now, the simple test scenario lack a timer service. So we have to
extend the run script a bit.

# Adding the timer service to the list of components to build.

  ! build { ... timer }

# Adding a start node to the static system configuration.

  ! <start name="timer">
  !   <resource name="RAM" quantum="1M"/>
  !   <route> <any-service> <parent/> </any-service> </route>
  !   <provides> <service name="Timer"/> </provides>
  ! </start>

# Routing the timer-session request by the test program to the timer service.

  ! <start name="test-pin_control">
  !   <resource name="RAM" quantum="1M"/>
  !   <route>
  !     <service name="Timer"> <child name="timer"/> </service>
  !     <any-service> <parent/> </any-service>
  !   </route>
  ! </start>

# Adding the timer executable to the boot image.

  ! build_boot_image { ... timer }

At the hardware side, we need to connect an LED in series with a resistor
dimensioned such that the potential difference over the LED will be
approximately 2V. When connecting a 5V pin over the LED and the resistor to
ground, the resistor should hence take away 3V. Most LEDs draw a current of
20mA. Hence, Ohm's law (R = U / I) tells us that the resistor should have a
value of 3V / 0.02 A = 15O Ohm. Picking a higher resistor cannot hurt. It
will just reduce the brightness of the LED. Long story short, a resistor of a
few hundred Ohm should be fine.

_If any electrical engineer is reading this and finds I'm writing nonsense,_
_please contact me._

To see if the LED is able to light up in principle when connected with the
resistor in series, the pins 8 (5V) and 34 (GND) become handy. The anode
contact (the long one) of the LED must face the 5V side.

Now its time to bring software and hardware together by connecting the LED's
anode to pin 27 (PB2) and starting the test program. The final setup looks
like this. What's not captured in the photo is that the LED is indeed
blinking.

[image pine_a64lts_led]

Responding to device interrupts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Besides sensing and driving digital signals, GPIO pins are often used as
an interrupt source. So some external circuity can trigger a sporadic
response by the software.

To explore the interrupt facility, let's first ignore the ARM GIC interrupt
controller for a moment and just focus on the PIO device. In the PB_CFG0
register, the value 6 configures the pin as operating in PB_EINT2 mode.
Whatever the meaning of the E or the 2, the pattern "INT" hints at what we
want.

! ...
! struct Pb_cfg0 : Register<0x24, 32>
! {
!     struct Pb2_select : Bitfield<8, 3>
!     {
!         enum { EINT2 = 6 };
!     };
! };
! ...
! Pio(addr_t base) : Mmio(base)
! {
!     write<Pb_pull0::Pb2>(Pb_pull0::PULL_DOWN);
!
!     write<Pb_cfg0::Pb2_select>(Pb_cfg0::Pb2_select::EINT2);
! }

The PB External Interrupt Status Register (PB_EINT_STATUS_REG) reflects
the interrupt state.

! struct Pb_eint_status : Register<0x214, 32> { };

As an intermediate test, we can poll this register
and see what happens when we connect the pin 27 (PB2) to pin 8 (5V).
The polling loop can be directly added to the 'Pio' constructor.

! while (true)
!     log("PB_EINT_STATUS: ", read<Pb_eint_status>());

After starting the program, we see the following output scrolling by.

! [init -> test-pin_interrupt] PB_EINT_STATUS: 0
! [init -> test-pin_interrupt] PB_EINT_STATUS: 0
! [init -> test-pin_interrupt] PB_EINT_STATUS: 0
! ...

Once after connecting PB2 to 5V, the output changes to:

! [init -> test-pin_interrupt] PB_EINT_STATUS: 4
! [init -> test-pin_interrupt] PB_EINT_STATUS: 4
! [init -> test-pin_interrupt] PB_EINT_STATUS: 4
! ...

The 4 corresponds to the bit 2 set, which is what we anticipated.
The status bit never returns to the original state. To clear the bit,
a 1 must be written to the status bit. This can be tested by slightly changing
the while loop.

! while (true) {
!     if (read<Pb_eint_status::Pb2>()) {
!         log("PB2 EINT status went high");
!         write<Pb_eint_status::Pb2>(1);
!     }
! }

The scrolling log output is no more. Now, we see only one message each time
we fiddle with the PB2 pin.

! [init -> test-pin_interrupt] PB2 EINT status went high

The clearing of the interrupt status works as advertised.

Until now, we have observed the PIO device behavior via a polling loop, which
is of course not in the spirit of using interrupts. To complete the scenario,
we have to tell the PIO to inform the CPU's interrupt controller (GIC)
whenever the EINT status goes high. The connection between the PIO and the
GIC can be established via the PB External Interrupt Control Register.

! struct Pb_eint_ctl : Register<0x210, 32>
! {
!    struct Pb2 : Bitfield<2, 1> { };
! };

When setting bit 2 in this register, the GIC will see a device interrupt
from the PIO device. The GIC interrupt numbers are documented in the
Allwinner A64 manual at page 211. PB_EINT is interrupt number 43.

To obtain an interrupt in our component, we can use core's IRQ service as
follows.

! #include <irq_session/connection.h>
! ...
!
! struct Test::Main
! {
!     ...
!
!     enum { PB_EINT = 43 };
!
!     Irq_connection _irq { _env, PB_EINT };
!
!
!     unsigned _count = 0;
!
!     void _handle_irq()
!     {
!         log("interrupt ", _count++, " occurred");
!
!         _pio.clear_pb2_status();
!
!         _irq.ack_irq();
!     }
!
!     Signal_handler<Main> _irq_handler { _env.ep(), *this, &Main::_handle_irq };
!
!     Main(Env &env) : _env(env)
!     {
!         _irq.sigh(_irq_handler);
!         _handle_irq();
!     }
! };

The following details about this code fragment are worth highlighting.

* The GIC interrupt number is passed as argument to the IRQ connection to
  core.

* Interrupts are delivered as signals. The '_irq_handler' is a signal
  handler that is registered at the IRQ session via the '_irq.sigh' method.
  Each time the signal occurs, the 'Main::_handle_irq' method is executed.

* The '_pio.clear_pb2_status' method performs the clearing of the PB2 interrupt
  status.
  ! struct Pio
  ! {
  !      ...
  !      void clear_pb2_status()
  !      {
  !          write<Pb_eint_status::Pb2>(1);
  !      }
  ! };
  The '_irq.ack_irq' call acknowledges the interrupt at the GIC.

* The '_handle_irq' method is manually called once after registering the
  signal handler at the IRQ session. This pattern ensures that an initially
  pending interrupt that occurred just before the call of '_irq.sigh' is
  processed before the component goes into idle state.

The following illustration summarizes the scenario.

[tikz img/pine_pin_interrupt]

The exact conditions for triggering an interrupt can be configured for the pin
using the PB External Interrupt Configure Register 0 (PB_EINT_CFG0).
By default, the status goes to 1 as soon as a rising edge is detected. The
other alternatives are falling edge, level-high (interrupt stays pending as
long as the signal is high), level-low, and double edge (interrupt on any
change of the signal).

Only if the bit 2 of the status register (PB_EINT_STATUS) and the bit 2
of the control register (PB_EINT_CTL) are set, the interrupt controller (GIC)
receives an interrupt. This GIC interrupt (number 43) is propagated via
core's IRQ service to our user-level component, which implements the
interrupt handler.

Thanks to the interrupt mechanism, we can now respond to sporadic hardware
events without active polling. When executing the scenario, we can see that a
single message occurs each time when fiddling with the PB2 pin. The system
stays completely idle otherwise.

! [init -> test-pin_interrupt] interrupt 0 occurred
! [init -> test-pin_interrupt] interrupt 1 occurred
! [init -> test-pin_interrupt] interrupt 2 occurred
! [init -> test-pin_interrupt] interrupt 3 occurred
! [init -> test-pin_interrupt] interrupt 4 occurred

Pointers to the corresponding code
----------------------------------

The test programs described above can be found at the
[https://github.com/genodelabs/genode-allwinner - genode-allwinner] Git
repository. The C++ code is located at
[https://github.com/genodelabs/genode-allwinner/tree/master/src/test/pin_state - src/test/pin_state/],
[https://github.com/genodelabs/genode-allwinner/tree/master/src/test/pin_control - src/test/pin_control/],
and
[https://github.com/genodelabs/genode-allwinner/tree/master/src/test/pin_interrupt - src/test/pin_interrupt/].
These test programs are accompanied with matching run scripts located at the
[https://github.com/genodelabs/genode-allwinner/tree/master/run - run/] directory.