\documentclass{article}
\topmargin=-0.3 truein
\textheight=9 truein
\textwidth=6.1 truein
\oddsidemargin=0.2 truein

\usepackage{psfig}
\usepackage{latexsym}
\usepackage[english]{babel}
\selectlanguage{english}

\title{The RK API Reference}

\author{Real-Time Multimedia Lab\\
        Department of Computer Science\\
        Carnegie Mellon University, Pittburgh PA
}

\date{}
\begin{document}

\maketitle

\begin{abstract}
This document briefly describes the Resource Kernel (RK) specific APIs.
Users interested to a more complete and detailed description can download the
TimeSys Linux/RT users/programmers manual, since the RK and TimeSys Linux/RT
APIs are very similar.
\end{abstract}


\section{Introduction}
In order to compile a Linux program for RK, link the library {\tt librk.a}
located under {\tt LinuxRK/lib/}.

To use CPU, network or disk reservation, the following general steps are
necessary:
\begin{enumerate}
\item Create Resource Set (RS)
\item Create CPU, disk and network reservation for the resource set
\item Attach a process to the resource set
\item execute the process
\item Destroy resource set.
\end{enumerate}

Please consult the example programs in the {\tt LinuxRK/examples} directory
for detail.

\subsection{Loading the RK module}
The Linux Resource Kernel (Linux/RK) is implemented as a kernel module
{\tt rk.o} that must be loaded before executing any application that requires
the RK system calls. If the module is not loaded, all the RK system calls
will return {\tt -1} as an error condition.

The RK module is in {\tt LinuxRK/rkmod/}; please note that in order to load it
you need a modified version of the linux kernel (distributed together with
the RK) that exports some hooks used by the module. In order to use the RK:
\begin{enumerate}
\item configure and compile {\tt linux.2.2.14.rk}: go to the
        {\tt linux.2.2.14.rk} directory, do
        ``{\tt make config/menuconfig/xconfig}'', ensuring that the
        {\tt Linux/RK} kernel option is set (it is by default), then do 
        ``{\tt make depend}'', and ``{\tt make bzImage}'';
\item install and boot it (put the {\tt bzImage} in the {\tt /boot}
        directory, edit the {\tt /etc/lilo.conf} file accordingly, run
        {\tt /sbin/lilo}, and reboot);
\item compile the module (go to the {\tt LinuxRK/rkmod/} directory, and
        type {\tt make});
\item load the module: {\tt insmod rk.o}. You must be root for doing it.
\item Enjoy!!!
\end{enumerate}

\section{Concepts}
\subsection{Reserve Inheritance}
RK provides kernel mutexes that implements {\em reserve} inheritance.
Reserve inheritance keeps track of one important invariant related to 
the process holding the lock:

\begin{quote}
The holder of the mutex should run with the cpu reserve 
with the highest priority that is active among all the cpu reserves attached
to the processes waiting for mutexes that this mutex holder is holding 
and itself.
\end{quote}

In addition it ensure that upon unlocking the mutex should be granted 
to the process with the highest priority.

To keep these properties the reserve inheritance mechanism implements the
following features:
Upon blocking on a mutex the process will be added to a waiting priority
queue. In addition its reserve will be inherited by the owner of the lock
if this has the highest priority among all the processes waiting for 
this lock and the reserve of the owner itself. We are going to call to this
set of reserve the \textit{inherited reserve set}.

Upon replenishment or depletion of any reserve in the \textit{inherited reserve set}, the highest priority invariant will be verified and the reserve will
be inherited if necessary.

