% on the following slides, include icon in the left sidebar
\def\lximg{/usr/share/lx/icons/fueller.png}

\input{configpres}

\title{Realtime application development using Linux-RT\_PREEMPT}
\maketitle

% stop displaying 'fueller.png' on the following slides
\def\lximg{none}

\subsection{RT\_PREEMPT Realtime development}

\subsubsection{Basics}
\begin{frame}[fragile]
\frametitle{Check sched\_rt\_runtime\_us!!}
\begin{verbatim}
echo -1 > \
/proc/sys/kernel/sched_rt_runtime_us
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Setting RT priority}
\begin{verbatim}
/* Set realtime priority */
struct sched_param param;
param.sched_priority = 99;
if (sched_setscheduler(0, SCHED_FIFO, &param) < 0)
    perror("Can't set scheduling policy");
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Lock memory}
\begin{verbatim}
if (mlockall(MCL_CURRENT | MCL_FUTURE))
    perror("mlockall failed:");
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Configure malloc() behaviour}
\begin{verbatim}
/* Turn off malloc trimming.*/
mallopt(M_TRIM_THRESHOLD, -1);

/* Turn off mmap usage. */
mallopt(M_MMAP_MAX, 0);
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Reserve process memory}
\begin{verbatim}
buffer = malloc(MSIZE);

for (i = 0; i < MSIZE; i += sysconf(_SC_PAGESIZE))
    buffer[i] = 0;

free(buffer);
\end{verbatim}
\textbf{BUT: Please avoid memory allocation from realtime context!!}
\end{frame}

\begin{frame}[fragile]
\frametitle{Prefault the stack (per Thread!)}
\begin{verbatim}
/* Prove that this thread is behaving well */
for (i = 0; i < SAVE_STACK_SIZE; i += sysconf(_SC_PAGESIZE))
    buffer[i] = i;
\end{verbatim}
\end{frame}

\subsubsection{Clocks and Timers}

\begin{frame}
\frametitle{Clocks: Basic}
\begin{itemize}
\item Use POSIX!
\item clock\_getres()
\item clock\_gettime()
\item clock\_settime()
\item clock\_nanosleep()
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Clock types}
\begin{itemize}
\item CLOCK\_MONOTONIC: Clock that cannot be set and represents monotonic time
since some unspecified starting point.
\item CLOCK\_REALTIME: System-wide real-time clock. Can be set (by NTP, User,
...)!
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Getting the time}
\begin{verbatim}
struct timespec tv;
struct timespec res;

clock_gettime(CLOCK_MONOTONIC, &tv);

clock_getres(CLOCK_MONOTONIC, &res);
\end{verbatim}
\end{frame}

\begin{frame}
\frametitle{Cyclic tasks}
\begin{itemize}
\item Use clock\_nanosleep!
\item Do not use signals!
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Example: 1 / 2}
\begin{verbatim}
#include <stdio.h>
#include <time.h>

#define CYCLE_TIME_NS (100 * 1000 * 1000) 
#define NSEC_PER_SEC 1000000000

void norm_ts(struct timespec *tv)
{
        if(tv->tv_nsec > NSEC_PER_SEC) {
                tv->tv_sec++;
                tv->tv_nsec -= NSEC_PER_SEC;
        }
}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Example: 2 / 2}
\begin{verbatim}
int main(void)
{
        struct timespec tv;

        clock_gettime(CLOCK_MONOTONIC, &tv);
        do {
                /* Do the work */

                /* Wait for next cycle */
                tv.tv_nsec += CYCLE_TIME_NS;
                norm_ts(&tv);
                clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tv, NULL);
        } while(1);
}
\end{verbatim}
\end{frame}

\subsubsection{Locking}
\begin{frame}
\frametitle{Locking}
\begin{itemize}
\item Use pthread\_mutexes
\item Activate PRIO\_INHERIT
\item Activate robustness
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Locking example}
\begin{verbatim}
pthread_mutex_t master_lock;
pthread_mutexattr_t mattr;

pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_setrobust_np(&mattr, PTHREAD_MUTEX_ROBUST_NP);
pthread_mutex_init(&master_lock, &mattr);

pthread_mutex_lock(&master_lock);
/* Do critical work */
pthread_mutex_unlock(&master_lock);

pthread_mutex_destroy(&master_lock);
\end{verbatim}
\end{frame}

\subsubsection{Signalling}
\begin{frame}
\frametitle{Signalling mechanisms}
\begin{itemize}
\item Do not use signals
\item Use pthread\_cond\_vars
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{pthread\_cond\_var: Initialization 1 / 2}
\begin{verbatim}
pthread_mutexattr_t mattr;
pthread_condattr_t cattr;
pthread_cond_t cond;
pthread_mutex_t mutex;

pthread_mutexattr_init (&mattr);
pthread_mutexattr_setpshared (&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_setrobust_np(&mattr, PTHREAD_MUTEX_ROBUST_NP);
pthread_mutex_init (&mutex, &mattr);
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{pthread\_cond\_var: Initialization 2 / 2}
\begin{verbatim}
pthread_condattr_init (&cattr);
pthread_condattr_setpshared (&cattr, PTHREAD_PROCESS_SHARED);
pthread_cond_init (&cond, &cattr);
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{pthread\_cond\_var: Send signal}
\begin{verbatim}
/* Send signal */
pthread_mutex_lock(&mutex);
/* Do the homework */
/* ... */
pthread_cond_broadcast (&cond);
pthread_mutex_unlock(&mutex);
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{pthread\_cond\_var: Wait for signal}
\begin{verbatim}
/* Wait for signal */
pthread_mutex_lock(&mutex);
pthread_cond_wait (&cond, &mutex);
/* -> We've been signalled */
pthread_mutex_unlock(&mutex);
\end{verbatim}
\end{frame}

\subsubsection{sources}
\begin{frame}
\frametitle{sources}
\small
\begin{thebibliography}{1}
\bibitem{rt1} https://rt.wiki.kernel.org/
\bibitem{rt2} https://rt.wiki.kernel.org/index.php/ Dynamic\_memory\_allocation\_example
\bibitem{rt3} https://rt.wiki.kernel.org/index.php/ Threaded\_RT-application\_with\_memory\_locking\_and\_stack\_handling\_example
\end{thebibliography} 
\end{frame}

\input{tailpres}
