% 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 = 80; if (sched_setscheduler(0, SCHED_FIFO, ¶m) < 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 #include #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_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); 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_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); pthread_mutexattr_setpshared (&mattr, PTHREAD_PROCESS_SHARED); pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); 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}