\section{API for LinuxRK}
\subsection{Creating a Resource Set}
\begin{quote}
\begin{tt}
\begin{tabbing}
rk\_resource\_set\_t rk\_resource\_set\_create(char *name)
\end{tabbing}
\end{tt}
\end{quote}
Creates resource set with name {\tt name} (or without name if
{\tt name == NULL} and returns data structure rk\_resource\_set\_t
on success. 

Returns {\tt NULL\_RESOURCE\_SET} if the RK fails to create the resource
set or {\tt -1} if the RK module is not installed.

\subsection{Destroying a Resource Set}
\begin{quote}
\begin{tt}
\begin{tabbing}
void rk\_resource\_set\_destroy(rk\_resource\_set\_t rs)
\end{tabbing}
\end{tt}
\end{quote}
Destroys the resource set passed as an argument.


\subsection{Attaching a Process to a Resource Set}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_resource\_set\_attach\_process(rk\_resource\_set\_t rs, pid\_t pid)
\end{tabbing}
\end{tt}
\end{quote}
Attaches the process specified by the {\tt pid} parameter to the resource
set {\tt rs}.
Returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure.

\subsection{Creating a CPU Reserve}
\begin{quote}
\begin{tt}
\begin{tabbing}
rk\_reserve\_t rk\_cpu\_reserve\_create(rk\_resource\_set\_t rs,
cpu\_reserve\_attr\_t attr)

\end{tabbing}
\end{tt}
\end{quote}
Creates a CPU reservation and attaches it to resource set {\tt rs}.
The attributes of the CPU reservation are specified by the {\tt attr}
parameter, that is a pointer to a {\tt cpu\_reserve\_attr} structure
defined as follows:
\begin{tt}
\begin{tabbing}
struct \= cpu\_reserve\_attr \{                         \\
    \> struct timespec compute\_time;                   \\
    \> struct timespec period;                          \\
    \> struct timespec deadline;                        \\
    \> struct timespec blocking\_time;                  \\
    \> struct timespec start\_time;                     \\
    \> rk\_reserve\_param\_data\_t reserve\_type;       \\
    \> ticket\_type\_t           ticket\_type;          \\
    \> unsigned long           quota\_tickets;          \\
    \> cpu\_tick\_data\_t         ticket\_age;          \\
\};
\end{tabbing}
\end{tt}

The amount of CPU reservation is specified by
{\tt struct timespec computed\_time} and {\tt struct timespec period}. The
{\tt struct timespec deadline} parameter is the relative deadline used by
Deadline Monotonic or Earliest Deadline First, whereas
{\tt struct timespec blocking\_time} and {\tt struct timespec start\_time}
are the reserve blocking time (used for admission control) and start time
respectively.

Parameters for CPU reservation are passed using the
{\tt rk\_reserve\_param\_t reserve\_type} field, that let you specify
the enforcement and replenishment modes.
Currently, LinuxRK supports the {\tt RSV\_HARD}, {\tt RSV\_FIRM}, and
{\tt RSV\_SOFT} enforcement modes:
\begin{itemize}
\item {\tt RSV\_HARD}: guaranteed to receive the specified amount on success.
        After receiving the specified amount of time, the reserve is depleted.
\item {RSV\_FIRM}: guaranteed to receive the specified amount on success.
        If resource is still available after using up guaranteed amount,
        it will compete against non-reserved tasks for more.
\item {RSV\_SOFT}: guaranteed to receive the specified amount on success.
        If resource is still available after using up guaranteed amount, it
        will compete against all tasks for more.
\end{itemize}

Replenishment modes:
\begin{itemize}
\item {\tt RSV\_HARD}: If a reserve uses more than the reserved time in a
        period, the extra time will be subtracted from the available time in
        the following period.
\item {\tt RSV\_SOFT}: The available time is always replenished to the reserved
        value.
\end{itemize}
        
Returns data structure {\tt rk\_reserve\_t} on success and {\tt NULL\_RESERVE}
on failure. 

\subsection{Destroying a CPU Reserve}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserve\_delete(rk\_resource\_set\_t);
\end{tabbing}
\end{tt}
\end{quote}
Destroys CPU reserve passed as an argument.

\subsection{Changing CPU Reserve Parameters}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserve\_ctl(rk\_reserve\_t rsv, cpu\_reserve\_attr\_t cpu\_attr attr)
\end{tabbing}
\end{tt}
\end{quote}
Changes the properties of existing CPU reservation {\tt rsv} (eg. computation
time and period) according to {\tt attr}.

Returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure.

\subsection{Obtaining CPU Reserve Parameters}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserve\_get\_attr(rk\_reserve\_t rs,
cpu\_reserve\_attr\_t cpu\_attr)
\end{tabbing}
\end{tt}
\end{quote}
Reads the properties of CPU reservation {\tt rsv}.

Returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure.

\subsection{Obtaining Information on Existing Reserves and Resource Sets}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserves\_get\_num(void)                                   \\
int rk\_resource\_sets\_get\_num(void)                                  \\
int rk\_cpu\_reserves\_get\_list(rk\_reserve\_t *rsvs, int count)       \\
int rk\_resource\_sets\_get\_list(rk\_resource\_set\_t *rss, int count)
\end{tabbing}
\end{tt}
\end{quote}
Return some useful information about the number of CPU reserves or resource
sets in the system, or a list of all the reserves or resource sets. The
{\tt *\_get\_list()} functions take as parameters a pointer to an array of
{\tt rk\_reserve\_t} (or {\tt rk\_resource\_set\_t}) and an integer
{\tt count} specifying the dimension of that array, and return the
number of reserves (or resource sets) on success and {\tt RK\_ERROR}
on failure.

\subsection{Scheduling Policies}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserves\_set\_scheduling\_policy(int policy);
\end{tabbing}
\end{tt}
\end{quote}
Set the reserve scheduling policy; currently supported scheduling policies
are: \begin{itemize}
\item 0 $\rightarrow$ Rate Monotonic;
\item 1 $\rightarrow$ Deadline Monotonic;
\item 2 $\rightarrow$ Earliest Deadline First.
\end{itemize}

Returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure.

If Earliest Deadline First is selected, the SOFT enforcement mode is
implemented as a simplified version of the Constant Bandwidth Server
(described in Luca Abeni and Giorgio Buttazzo,
{\em ``Integrating Multimedia Applications in Hard Real-Time Systems''},
Proceedings of the IEEE Real-Time Systems Symposium, Madrid, Spain,
December 1998). Basically, when a reserve finishes the available execution
time, the deadline is postponed and tasks' priorities are updated
accordingly, but it is not depleted (CBS is work conserving).

\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cpu\_reserves\_get\_scheduling\_policy(void);
\end{tabbing}
\end{tt}
\end{quote}
Returns the currently used reserve scheduling policy.

\subsection{Removing the RK Module}
Before removing the RK module, the following system call must be invoked, in
order to remove the {\em default} and {\em idle} RS.
\begin{quote}
\begin{tt}
\begin{tabbing}
int rk\_cleanup(void)
\end{tabbing}
\end{tt}
\end{quote}

\subsection{Creating Periodic Tasks}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rt\_make\_periodic(struct timespec *period, struct timespec *start);
\end{tabbing}
\end{tt}
\end{quote}
Transforms the calling task in a periodic task with period {\tt period} and
first activation at {\tt start}.

Returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure.

\subsection{Synchronizing Periodic Tasks}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rt\_wait\_for\_start\_time(void)                    \\
int rt\_wait\_for\_next\_period(void)
\end{tabbing}
\end{tt}
\end{quote}
Blocks the calling task until the first ({\tt start\_time}) or the next
({\tt next\_period}) periodic activation. The calling task must be periodic;
returns {\tt RK\_SUCCESS} on success and {\tt RK\_ERROR} on failure (when
invoked by a non periodic task).

\subsection{Handling Tasks' Periods}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rt\_process\_get\_period(pid\_t pid, struct timespec *period)       \\
int rt\_process\_set\_period(pid\_t pid, struct timespec *period)
\end{tabbing}
\end{tt}
\end{quote}
Gets/sets the period for a periodic task identified by {\tt pid}.

\subsection{Getting the scheduling error}
\begin{quote}
\begin{tt}
\begin{tabbing}
long int rt\_get\_scheduling\_error(void)
\end{tabbing}
\end{tt}
\end{quote}
When the EDF scheduling policy is used, returns the {\em ``scheduling error''}
$\epsilon_{i,j} = d_{i,j} - r_{i,j}$ for a periodic task. The scheduling error
is defined as {\bf the difference between the absolute deadline of the reserve
serving a task and the task activation time}.

In general, if $\epsilon > 0$ the task is not reserved enough time per
period.

\subsection{Mutex and Reserve Inheritance}
\begin{quote}
\begin{tt}
\begin{tabbing}
int rt\_mutex\_create(int proto, int gid);                      \\
int rt\_mutex\_destroy(int mutex\_id);                          \\
int rt\_mutex\_lock(int mutex\_id);                             \\
int rt\_mutex\_trylock(int mutex\_id);                          \\
int rt\_mutex\_unlock(int mutex\_id);
\end{tabbing}
\end{tt}
\end{quote}

Reserve inheritance can be selected at creation time of the mutex setting
the parameter proto to {\bf PTHREAD\_PRIO\_INHERIT}. In case reserve
inheritance is not desired this parameter should be set to 
{\bf PTHREAD\_PRIO\_NONE}. the call to {\em rt\_mutex\_create()} returns an integer that
works as the mutex handler.

The mutex is initialized to the \textit{unlocked} state and can be 
lock with the call to 
\textit{rt\_mutex\_lock()}. This function takes as a parameter the mutex id. If 
the mutex is already locked by other process, then the current process will be
blocked until the mutex is released.

\textit{rt\_mutex\_trylock()} is also used to lock the mutex, but in case the
mutex is already locked then it will return with \textbf{-EBUSY}, instead of 
blocking the process.

\textit{rt\_mutex\_unlock()} is used to unlock the mutex. whenever this happends 
the mutex is granted to the next process waiting for it.

\textit{rt\_mutex\_destroy()} destroys the mutex.


\subsubsection{pthread mutexes}
the  mutexes can be used through the pthread library. You should read the man
pages for this purpose. Notwithstanding a new function call was added to 
the library to activate the reserve inheritance: \textbf{pthread\_mutexattr\_setprotocol()}.

\textit{pthread\_mutexattr\_setprotocol(pthread\_mutex\_attr\_t, int proto)}, takes
as a parameter the mutex attributes and the protocol to activate. This protocol
should be one of PTHREAD\_PRIO\_INHERIT or PTHREAD\_PRIO\_NONE.

\subsection{Disk Reservations}
The RK provide {\em experimental} support for disk reservations and
disk server coscheduling. These functionalities can be accessed using the
following system calls.
\begin{quote}
\begin{tt}
\begin{tabbing}
void cpu\_reserve\_start(rk\_reserve\_t, cpu\_tick\_t);                 \\
rk\_reserve\_t rk\_disk\_reserve\_create(rk\_resource\_set\_t,          \\
                                               disk\_reserve\_attr\_t); \\
int rk\_disk\_reserve\_delete(rk\_resource\_set\_t);                    \\
int rk\_reserve\_update\_account(rk\_reserve\_t, unsigned long);        \\
int rk\_reserve\_quota\_query(rk\_reserve\_t, unsigned long *);         \\
void rk\_reserve\_wait\_on\_quota(rk\_reserve\_t);                      \\
int disk\_higher\_prio(rk\_reserve\_t, rk\_reserve\_t);
\end{tabbing}
\end{tt}
\end{quote}

The disk support is still undocumented.

\subsection{Creating a Network Reserve}
\begin{quote}
\begin{tt}
\begin{tabbing}
rk\_reserve\_t net\_reserve\_create(rk\_resource\_set\_t rs,
net\_reserve\_attr\_t attr)
\end{tabbing}
\end{tt}
\end{quote}

Creates a network reservation and attaches it to a resource set {\tt rs}.
The reservation is associated with a particular socket connection.
Currently RK supports only one reserve per socket or one socket per
reserve. The network reservation at this point only involves a packet
scheduler at the sending side. The packet scheduler was implemented using
rate-monotonic and  deadline monotonic scheduling theories that
previously applied to CPU  reservation(Please take a look at:
Sourav Ghosh and Ragunathan Rajkumar, 
{\em ``Network Bandwidth Reservation using the Rate-Monotonic Model''},
SoftCOM 99). 

This packet scheduler decouples bandwidth and delay guarantees for a reserved 
flow.

The attributes of a network reservation are specified by the {\tt attr}
paramter, which is a pointer to a {\tt net\_reserve\_attr} structure
defined as follows:

\begin{tt}
\begin{tabbing}
struct net\_reserve\_attr \{                            \\
  size\_t amount;                                       \\
  struct timespec period;                               \\
  struct timespec deadline;                             \\
  struct timespec blocking\_time;                       \\
  struct timespec start\_time;                          \\
  rk\_reserve\_param\_data\_t reserve\_type;            \\
  int socket\_fd;                                       \\
\};
\end{tabbing}
\end{tt}

The parameters are self-explanatory (similar to CPU reservation). The 
parameter {\tt amount} is the reservation in terms of number of bytes
that would be sent within a period specified by the variable {\tt period}.
The {\tt socket\_fd} stores the socket descriptor attached to this reserve.  

\subsection{Changing Network Reserve paramters}
\begin{quote}
\begin{tt}
\begin{tabbing}
int net\_reserve\_ctl(rk\_resource\_set\_t rs, rk\_reserve\_t rsv,
size\_t ub, struct timespec *ut)
\end{tabbing}
\end{tt}
\end{quote}
This function is not fully functional yet.

\end{document}
