/sharkdoc/branches/new_sharkdoc/vol1/vol1.tex |
---|
0,0 → 1,77 |
\documentclass[italian,english]{report} |
\usepackage[T1]{fontenc} |
\usepackage[latin1]{inputenc} |
\usepackage{geometry} |
\geometry{verbose,a4paper} |
\usepackage{array} |
\usepackage{longtable} |
\usepackage{makeidx} |
\makeindex |
\usepackage{graphicx} |
\makeatletter |
%% Special footnote code from the package 'stblftnt.sty' |
%% Author: Robin Fairbairns -- Last revised Dec 13 1996 |
\let\SF@@footnote\footnote |
\def\footnote{\ifx\protect\@typeset@protect |
\expandafter\SF@@footnote |
\else |
\expandafter\SF@gobble@opt |
\fi |
} |
\expandafter\def\csname SF@gobble@opt \endcsname{\@ifnextchar[%] |
\SF@gobble@twobracket |
\@gobble |
} |
\edef\SF@gobble@opt{\noexpand\protect |
\expandafter\noexpand\csname SF@gobble@opt \endcsname} |
\def\SF@gobble@twobracket[#1]#2{} |
\newenvironment{intest}{\noindent\large\bf\hspace*{1pt}} |
{\vspace*{-5pt}\\\line(1,0){433}} |
\usepackage{babel} |
\makeatother |
\begin{document} |
\thispagestyle{empty} |
\begin{center}{\LARGE S.Ha.R.K. User Manual}\end{center}{\LARGE \par} |
\vfill{} |
\begin{center}Volume I \end{center} |
\begin{center}Kernel Primitives\end{center} |
\vfill{} |
\begin{center}Written by\end{center} |
\begin{center}Giorgio Buttazzo (giorgio at sssup.it)\end{center} |
\begin{center}Paolo Gai (pj at sssup.it)\end{center} |
\begin{center}Luigi Palopoli (luigi at hartik.sssup.it)\end{center} |
\begin{center}Marco Caccamo (caccamo at sssup.it)\end{center} |
\begin{center}Giuseppe Lipari (lipari at sssup.it) \end{center} |
\begin{center}Tullio Facchinetti (tullio.facchinetti at unipv.it)\end{center} |
\vfill{} |
\begin{center}\includegraphics[width=2cm]{../common/sssup.ps}\end{center} |
\begin{center}Scuola Superiore di Studi e Perfezionamento S. Anna\end{center} |
\begin{center}RETIS Lab\end{center} |
\begin{center}Via Carducci, 40 - 56100 Pisa\end{center} |
\begin{center}\pagebreak\end{center} |
\tableofcontents{} |
\include{introd} |
\include{sys} |
\include{semaf} |
\include{util} |
\appendix |
\include{errors} |
\printindex{} |
\bibliographystyle{alpha} |
\bibliography{../common/biblio} |
\end{document} |
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/over.eps |
=================================================================== |
--- new_sharkdoc/vol1/over.eps (nonexistent) |
+++ new_sharkdoc/vol1/over.eps (revision 1676) |
@@ -0,0 +1,217 @@ |
+%!PS-Adobe-2.0 EPSF-2.0 |
+%%Title: over.fig |
+%%Creator: fig2dev Version 3.2 Patchlevel 1 |
+%%CreationDate: Wed Jul 12 11:38:50 2000 |
+%%For: pj@galadriel (Paolo Gai) |
+%%Orientation: Portrait |
+%%BoundingBox: 0 0 248 135 |
+%%Pages: 0 |
+%%BeginSetup |
+%%EndSetup |
+%%Magnification: 1.0000 |
+%%EndComments |
+/$F2psDict 200 dict def |
+$F2psDict begin |
+$F2psDict /mtrx matrix put |
+/col-1 {0 setgray} bind def |
+/col0 {0.000 0.000 0.000 srgb} bind def |
+/col1 {0.000 0.000 1.000 srgb} bind def |
+/col2 {0.000 1.000 0.000 srgb} bind def |
+/col3 {0.000 1.000 1.000 srgb} bind def |
+/col4 {1.000 0.000 0.000 srgb} bind def |
+/col5 {1.000 0.000 1.000 srgb} bind def |
+/col6 {1.000 1.000 0.000 srgb} bind def |
+/col7 {1.000 1.000 1.000 srgb} bind def |
+/col8 {0.000 0.000 0.560 srgb} bind def |
+/col9 {0.000 0.000 0.690 srgb} bind def |
+/col10 {0.000 0.000 0.820 srgb} bind def |
+/col11 {0.530 0.810 1.000 srgb} bind def |
+/col12 {0.000 0.560 0.000 srgb} bind def |
+/col13 {0.000 0.690 0.000 srgb} bind def |
+/col14 {0.000 0.820 0.000 srgb} bind def |
+/col15 {0.000 0.560 0.560 srgb} bind def |
+/col16 {0.000 0.690 0.690 srgb} bind def |
+/col17 {0.000 0.820 0.820 srgb} bind def |
+/col18 {0.560 0.000 0.000 srgb} bind def |
+/col19 {0.690 0.000 0.000 srgb} bind def |
+/col20 {0.820 0.000 0.000 srgb} bind def |
+/col21 {0.560 0.000 0.560 srgb} bind def |
+/col22 {0.690 0.000 0.690 srgb} bind def |
+/col23 {0.820 0.000 0.820 srgb} bind def |
+/col24 {0.500 0.190 0.000 srgb} bind def |
+/col25 {0.630 0.250 0.000 srgb} bind def |
+/col26 {0.750 0.380 0.000 srgb} bind def |
+/col27 {1.000 0.500 0.500 srgb} bind def |
+/col28 {1.000 0.630 0.630 srgb} bind def |
+/col29 {1.000 0.750 0.750 srgb} bind def |
+/col30 {1.000 0.880 0.880 srgb} bind def |
+/col31 {1.000 0.840 0.000 srgb} bind def |
+ |
+end |
+save |
+-23.0 148.0 translate |
+1 -1 scale |
+ |
+/cp {closepath} bind def |
+/ef {eofill} bind def |
+/gr {grestore} bind def |
+/gs {gsave} bind def |
+/sa {save} bind def |
+/rs {restore} bind def |
+/l {lineto} bind def |
+/m {moveto} bind def |
+/rm {rmoveto} bind def |
+/n {newpath} bind def |
+/s {stroke} bind def |
+/sh {show} bind def |
+/slc {setlinecap} bind def |
+/slj {setlinejoin} bind def |
+/slw {setlinewidth} bind def |
+/srgb {setrgbcolor} bind def |
+/rot {rotate} bind def |
+/sc {scale} bind def |
+/sd {setdash} bind def |
+/ff {findfont} bind def |
+/sf {setfont} bind def |
+/scf {scalefont} bind def |
+/sw {stringwidth} bind def |
+/tr {translate} bind def |
+/tnt {dup dup currentrgbcolor |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} |
+ bind def |
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul |
+ 4 -2 roll mul srgb} bind def |
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def |
+/$F2psEnd {$F2psEnteredState restore end} def |
+%%EndProlog |
+ |
+$F2psBegin |
+10 setmiterlimit |
+n -1000 1164 m -1000 -1000 l 1301 -1000 l 1301 1164 l cp clip |
+ 0.90000 0.90000 sc |
+% Polyline |
+0.500 slw |
+n 44 143 m 44 149 l gs col-1 s gr |
+% Polyline |
+n 59 143 m 59 149 l gs col-1 s gr |
+% Polyline |
+n 74 143 m 74 149 l gs col-1 s gr |
+% Polyline |
+n 89 143 m 89 149 l gs col-1 s gr |
+% Polyline |
+n 104 143 m 104 149 l gs col-1 s gr |
+% Polyline |
+n 119 143 m 119 149 l gs col-1 s gr |
+% Polyline |
+n 134 143 m 134 149 l gs col-1 s gr |
+% Polyline |
+n 149 143 m 149 149 l gs col-1 s gr |
+% Polyline |
+n 164 143 m 164 149 l gs col-1 s gr |
+% Polyline |
+n 179 143 m 179 149 l gs col-1 s gr |
+% Polyline |
+n 194 143 m 194 149 l gs col-1 s gr |
+% Polyline |
+n 209 143 m 209 149 l gs col-1 s gr |
+% Polyline |
+n 224 143 m 224 149 l gs col-1 s gr |
+% Polyline |
+n 239 143 m 239 149 l gs col-1 s gr |
+% Polyline |
+n 254 143 m 254 149 l gs col-1 s gr |
+% Polyline |
+n 269 143 m 269 149 l gs col-1 s gr |
+% Polyline |
+n 284 143 m 284 149 l gs col-1 s gr |
+% Polyline |
+n 44 68 m 44 74 l gs col-1 s gr |
+% Polyline |
+n 59 68 m 59 74 l gs col-1 s gr |
+% Polyline |
+n 74 68 m 74 74 l gs col-1 s gr |
+% Polyline |
+n 89 68 m 89 74 l gs col-1 s gr |
+% Polyline |
+n 104 68 m 104 74 l gs col-1 s gr |
+% Polyline |
+n 119 68 m 119 74 l gs col-1 s gr |
+% Polyline |
+n 134 68 m 134 74 l gs col-1 s gr |
+% Polyline |
+n 149 68 m 149 74 l gs col-1 s gr |
+% Polyline |
+n 164 68 m 164 74 l gs col-1 s gr |
+% Polyline |
+n 179 68 m 179 74 l gs col-1 s gr |
+% Polyline |
+n 194 68 m 194 74 l gs col-1 s gr |
+% Polyline |
+n 209 68 m 209 74 l gs col-1 s gr |
+% Polyline |
+n 224 68 m 224 74 l gs col-1 s gr |
+% Polyline |
+n 239 68 m 239 74 l gs col-1 s gr |
+% Polyline |
+n 269 68 m 269 74 l gs col-1 s gr |
+% Polyline |
+n 284 68 m 284 74 l gs col-1 s gr |
+% Polyline |
+n 59 149 m 59 134 l 29 134 l 29 149 l cp gs 0.60 setgray ef gr gs col-1 s gr |
+% Polyline |
+n 119 149 m 119 134 l 89 134 l 89 149 l cp gs 0.60 setgray ef gr gs col-1 s gr |
+% Polyline |
+n 179 149 m 179 134 l 149 134 l 149 149 l cp gs 0.60 setgray ef gr gs col-1 s gr |
+% Polyline |
+n 284 149 m 284 134 l 254 134 l 254 149 l cp gs 0.60 setgray ef gr gs col-1 s gr |
+% Polyline |
+n 89 74 m 89 59 l 59 59 l 59 74 l cp gs 0.80 setgray ef gr gs col-1 s gr |
+% Polyline |
+n 254 74 m 254 59 l 209 59 l 209 74 l cp gs 0.80 setgray ef gr gs col-1 s gr |
+/Times-Roman ff 10.00 scf sf |
+26 164 m |
+gs 1 -1 sc (0) col0 sh gr |
+/Times-Roman ff 10.00 scf sf |
+86 164 m |
+gs 1 -1 sc (4) col0 sh gr |
+/Times-Roman ff 10.00 scf sf |
+146 164 m |
+gs 1 -1 sc (8) col0 sh gr |
+/Times-Roman ff 10.00 scf sf |
+206 164 m |
+gs 1 -1 sc (12) col0 sh gr |
+/Times-Roman ff 10.00 scf sf |
+266 164 m |
+gs 1 -1 sc (16) col0 sh gr |
+% Polyline |
+n 77 17 m 77 17 l 77 17 l 77 17 l cp gs 0.75 setgray ef gr gs col0 s gr |
+% Polyline |
+n 29 74 m 299 74 l gs col-1 s gr |
+% Polyline |
+n 29 119 m 29 149 l 299 149 l gs col-1 s gr |
+% Polyline |
+n 89 119 m 89 149 l gs col-1 s gr |
+% Polyline |
+n 149 119 m 149 149 l gs col-1 s gr |
+% Polyline |
+n 209 119 m 209 149 l gs col-1 s gr |
+% Polyline |
+n 269 119 m 269 149 l gs col-1 s gr |
+% Polyline |
+n 29 149 m 29 152 l gs col-1 s gr |
+% Polyline |
+n 89 149 m 89 152 l gs col-1 s gr |
+% Polyline |
+n 149 149 m 149 152 l gs col-1 s gr |
+% Polyline |
+n 209 149 m 209 152 l gs col-1 s gr |
+% Polyline |
+n 269 149 m 269 152 l gs col-1 s gr |
+% Polyline |
+n 29 44 m 29 74 l gs col-1 s gr |
+% Polyline |
+n 254 44 m 254 74 l gs col-1 s gr |
+$F2psEnd |
+rs |
/new_sharkdoc/vol1/over.eps |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/semaf.tex |
=================================================================== |
--- new_sharkdoc/vol1/semaf.tex (nonexistent) |
+++ new_sharkdoc/vol1/semaf.tex (revision 1676) |
@@ -0,0 +1,1155 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{Synchronization and communication} |
+%---------------------------------------------------------------------------- |
+ |
+This chapter describes the task's interaction capabilities provided by the |
+S.Ha.R.K. kernel. In order to improve the programming flexibility without |
+jeopardizing the hard tasks' a priori guarantee, the kernel implements different |
+mechanisms. |
+ |
+In general, hard tasks should not use system calls that can cause an unbounded |
+(or unknown) blocking time, since they can jeopardize the system schedulability. |
+ |
+\begin{figure} |
+\begin{center}\includegraphics{over.eps}\end{center} |
+\caption{EDF Scheduling - Overload due to a task\_delay().} |
+\label{fg:semaf-over} |
+\end{figure} |
+ |
+For example, consider Figure~\ref{fg:semaf-over}: in this case there are two |
+periodic tasks, $\tau_{1}$ (execution time $C_{1}=5$ and period $T_{1}=15$) and |
+$\tau_{2}$ (execution time $C_{2}=2$ and period $T_{2}=4$). Since the total |
+utilization factor is $U=1/2+1/3=5/6<1$, the system is schedulable by EDF, but |
+if $\tau_{1}$ blocks for $8$ time units at time $t=4$, $\tau_{2}$ misses a |
+deadline at time $t=16$. |
+ |
+For efficiency reasons, the system does not perform any check to avoid the use |
+of blocking primitives in hard tasks; so this aspect is left to the programmer |
+responsibility. |
+ |
+%---------------------------------------------------------------------------- |
+\section{POSIX Semaphores} |
+%---------------------------------------------------------------------------- |
+ |
+The primitives described in this Section covers the semaphore mechanism |
+interface that can be used by the S.Ha.R.K. applications. The semaphore |
+interface directly follows the POSIX semaphore interface; the S.Ha.R.K. Kernel |
+add also some other primitives that allows to increment/decrement the semaphore |
+counter by more than one unit at a time. |
+ |
+These primitives can be used both for synchronization and mutual exclusion. It |
+is worth noting that the traditional semaphore mechanism can cause unbounded |
+\emph{priority inversion}, so it is not suitable for hard real-time tasks. |
+Concerning the synchronization, we note that the guarantee mechanism does not |
+take synchronization into account; therefore the programmer should avoid to |
+explicitly synchronize hard tasks by means of blocking primitives. It is instead |
+possible to use a weak synchronization between hard real-time tasks, realized |
+through non-blocking semaphores. |
+ |
+Only \texttt{SEM\_NSEMS\_MAX} semaphores can be created in the system. If an |
+application needs to use the POSIX semaphores, it have to add the call to the |
+function |
+ |
+\texttt{void SEM\_register\_module(void);} |
+ |
+into the \texttt{\_\_kernel\_register\_levels\_\_} function of the |
+initialization file (see Volume III - S.Ha.R.K. Modules). |
+ |
+In this section will be briefly described the POSIX semaphore interface |
+\footnote{This section only described unnamed semaphores. The interface for |
+named semaphores is also provided, althoutgh it does not use a file system but |
+resolve the names internally (as allowed by the POSIX 1003.13 PSE51 profile).}. |
+For a complete reference see the POSIX standard (the Linux manpage also works |
+well). |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_INIT\index{sem\_init()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_init(sem\_t {*}sem, int pshared, unsigned int value);}] |
+ |
+\item [\textbf{Description:}] It is used to initialize a semaphore referred by |
+sem. The value of the initialized semaphore is \texttt{value}. The pshared |
+argument is ignored. After the call to the primitive, the sem value can bve used |
+to refer the semaphore. |
+ |
+\item [\textbf{Return value:}] on successful completion, the function |
+initializes the semaphore in sem and returns 0. Otherwise, it returns -1 and |
+\texttt{errno} is set according to the POSIX standard. |
+ |
+\item [\textbf{See also}:] sem\_wait(), sem\_trywait, sem\_post(), |
+sem\_destroy(). |
+ |
+\end{description} |
+ |
+\begin{description} |
+\item \texttt{[Example]} |
+\end{description} |
+ |
+\begin{verbatim} |
+sem_t mutex; |
+ |
+TASK demo(void *arg) { |
+ ... |
+ |
+ /* The task enters a critical section protected by a mutex semaphore */ |
+ sem_wait(&mutex); |
+ <critical section> |
+ sem_post(&mutex); |
+ ... |
+} |
+ |
+int main(int argc, char**argv) { |
+ ... |
+ sem_init(&mutex, 0, 1); |
+ ... |
+} |
+\end{verbatim} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_DESTROY\index{sem\_destroy()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_destroy(sem\_t {*}sem);}] |
+ |
+\item [\textbf{Description:}] It is used to destroy the semaphore indicated by |
+sem. Only a semaphore that was created using sem\_init() may be destroyed using |
+sem\_destroy(). \textbf{Warning}: This system call does not check if the |
+semaphore queue is empty or not, and does not awake tasks blocked on the |
+semaphore. The programmer has to make sure that \texttt{s} is free before |
+destroying it. |
+ |
+\item [\textbf{Return value}:] on successful completion, the function destroys |
+the sem semaphore and returns 0. Otherwise, it returns -1 and \texttt{errno} is |
+set according to the POSIX standard. |
+ |
+\item [\textbf{See also}:] sem\_init(). |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_WAIT\index{sem\_wait()} and SEM\_TRYWAIT\index{sem\_trywait()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_wait(sem\_t {*}sem);}] |
+ |
+\item [\textbf{int sem\_trywait(sem\_t {*}sem);}] |
+ |
+\item [\textbf{Description:}] is used to lock the semaphore referenced by |
+\texttt{sem}. If the semaphore value is currently zero, then the calling task |
+shall not return from the call to \texttt{sem\_wait}() until it either locks the |
+semaphore. \texttt{sem\_trywait} locks the semaphore referenced by \texttt{sem} |
+only if the semaphore is currently not locked; that is, if the semaphore value |
+is currently positive. Otherwise, it does not lock the semaphore. |
+\texttt{sem\_wait} is a cancellation point. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return 0. |
+Otherwise, they return -1 and \texttt{errno} is set according to the POSIX |
+standard. |
+ |
+\item [\textbf{See also}:] sem\_post(). |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_XWAIT\index{sem\_wait()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{BYTE sem\_xwait(sem\_t {*}s, int n, int wait);}] |
+ |
+\item [Description:]\texttt{sem\_xwait()} is a non-portable extension to the |
+POSIX semaphores that decreases the semaphore counter by \texttt{n}. If the |
+counter is greater than or equal to \texttt{n} and there are no tasks blocked on |
+semaphore \texttt{s}, the counter is decreased by \texttt{n} and |
+\texttt{sem\_xwait} returns 0, otherwise the system call's behavior depends on |
+the \texttt{b} parameter. If \texttt{wait} is \texttt{BLOCK}, the calling task |
+blocks on the semaphore, if \texttt{wait} is \texttt{NON\_BLOCK} |
+\texttt{sem\_xwait} returns -1, errno is set to EAGAIN and the calling task does |
+not block. The semaphore queue is ordered using a FIFO strategy, in order to |
+avoid starvation. Hard tasks should not use blocking system calls, so it is |
+suggested to use \texttt{sem\_trywait()/xwait()} (only with \texttt{b = |
+NON\_BLOCK}). \texttt{sem\_xwait} is a cancellation point. |
+ |
+\item [\textbf{Return value:}] on successful completion, the function returns 0. |
+Otherwise, it returns -1 and \texttt{errno} is set according to the POSIX |
+standard. |
+ |
+\item [\textbf{See also}:] sem\_wait(), sem\_trywait(), sem\_post(). |
+ |
+\end{description} |
+ |
+\begin{description} |
+\item [\textbf{Example:}] |
+\end{description} |
+ |
+\begin{verbatim} |
+sem_t sync; |
+ |
+TASK demo(void *arg) { |
+ ... |
+ /* The demo task synchronizes itself */ |
+ /* with the wake task, waiting */ |
+ /* for 5 signals on the sync semaphore */ |
+ sem_xwait(&sync, 5, BLOCK); |
+ ... |
+} |
+ |
+TASK wake(void *arg) { |
+ while (1) { |
+ ... |
+ sem_xsignal(sync, 1); |
+ ... |
+ task_endcycle(); |
+ } |
+} |
+ |
+void main(void) { |
+ ... |
+ sem_init(&sync, 0, 0); |
+ ... |
+} |
+\end{verbatim} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_POST\index{sem\_post()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_post(sem\_t {*}sem);}] |
+ |
+\item [\textbf{Description:}]It unlocks the semaphore referenced by sem by |
+performing the semaphore unlock operation on that semaphore. If the semaphore |
+queue is not empty and the first task in the queue requests a feasible counter |
+decrement, it can be awaken. The task is put in the ready queue and the |
+scheduler is invoked: for this reason this system call can cause a preemption. |
+The semaphore queue is a FIFO queue: tasks are awoken in a FIFO order according |
+to resource availability. |
+ |
+\item [\textbf{Return value:}] on successful completion, the function destroys |
+the sem semaphore and returns 0. Otherwise, it returns -1 and \texttt{errno} is |
+set according to the POSIX standard. |
+ |
+\item [\textbf{See also}:] sem\_wait(), sem\_trywait(). |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_XPOST\index{sem\_xpost()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_xpost(sem\_t {*}s, int n);}] |
+ |
+\item [\textbf{Description:}]\texttt{sem\_xpost()} is a non-portable extension |
+to the POSIX semaphores that implements the classical signal primitive on |
+semaphore \texttt{s}, increasing the counter by \texttt{n}. If the semaphore |
+queue is not empty and the first task in the queue requests a feasible counter |
+decrement, it can be awaken. The task is put in the \texttt{READY} queue and the |
+scheduler is invoked: for this reason this system call can cause a preemption. |
+The semaphore queue is a FIFO queue: tasks are awoken in a FIFO order according |
+to resource availability. |
+ |
+\item [\textbf{Return value:}] on successful completion, the function destroys |
+the sem semaphore and returns 0. Otherwise, it returns -1 and \texttt{errno} is |
+set according to the POSIX standard. |
+ |
+\item [\textbf{See also}:] \texttt{sem\_init(), sem\_wait(), sem\_destroy()}. |
+ |
+\item [Example:]see \texttt{sem\_wait()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SEM\_GETVALUE\index{sem\_getvalue()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int sem\_getvalue(sem\_t {*}sem, int {*}sval);}] |
+ |
+\item [\textbf{Description:}]\texttt{sem\_getvalue()} updates the location |
+referenced by the sval argument to have the value of the semaphore referenced by |
+sem without affecting the state of the semaphore. If sem is locked the value |
+returned by sem\_getvalue is a negative number whose absolute value represents |
+the number of processes waiting for the semaphore at some unspecified time |
+during the call. |
+ |
+\item [\textbf{Return value:}] on successful completion, the function destroys |
+the sem semaphore and returns 0. Otherwise, it returns -1 and \texttt{errno} is |
+set according to the POSIX standard. |
+ |
+\item [\textbf{See also}:] \texttt{sem\_init(), sem\_wait(), sem\_destroy()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Internal Semaphores} |
+%---------------------------------------------------------------------------- |
+ |
+When developing a complex driver of the kernel, a designer usually needs to |
+manage a lot of shared resources that have to be accessed in mutual exclusion, |
+and needs also a lot of synchronization points that are not cancellation points. |
+For these pourposes the POSIX semaphores are not good because they are limited |
+in number and they are cancellation points. |
+ |
+For this pourpose the S.Ha.R.K. Kernel provides a sort of lightweight semaphores |
+called \emph{internal} semaphores, that fulfill the designer needs \footnote{The |
+existence of two type of semaphores is not new in Kernel development; For |
+example, the Linux Kernel differentiate the semaphores used by the applications |
+and the semaphors used by the Kernel.}: they are not cancellation points and |
+there is no limit on the number of semaphores that can be created in a system |
+\footnote{Only 8 bytes are taken for each internal semaphore. In some sense the |
+internal semaphores are similar to the POSIX mutexes...}. The interface of the |
+Internal semaphores is very similar to POSIX semaphore interface. |
+ |
+To use the Internal Semaphores, you don't need to call any registration function |
+at kernel startup time. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INTERNAL\_SEM\_INIT\index{internal\_sem\_init()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void internal\_sem\_init(internal\_sem\_t {*}s, int value);}] |
+ |
+\item [\textbf{Description:}]It initializes the internal semaphore \texttt{s} |
+with a specified \texttt{value}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INTERNAL\_SEM\_WAIT\index{internal\_sem\_wait()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void internal\_sem\_wait(internal\_sem\_t {*}s);}] |
+ |
+\item [\textbf{Description:}]It implements a blocking wait. the semaphore |
+counter is decremented by one. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INTERNAL\_SEM\_TRYWAIT\index{internal\_sem\_trywait()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int internal\_sem\_trywait(internal\_sem\_t {*}s);}] |
+ |
+\item [\textbf{Description:}]It implements a non-blocking wait. It returns 0 if |
+the counter is decremented, -1 if not. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INTERNAL\_SEM\_POST\index{internal\_sem\_post()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void internal\_sem\_post(internal\_sem\_t {*}s);}] |
+ |
+\item [\textbf{Description:}]It implements a post operation. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INTERNAL\_SEM\_GETVALUE\index{internal\_sem\_getvalue()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int internal\_sem\_getvalue(internal\_sem\_t {*}s);}] |
+ |
+\item [\textbf{Description:}]It returns a value greater or equal 0 if there are |
+no tasks blocked on s, -1 otherwise. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Mutexes and Condition Variables} |
+%---------------------------------------------------------------------------- |
+ |
+The primitives described in this section allows the user to define and use |
+\emph{mutexes} and \emph{condition variables}. A mutex can be thought as a |
+binary semaphore initialized to 1. In that way, a critical section can be |
+specified using the \emph{mutex\_lock} and \emph{mutex\_unlock} primitives. |
+Moreover, using condition variables a task can block itself waiting for an |
+event. |
+ |
+The provided implementation extends the POSIX standard mutex functions |
+implementing protocols like Stack Resource Policy and Non Preemptive |
+Protocol, that are not part of the standard. To do that, the mutex |
+initialization interface is different from the standard to allow the |
+specification of the various policies. In any case, the standard interface |
+is provided based on the extended interface. |
+ |
+%---------------------------------------------------------------------------- |
+\subsection{Mutex attributes} |
+%---------------------------------------------------------------------------- |
+ |
+A mutex can be used to implement critical sections that uses different |
+policies (for example, the Priority Inheritance, Priority Ceiling |
+or Stack Resource Policy protocol). The S.Ha.R.K. Kernel provides |
+a set of structures derived from the basic structure mutexattr\_t |
+\footnote{Similar to the pthread\_mutexattr\_t structures of the POSIX |
+standard.} that allow to handle the specification of different policies. |
+ |
+The mutex attributes are different foe every policy, that is implemented |
+by a Resouce Module. To see the the description of the mutex attributes |
+for every policy, look at the S.Ha.R.K. Modules Manual. |
+ |
+%---------------------------------------------------------------------------- |
+\subsection{Functions} |
+%---------------------------------------------------------------------------- |
+ |
+This subsection describes the functions that handle mutexes and condition |
+variables. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+MUTEX\_INIT\index{mutex\_init()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int mutex\_init(mutex\_t {*}mutex, const mutexattr\_t {*}attr);}] |
+ |
+\item [\textbf{Description:}]The mutex\_init function inituializes the mutex |
+referenced by \emph{mutex} with attributes specified by \emph{attr}. \emph{attr} |
+shall be not equal NULL. Upon successful initialization, the state |
+of the mutex becomes initialized and unlocked. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\item [\textbf{See also}:] mutex\_destroy(). |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+MUTEX\_DESTROY\index{mutex\_destroy()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int mutex\_destroy(mutex\_t {*}mutex);}] |
+ |
+\item [\textbf{Description:}]The mutex\_destroy function destroys the mutex |
+object |
+referenced by mutex. It is safe to destroy an initialize mutex that |
+is unlocked. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\item [\textbf{See also}:] mutex\_init(). |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+MUTEX\_LOCK\index{mutex\_lock()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int mutex\_lock(mutex\_t {*}mutex);}] |
+ |
+\item [\textbf{Description:}]The mutex\_lock function locks an unlocked mutex. |
+If |
+the mutex is already locked , the calling thread waits until the mutex |
+becomes available. the behaviour of the function may change depending |
+on the particular policy passed with the mutexattr\_t parameter at |
+mutex initialization. The function is \emph{not} a cancellation point. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+MUTEX\_TRYLOCK\index{mutex\_trylock()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int mutex\_lock(mutex\_t {*}mutex);}] |
+ |
+\item [\textbf{Description:}]The mutex\_trylock function is identycal to |
+mutex\_lock |
+except that if the mutex us locked when the function is called, the |
+calling task does not block but returns -1 and an errno value of EBUSY, |
+as specified by the POSIX standard. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+MUTEX\_UNLOCK\index{mutex\_unlock()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int mutex\_unlock(mutex\_t {*}mutex);}] |
+ |
+\item [\textbf{Description:}]The mutex\_unlock function is called by the owner |
+of |
+the mutex object to release it. If there are thread blocked on the |
+mutex object referenced by mutex when mutex\_lock is called, the mutex |
+becomes available, and the task that will acquire the mutex depends |
+on the policy with that the mutex was initialized. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+COND\_INIT\index{cond\_init()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int cond\_init(cond\_t {*}cond);}] |
+ |
+\item [\textbf{Description:}]The function initializes the condition variable |
+referenced |
+by cond. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+COND\_DESTROY\index{cond\_destroy()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int cond\_destroy(cond\_t {*}cond);}] |
+ |
+\item [\textbf{Description:}]The function destroys the given condition variable |
+specified by cond. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+COND\_SIGNAL\index{cond\_signal()} and COND\_BROADCAST\index{cond\_broadcast()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int cond\_signal(cond\_t {*}cond);}] |
+ |
+\item [\textbf{int cond\_broadcast(cond\_t {*}cond);}] |
+ |
+\item [\textbf{Description:}]The function cond\_signal unblocks at least one of |
+the threads that are blocked on the specified condition variable cond. |
+The function cond\_broadcast unblocks all threads currently blocked |
+on the specified condition variable cond. These functions have no |
+effect if there are no threads currently blocked on cond. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+COND\_WAIT\index{cond\_wait()} and COND\_TIMEDWAIT\index{cond\_timedwait()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{int cond\_wait(cond\_t {*}cond, mutex\_t {*}mutex);}] |
+ |
+\item [\textbf{int cond\_timedwait(cond\_t {*}cond, mutex\_t {*}mutex, |
+const struct timespec {*}abstime);}] |
+ |
+\item [\textbf{Description:}]These functions are used to block on a condition |
+variable. |
+They shall be called with \emph{mutex} locked by the calling task. |
+These functions release mutex and cause the calling task to block |
+on the condition variable cond. Upon successful return, the mutex |
+is locked and is owned by the calling task. When using condition variables, |
+there is always a Boolean predicate involving shared variables associated |
+with each condition wait that is true if the thread should proceed. |
+Spurious wakeups from the \texttt{cond\_wait} or \texttt{cond\_timedwait} |
+functions may occur. Since the return from \texttt{cond\_wait} or |
+\texttt{cond\_timedwait} does not imply anything about the value of |
+this predicate, the predicate should be re-evaluated upon each return. |
+ |
+The \texttt{cond\_wait} and cond\_timedwait functions are cancellation |
+points. When the cancelability enable state of a task is set to |
+\texttt{TASK\_CANCEL\_DEFERRED}, |
+a side effect of acting upon a cancellation request while in a condition |
+wait is that the mutex is (in effect) reaquired before calling the |
+first cancellation cleanup handler. To ensure a correct cancellation, |
+a cleanup function should be pushed before the \texttt{cond\_wait} |
+call (in case of cancellation it simply unlock the mutex). |
+ |
+The \texttt{cond\_timedwait} function is the same as the \texttt{cond\_wait} |
+function except that an error is returned if the absolute time specified |
+by abstime passes before the condition cond is signaled or broadcasted, |
+or if the absolute time specified by abstime has already been passed |
+at the time of the call. |
+ |
+\item [\textbf{Return value:}] on successful completion the functions return |
+0. Otherwise, they return -1 and \texttt{errno} is set according to |
+the POSIX standard. |
+ |
+\end{description} |
+ |
+% |
+% Tool: still in use? |
+% |
+ |
+% %---------------------------------------------------------------------------- |
+% \section{Communication Ports \footnote{The S.Ha.R.K. communication ports are |
+% directly derived from the previous varsions of the Hartik Kernel.}} |
+% %---------------------------------------------------------------------------- |
+% |
+% S.Ha.R.K. communication ports allow tasks to exchange messages. Each |
+% port is uniquely identified by a symbolic name (i.e., a string of |
+% characters); a task willing to use this communication facility has |
+% to open the channel using the \texttt{port\_create()} call, thus becoming |
+% the owner of the resource. Any other task that wants to use this communication |
+% end-point to send or receive data needs to connect to it by using |
+% the \texttt{port\_connect()} primitive. |
+% |
+% S.Ha.R.K. offers three types of ports: |
+% |
+% \begin{itemize} |
+% |
+% \item \texttt{STREAM}: it is a one-to-one communication facility, which |
+% can be opened either by the reader or by the writer task. The task |
+% executing the \texttt{port\_create()} must specify the message size |
+% and maximum number of messages in the queue. The task executing the |
+% |
+% \texttt{port\_connect()} must only specify the size of the messages |
+% it wants to receive/send, which can be different from the one specified |
+% by the owner. For example, a task may open a port for reading messages |
+% of 4 bytes, while another task can connect to it to write one-byte |
+% messages. This mechanism turns out to be useful for character oriented |
+% device drivers which need to fill a given structure, before the message |
+% can be processed further by a higher-level task. |
+% |
+% \item \texttt{MAILBOX}: it is a many-to-one communication facility, thought |
+% for being used in classical client/server mechanisms. This kind of |
+% port can only be opened by the reader task (the server) which wants |
+% to receive data from writer tasks (the clients). Message size is fixed |
+% and defined by the reader. |
+% |
+% \item \texttt{STICK}: it is a one-to-many communication facility intended |
+% to be used for exchanging periodic state-messages, for which the most |
+% recent information is relevant. It can be opened only by the (unique) |
+% writer task and the reading tasks must connect to it. It contains |
+% just one message and any new message posted by the writer will overwrite |
+% the previous one. Messages are non-consumable: a reader task can perform |
+% many readings of a given message until the writer posts a new one. |
+% \end{itemize} |
+% |
+% The first two kinds of port implement the synchronous communication |
+% paradigm, while \texttt{STICK} ports implement an asynchronous (state-message) |
+% paradigm. It is worth noting that in order to protect the internal |
+% data structures, \texttt{STREAM} ports use semaphores for synchronizing |
+% the accesses, \texttt{STICK} ports just use a mutual exclusion semaphore, |
+% and the \texttt{MAILBOX} ports use both kinds of semaphores. |
+% |
+% For this reason, \texttt{MAILBOX} and \texttt{STICK} ports should |
+% not be used by critical tasks, whereas \texttt{STREAM} ports can be |
+% used by any task requiring a state-message non-blocking semantics. |
+% Moreover, the execution time of a transaction depends on the message |
+% size (the message is copied in/from the buffer when a send/receive |
+% is performed). The semantics associated with each port is graphically |
+% illustrated in Figure \ref{fg:port-type}. |
+% |
+% An application that uses the communication ports, must register the |
+% HARTPORT Module. Please see Volume III - S.Ha.R.K. Modules for details. |
+% |
+% \begin{figure} |
+% \begin{center}\includegraphics[width=8cm]{port.eps}\end{center} |
+% \caption{HARTIK ports.\label{fg:port-type}} |
+% \end{figure} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_CREATE\index{port\_create()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{PORT port\_create(char {*}name, int dim, int num, |
+% int type, int mode);}] |
+% |
+% \item [\textbf{Description:}]It opens the port identified by the string |
+% \texttt{name}. |
+% The argument \texttt{dim} specifies the message size in bytes, \texttt{num} |
+% specifies the queue size, \texttt{type} the port type (\texttt{STREAM}, |
+% \texttt{MAILBOX}, or \texttt{STICK}), and \texttt{mode} the access |
+% mode (\texttt{READ} or \texttt{WRITE}). |
+% |
+% \item [\textbf{Return Value:}] The primitive returns the port identifier, |
+% which identifies the connection between the port and the task, and |
+% not the port itself, which is identified through its name. A return |
+% value -1 indicates that an error is occurred. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_delete(), port\_connect(), |
+% port\_disconnect(), port\_send(), port\_receive()}. |
+% |
+% \end{description} |
+% |
+% \begin{description} |
+% \item [Example:\label{pg:port-ex}] |
+% \item \texttt{TASK demo(void)} \{ |
+% \item \texttt{~~PORT p; } |
+% \item \texttt{~~char msg{[}6{]}; } |
+% \item \texttt{~~\ldots{}} |
+% \item \texttt{~~/{*} Demo task, of NRT type, opens the \char`\"{}goofy\char`\"{} |
+% port {*}/} |
+% \item \texttt{~~/{*} and sends a message of 6 bytes. {*}/} |
+% \item \texttt{~~p = port\_create(\char`\"{}goofy\char`\"{}, 6, 8, STREAM, |
+% WRITE);} |
+% \item \texttt{~~\ldots{}} |
+% \item \texttt{~~port\_send(p, msg, BLOCK); } |
+% \item \texttt{\}} |
+% \item \texttt{~} |
+% \item \texttt{TASK duro(void)} \{ |
+% \item \texttt{~~PORT q; } |
+% \item \texttt{~~char msg{[}2{]}; } |
+% \item \texttt{~~/{*} Duro task (HARD) connects to the \char`\"{}goofy\char`\"{} |
+% {*}/} |
+% \item \texttt{~~/{*} port and receives messages of 2 bytes {*}/ } |
+% \item \texttt{~~q = port\_connect(\char`\"{}goofy\char`\"{}, 2, STREAM, |
+% READ);} |
+% \item \texttt{~~while (condition) \{} |
+% \item \texttt{~~~~\ldots{}} |
+% \item \texttt{~~~~if (port\_receive(q, msg, NON\textbackslash{}\_BLOCK) \{} |
+% \item \texttt{~~~~~~<action 1>;~/{*} Ready Message! {*}/} |
+% \item \texttt{~~~~\}} |
+% \item \texttt{~~~~else \{} |
+% \item \texttt{~~~~~~<action 2>;~/{*} Message not Ready! {*}/} |
+% \item \texttt{~~~~\}} |
+% \item \texttt{~~~~\ldots{}} |
+% \item \texttt{~~~~task\_endcycle();} |
+% \item \texttt{~~\}} |
+% \item \texttt{\}} |
+% |
+% \end{description} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_DELETE\index{port\_delete()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{void port\_delete(PORT p)};] |
+% |
+% \item [\textbf{Description:}]It destroys the port identified by \texttt{p}. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_create(), port\_connect(), |
+% port\_disconnect(), |
+% port\_send(), port\_receive()}. |
+% |
+% \item [\textbf{Example:}]see the example at page \pageref{pg:port-ex}. |
+% |
+% \end{description} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_CONNECT\index{port\_connect()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{PORT port\_connect(char {*}name, int dim, int type, |
+% int mode);}] |
+% |
+% \item [\textbf{Description:}]It connects the calling task to the port identified |
+% by \texttt{name}. The argument \texttt{dim} specifies the message |
+% size in bytes, \texttt{type} the port type (\texttt{STREAM}, \texttt{MAILBOX}, |
+% or \texttt{STICK}), and \texttt{mode} the access mode (\texttt{READ} |
+% or \texttt{WRITE}). If the port has not been opened by \texttt{port\_create()}, |
+% the task is blocked, waiting for port creation. To avoid synchronization |
+% delays, connection should be established only \underbar{after} opening |
+% the port. |
+% |
+% \item [\textbf{Return value:}] The function returns the port identification |
+% number in the case of successful operation; else -1 is returned. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_create(), port\_delete(), |
+% port\_disconnect(), port\_send(), port\_receive()}. |
+% |
+% \end{description} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_DISCONNECT\index{port\_disconnect()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{void port\_disconnect(PORT p)};] |
+% |
+% \item [\textbf{Description:}]It closes the connection identified by \texttt{p}. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_create(), port\_connect(), |
+% port\_delete(), port\_send(), port\_receive()}. |
+% |
+% \end{description} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_SEND\index{port\_send()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{int port\_send(PORT p, char {*}msg, BYTE b);}] |
+% |
+% \item [\textbf{Description:}]It sends a message pointed by \texttt{msg} to the |
+% port identified by \texttt{p}. Message dimension is defined through |
+% \texttt{port\_create()} |
+% or \texttt{port\_connect()} and cannot be dynamically changed. The |
+% argument \texttt{b} can be \texttt{BLOCK} or \texttt{NON\_BLOCK}. |
+% If \texttt{b = BLOCK} and the port queue is full, then the task is |
+% blocked until the buffer is freed. If \texttt{b = NON\_BLOCK} and |
+% the port queue is full, then the primitive returns 0 and the message |
+% is not sent. |
+% |
+% \item [\textbf{Return value:}] 1 (TRUE) if the operation can be performed, |
+% 0 otherwise. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_create(), port\_connect(), |
+% port\_disconnect(), |
+% port\_send(), port\_receive()}. |
+% |
+% \item [\textbf{Example:}]see the example at page \pageref{pg:port-ex}. |
+% |
+% \end{description} |
+% |
+% %---------------------------------------------------------------------------- |
+% \begin{intest} |
+% PORT\_RECEIVE\index{port\_receive()} |
+% \end{intest} |
+% |
+% \begin{description} |
+% |
+% \item [\textbf{int port\_receive(PORT p, char {*}msg, BYTE b);}] |
+% |
+% \item [\textbf{Description:}]It receives a message from the port identified by |
+% \texttt{p} and copies it in a memory buffer pointed by \texttt{msg}. Message |
+% dimension is defined through \texttt{port\_create()} or \texttt{port\_connect()} |
+% and cannot be dynamically changed. The argument \texttt{b} can be |
+% \texttt{BLOCK} or \texttt{NON\_BLOCK}. If \texttt{b = BLOCK} and the |
+% port queue is empty, then the task is blocked until a message is available. |
+% If \texttt{b = NON\_BLOCK} and the port queue is empty, then the primitive |
+% returns 0 and no message is received. |
+% |
+% \item [\textbf{Return value:}] 1 (TRUE) if the operation can be performed, |
+% 0 otherwise. |
+% |
+% \item [\textbf{See also}:] \texttt{port\_create(), port\_connect(), |
+% port\_disconnect(), port\_send(), port\_receive()}. |
+% |
+% \item [\textbf{Example:}]see the example at page \pageref{pg:port-ex}. |
+% |
+% \end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Cyclical Asynchronous Buffers} |
+%---------------------------------------------------------------------------- |
+ |
+\textbf{Cyclical Asynchronous Buffers} (or CABs) represent a particular |
+mechanism purposely designed for the cooperation among periodic activities |
+with different activation rates. See \cite{But97} for implementation |
+details. |
+ |
+A CAB provides a one-to-many communication channel, which at any instant |
+contains the most recent message inserted into it. A message is not |
+consumed (that is, extracted) by a receiving process but is maintained |
+into the CAB structure until a new message is overwritten. As a consequence, |
+once the first message is put in a CAB, a task can never be blocked |
+during a receive operation. Similarly, since a new message overwrites |
+the old one, a sender can never be blocked. |
+ |
+Notice that, using such a semantics, a message can be read more than |
+once if the receiver is faster than the sender, while messages can |
+be lost if the sender is faster than the receiver. However, this is |
+not a problem in many control applications, where tasks are interested |
+only in fresh sensory data rather than in the complete message history |
+produced by a sensory acquisition task. |
+ |
+Notice that more tasks can simultaneously access the same buffer in |
+a CAB for reading. Also, if a task $P$ reserves a CAB for writing |
+while another task $Q$ is using that CAB, a new buffer is created, |
+so that $P$ can write its message without interfering with $Q$. |
+As $P$ finishes writing, its message becomes the most recent one |
+in that CAB. The maximum number of buffers that can be created in |
+a CAB is specified as a parameter in the \emph{cab\_create} primitive. |
+To avoid blocking, this number must be equal to the number of tasks |
+that use the CAB plus one. |
+ |
+CABs can be created and initialized by the \emph{cab\_create} primitive, |
+which requires the CAB name, the dimension of the message, and the |
+number of messages that the CAB may contain simultaneously. The |
+\emph{cab\_delete} |
+primitive removes a CAB from the system and releases the memory space |
+used by its data structures. |
+ |
+To insert a message in a CAB, a task must first reserve a buffer from |
+the CAB memory space, then copy the message into the buffer, and finally |
+put the buffer into the CAB structure, where it becomes the most recent |
+message. This is done according to the following scheme: |
+ |
+\vspace{5mm} \begin{tt} |
+\begin{tabbing} |
+\={b}uf\_pointer = {\textbf{cab\_reserve}}(cab\_id);\\ |
+\>\(<\)copy message in *buf\_pointer\(>\)\\ |
+\>{\textbf{cab\_putmes}}(cab\_id, buf\_pointer);\\ |
+\end{tabbing} |
+\end{tt} |
+ |
+\noindent Similarly, to get a message from a CAB, a task has to get |
+the pointer to the most recent message, use the data, and release |
+the pointer. This is done according to the following scheme: |
+ |
+\vspace{5mm} \begin{tt} |
+\begin{tabbing} |
+\={m}es\_pointer = {\textbf{cab\_getmes}}(cab\_id);\\ |
+\>\(<\)use message\(>\)\\ |
+\>{\textbf{cab\_unget}}(cab\_id, mes\_pointer); |
+\end{tabbing} |
+\end{tt} A simple example of CABs' usage is reported below. |
+ |
+\label{pg:cab-ex} \begin{minipage}{\columnwidth} |
+\begin{small} |
+\begin{tt} |
+\begin{verbatim} |
+CAB cc; |
+ |
+void main(void) { |
+ SYS_PARMS parms = BASE_SYS; |
+ |
+ /* global declaration */ |
+ sys_def_tick(parms, 1, mSec); |
+ sys_init(&parms); |
+ |
+ /* The CAB named cc contains a message of */ |
+ /* 5 floats and can be used by two tasks */ |
+ cc = cab_create("my_cab", 5 * sizeof(float), 3); |
+ task_activate(task_create("ll", read, HARD, APERIODIC, 100, NULL)); |
+ task_activate(task_create("ss", write, HARD, PERIODIC, 333, NULL)); |
+ ... |
+} |
+ |
+/*---------------------------------------------------------------------*/ |
+TASK write(void) { |
+ float msg[5]; |
+ char *pun; |
+ ... |
+ |
+ while (1) { |
+ |
+ /* send a message to the `cc' cab */ |
+ pun = cab_reserve(cc); /* reserve a buffer */ |
+ memcpy(pun, msg, 5 * sizeof(float)); |
+ cab_putmes(cc, pun); /* release the buffer */ |
+ task_endcycle(); |
+ } |
+} |
+ |
+/*---------------------------------------------------------------------*/ |
+TASK read(void) { |
+ float msg[5]; |
+ char *pun; |
+ ... |
+ |
+ while (1) { |
+ |
+ /* get a message from the `cc' CAB */ |
+ pun = cab_getmes(cc); /* reserve a buffer */ |
+ memcpy(msg, pun, 5 * sizeof(float)); |
+ cab_unget(cc, pun); /* release the buffer */ |
+ task_endcycle(); |
+ } |
+} |
+\end{verbatim} |
+\end{tt} |
+\end{small} |
+\end{minipage} |
+ |
+%---------------------------------------------------------------------------- |
+\vspace{7mm} \begin{intest} |
+CAB\_CREATE\index{cab\_create()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{CAB cab\_create(char {*}name, int dim\_mes, BYTE num\_mes)}] |
+ |
+\item [\textbf{Description:}]It initializes a CAB. \texttt{name} is a pointer to |
+an identification string (used only for debugging purposes); \texttt{dim} |
+is the size of the messages contained in the CAB; \texttt{numbuf} |
+is the number of buffers the CAB is composed of. Notice that such |
+a number must be greater than or equal to the number of tasks that |
+use the CAB plus one. |
+ |
+\item [\textbf{Return value:}] It returns the index of the created CAB. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_delete(), cab\_reserve(), cab\_putmes(), |
+cab\_getmes(), cab\_unget()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\vspace{7mm} \begin{intest} |
+CAB\_DELETE\index{cab\_delete()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void cab\_delete(CAB cc);}] |
+ |
+\item [\textbf{Description:}]It removes the \texttt{cc} CAB from the system, |
+deallocating |
+its buffers and data structures. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_create(), cab\_reserve(), cab\_putmes(), |
+cab\_getmes(), cab\_unget()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\vspace{7mm} \begin{intest} |
+CAB\_RESERVE\index{cab\_reserve()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{char {*}cab\_reserve(CAB cc);}] |
+ |
+\item [\textbf{Description:}]it reserves a buffer belonging to the \texttt{cc} |
+CAB and returns a pointer to it. The primitive has to be used only by |
+writers and \emph{never} by readers. |
+ |
+\item [\textbf{Return value:}] it returns a pointer to the reserved buffer. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_delete(), cab\_create(), cab\_putmes(), |
+cab\_getmes(), cab\_unget()}. |
+ |
+\end{description} |
+ |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+CAB\_PUTMES\index{cab\_putmes()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void cab\_putmes(CAB id, char {*}pun)}] |
+ |
+\item [\textbf{Description:}]It inserts the message pointed by \texttt{pun} into |
+the CAB identified by \texttt{id}. This primitive must be used \emph{only} |
+by writing tasks. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_delete(), cab\_create(), cab\_reserve(), |
+cab\_getmes(), cab\_unget()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\vspace{7mm} \begin{intest} |
+CAB\_GETMES\index{cab\_getmes()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{char {*}cab\_getmes(CAB cc);}] |
+ |
+\item [\textbf{Description:}]It returns a pointer to the latest message written |
+into the \texttt{cc} CAB. This primitive must be used \emph{only} |
+by reading tasks. |
+ |
+\item [\textbf{Returned value:}] It returns a pointer to the most recent |
+message contained in the CAB. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_delete(), cab\_create(), cab\_putmes(), |
+cab\_reserve(), cab\_unget()}. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\vspace{7mm} \begin{intest} |
+CAB\_UNGET\index{cab\_unget()} |
+\end{intest} |
+ |
+\begin{description} |
+ |
+\item [\textbf{void cab\_unget(CAB cc, char {*}pun);}] |
+ |
+\item [\textbf{Description:}]it notifies the system that the buffer pointed by |
+\texttt{pun} belonging to the \texttt{cc} CAB is no longer used by the calling |
+task. |
+ |
+\item [\textbf{See also}:] \texttt{cab\_delete(), cab\_create(), cab\_reserve(), |
+cab\_getmes(), cab\_putmes()}. |
+ |
+\end{description} |
+ |
+\section{POSIX Message Queues} |
+ |
+S.Ha.R.K. provides the message passing function defined in the POSIX |
+standard. For more information, see Section 15 of the POSIX standard, |
+Message Passing. |
/new_sharkdoc/vol1/semaf.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/port.eps |
=================================================================== |
--- new_sharkdoc/vol1/port.eps (nonexistent) |
+++ new_sharkdoc/vol1/port.eps (revision 1676) |
@@ -0,0 +1,235 @@ |
+%!PS-Adobe-2.0 EPSF-2.0 |
+%%Title: port.fig |
+%%Creator: fig2dev Version 3.2 Patchlevel 1 |
+%%CreationDate: Wed Jul 12 11:38:50 2000 |
+%%For: pj@galadriel (Paolo Gai) |
+%%Orientation: Portrait |
+%%BoundingBox: 0 0 314 197 |
+%%Pages: 0 |
+%%BeginSetup |
+%%EndSetup |
+%%Magnification: 1.0000 |
+%%EndComments |
+/$F2psDict 200 dict def |
+$F2psDict begin |
+$F2psDict /mtrx matrix put |
+/col-1 {0 setgray} bind def |
+/col0 {0.000 0.000 0.000 srgb} bind def |
+/col1 {0.000 0.000 1.000 srgb} bind def |
+/col2 {0.000 1.000 0.000 srgb} bind def |
+/col3 {0.000 1.000 1.000 srgb} bind def |
+/col4 {1.000 0.000 0.000 srgb} bind def |
+/col5 {1.000 0.000 1.000 srgb} bind def |
+/col6 {1.000 1.000 0.000 srgb} bind def |
+/col7 {1.000 1.000 1.000 srgb} bind def |
+/col8 {0.000 0.000 0.560 srgb} bind def |
+/col9 {0.000 0.000 0.690 srgb} bind def |
+/col10 {0.000 0.000 0.820 srgb} bind def |
+/col11 {0.530 0.810 1.000 srgb} bind def |
+/col12 {0.000 0.560 0.000 srgb} bind def |
+/col13 {0.000 0.690 0.000 srgb} bind def |
+/col14 {0.000 0.820 0.000 srgb} bind def |
+/col15 {0.000 0.560 0.560 srgb} bind def |
+/col16 {0.000 0.690 0.690 srgb} bind def |
+/col17 {0.000 0.820 0.820 srgb} bind def |
+/col18 {0.560 0.000 0.000 srgb} bind def |
+/col19 {0.690 0.000 0.000 srgb} bind def |
+/col20 {0.820 0.000 0.000 srgb} bind def |
+/col21 {0.560 0.000 0.560 srgb} bind def |
+/col22 {0.690 0.000 0.690 srgb} bind def |
+/col23 {0.820 0.000 0.820 srgb} bind def |
+/col24 {0.500 0.190 0.000 srgb} bind def |
+/col25 {0.630 0.250 0.000 srgb} bind def |
+/col26 {0.750 0.380 0.000 srgb} bind def |
+/col27 {1.000 0.500 0.500 srgb} bind def |
+/col28 {1.000 0.630 0.630 srgb} bind def |
+/col29 {1.000 0.750 0.750 srgb} bind def |
+/col30 {1.000 0.880 0.880 srgb} bind def |
+/col31 {1.000 0.840 0.000 srgb} bind def |
+ |
+end |
+save |
+-108.0 304.0 translate |
+1 -1 scale |
+ |
+/cp {closepath} bind def |
+/ef {eofill} bind def |
+/gr {grestore} bind def |
+/gs {gsave} bind def |
+/sa {save} bind def |
+/rs {restore} bind def |
+/l {lineto} bind def |
+/m {moveto} bind def |
+/rm {rmoveto} bind def |
+/n {newpath} bind def |
+/s {stroke} bind def |
+/sh {show} bind def |
+/slc {setlinecap} bind def |
+/slj {setlinejoin} bind def |
+/slw {setlinewidth} bind def |
+/srgb {setrgbcolor} bind def |
+/rot {rotate} bind def |
+/sc {scale} bind def |
+/sd {setdash} bind def |
+/ff {findfont} bind def |
+/sf {setfont} bind def |
+/scf {scalefont} bind def |
+/sw {stringwidth} bind def |
+/tr {translate} bind def |
+/tnt {dup dup currentrgbcolor |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add |
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} |
+ bind def |
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul |
+ 4 -2 roll mul srgb} bind def |
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def |
+/$F2psEnd {$F2psEnteredState restore end} def |
+%%EndProlog |
+ |
+$F2psBegin |
+10 setmiterlimit |
+n -1000 6052 m -1000 -1000 l 8026 -1000 l 8026 6052 l cp clip |
+ 0.06000 0.06000 sc |
+/Times-Roman ff 180.00 scf sf |
+1800 3450 m |
+gs 1 -1 sc (Clients) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+6150 3375 m |
+gs 1 -1 sc (Server) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+6150 3600 m |
+gs 1 -1 sc (\(Owner\)) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+1800 4725 m |
+gs 1 -1 sc (Producers) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+1800 4950 m |
+gs 1 -1 sc (\(Owner\)) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+6150 4725 m |
+gs 1 -1 sc (Consumers) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+2100 2325 m |
+gs 1 -1 sc (Writer) col0 sh gr |
+/Times-Roman ff 180.00 scf sf |
+5850 2325 m |
+gs 1 -1 sc (Reader) col0 sh gr |
+% Polyline |
+7.500 slw |
+n 3375 3240 m 4950 3240 l 4950 3690 l 3375 3690 l gs col-1 s gr |
+% Polyline |
+n 4500 3240 m 4500 3690 l gs col-1 s gr |
+% Polyline |
+n 4275 3240 m 4275 3690 l gs col-1 s gr |
+% Polyline |
+n 4050 3240 m 4050 3690 l gs col-1 s gr |
+% Polyline |
+n 3825 3240 m 3825 3690 l gs col-1 s gr |
+% Polyline |
+n 4725 3240 m 4725 3690 l gs col-1 s gr |
+% Polyline |
+gs clippath |
+5505 3435 m 5625 3465 l 5505 3495 l 5640 3495 l 5640 3435 l cp |
+clip |
+n 4950 3465 m 5625 3465 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 5505 3435 m 5625 3465 l 5505 3495 l col-1 s |
+% Polyline |
+gs clippath |
+3255 3435 m 3375 3465 l 3255 3495 l 3390 3495 l 3390 3435 l cp |
+clip |
+n 2700 3465 m 3375 3465 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 3255 3435 m 3375 3465 l 3255 3495 l col-1 s |
+% Polyline |
+gs clippath |
+3263 3322 m 3375 3375 l 3251 3381 l 3384 3407 l 3396 3349 l cp |
+clip |
+n 2700 3240 m 3375 3375 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 3263 3322 m 3375 3375 l 3251 3381 l col-1 s |
+% Polyline |
+gs clippath |
+3251 3549 m 3375 3555 l 3263 3608 l 3396 3581 l 3384 3523 l cp |
+clip |
+n 2700 3690 m 3375 3555 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 3251 3549 m 3375 3555 l 3263 3608 l col-1 s |
+/Times-Roman ff 150.00 scf sf |
+3825 3060 m |
+gs 1 -1 sc (MAILBOX) col-1 sh gr |
+% Polyline |
+n 4635 5040 m 4635 4410 l 3735 4410 l 3735 5040 l cp gs col-1 s gr |
+% Polyline |
+gs clippath |
+3615 4695 m 3735 4725 l 3615 4755 l 3750 4755 l 3750 4695 l cp |
+clip |
+n 3060 4725 m 3735 4725 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 3615 4695 m 3735 4725 l 3615 4755 l col-1 s |
+% Polyline |
+gs clippath |
+5190 4695 m 5310 4725 l 5190 4755 l 5325 4755 l 5325 4695 l cp |
+clip |
+n 4635 4725 m 5310 4725 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 5190 4695 m 5310 4725 l 5190 4755 l col-1 s |
+% Polyline |
+gs clippath |
+5186 4494 m 5310 4500 l 5198 4553 l 5331 4526 l 5319 4468 l cp |
+clip |
+n 4635 4635 m 5310 4500 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 5186 4494 m 5310 4500 l 5198 4553 l col-1 s |
+% Polyline |
+gs clippath |
+5198 4897 m 5310 4950 l 5186 4956 l 5319 4982 l 5331 4924 l cp |
+clip |
+n 4635 4815 m 5310 4950 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 5198 4897 m 5310 4950 l 5186 4956 l col-1 s |
+/Times-Roman ff 150.00 scf sf |
+4005 4230 m |
+gs 1 -1 sc (STICK) col-1 sh gr |
+% Polyline |
+n 3375 2025 m 4950 2025 l 4950 2475 l 3375 2475 l gs col-1 s gr |
+% Polyline |
+n 4500 2025 m 4500 2475 l gs col-1 s gr |
+% Polyline |
+n 4275 2025 m 4275 2475 l gs col-1 s gr |
+% Polyline |
+n 4050 2025 m 4050 2475 l gs col-1 s gr |
+% Polyline |
+n 3825 2025 m 3825 2475 l gs col-1 s gr |
+% Polyline |
+n 4725 2025 m 4725 2475 l gs col-1 s gr |
+% Polyline |
+gs clippath |
+5505 2220 m 5625 2250 l 5505 2280 l 5640 2280 l 5640 2220 l cp |
+clip |
+n 4950 2250 m 5625 2250 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 5505 2220 m 5625 2250 l 5505 2280 l col-1 s |
+% Polyline |
+gs clippath |
+3255 2220 m 3375 2250 l 3255 2280 l 3390 2280 l 3390 2220 l cp |
+clip |
+n 2700 2250 m 3375 2250 l gs col-1 s gr gr |
+ |
+% arrowhead |
+n 3255 2220 m 3375 2250 l 3255 2280 l col-1 s |
+/Times-Roman ff 150.00 scf sf |
+3870 1890 m |
+gs 1 -1 sc (STREAM) col-1 sh gr |
+$F2psEnd |
+rs |
/new_sharkdoc/vol1/port.eps |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/errors.tex |
=================================================================== |
--- new_sharkdoc/vol1/errors.tex (nonexistent) |
+++ new_sharkdoc/vol1/errors.tex (revision 1676) |
@@ -0,0 +1,98 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{Errors and Exceptions} |
+\label{ch:Errors} \label{ch:Exceptions} |
+%---------------------------------------------------------------------------- |
+ |
+This appendix describes the errors and exceptions codes that can be |
+printed into the screen, returned by a functions into the the \texttt{errno} |
+variables or that the kernel can raise. These error constants are |
+included from the \texttt{errno.h} standard include file, and are |
+contained into the \texttt{bits/errno.h} include file. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Abort codes} |
+%---------------------------------------------------------------------------- |
+ |
+\begin{longtable}{|c|c|c|} |
+\hline Name & N.& Description \\ \hline |
+\hline none & 1 & Generic OSLib abortASIG\_DEFAULT\_ACTION \\ |
+\hline ASIG\_DEFAULT\_ACTION & 2& The default handler of a signal has been executed \\ |
+\hline ASIGINIT & 3 & Internal error in initializing signals (should never happens) \\ |
+\hline AHEXC & 4 & a set\_exchandler\_XXX function has been executed. \\ |
+\hline AARPFULL & 5 & ARP table full. \\ |
+\hline |
+\end{longtable} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Exceptions posted with kern\_raise} |
+%---------------------------------------------------------------------------- |
+ |
+\begin{longtable}{|l|c|p{8cm}|} |
+\hline Name & N. & Description \\ \hline |
+\hline XDOUBLE\_EXCEPTION & 1 & Two exceptions has been raised. Currently not used \\ |
+\hline XUNVALID\_KILL\_SHADOW & 2 & Called into the internal function task\_makefree because a task was killed while some other task shadow points to that task. \\ |
+\hline XNOMORE\_CLEANUPS & 3 & Too many cleanups handlers has been used. Currently not used. \\ |
+\hline XUNVALID\_TASK & 4 & The Registered Modules does not implement a primitive called by the task (usually happens when the user calls task\_delay or task\_sleep) \\ |
+\hline XUNVALID\_GUEST & 5 & The Registered Modules does not handle correctly the guest tasks. Check the initfile. \\ |
+\hline XNOMORE\_EVENTS & 6 & Too many OSLib events posted. The number of OSLib events posted is declared in \texttt{include/ll/sys/ll/event.h} into the constant \texttt{MAX\_EVENT}.\\ |
+\hline XDEADLINE\_MISS & 7 & A Task missed its deadline.\\ |
+\hline XWCET\_VIOLATION & 8 & A Task consumed more tha its declared WCET.\\ |
+\hline XACTIVATION & 9 & A Sporadic task has been activated more frequently than declared.\\ |
+\hline XMUTEX\_OWNER\_KILLED & 10 & A task is terminated while it owns a mutex.\\ |
+\hline XSRP\_UNVALID\_LOCK & 11 & A task tried to lock a SRP mutex with a wrong preemption level, or a task tries to lock a SRP mutex already locked, or a task tries to lock a SRP mutex without declaring its preemption level.\\ |
+\hline XUNVALID\_DUMMY\_OP & 12 & Someone tried to execute an operation on the dummy Scheduling Module.\\ |
+\hline XUNVALID\_SS\_REPLENISH & 13 & Error in the Sporadic Server replenishments. Please look at \texttt{kernel/modules/ss.c}.\\ |
+\hline XARP\_TABLE\_FULL & 14 & Arp table full. See \texttt{drivers/net/arp.c}.\\ |
+\hline XNETBUFF\_INIT\_EXC & 15 & Network buffers error. See \texttt{drivers/net/netbuff.}.\\ |
+\hline XNETBUFF\_GET\_EXC & 16 & Network buffers error. See \texttt{drivers/net/netbuff.}. \\ |
+\hline XNETBUFF\_ALREADYFREE\_EXC & 17 & Network buffers error. See \texttt{drivers/net/netbuff.}. \\ |
+\hline XNETBUFF\_RELEASE\_EXC & 18 & Network buffers error. See \texttt{drivers/net/netbuff.}. \\ |
+\hline XUDP\_BADCHK\_EXC & 19 & UDP CRC check failed. \\ |
+\hline |
+\end{longtable} |
+ |
+%---------------------------------------------------------------------------- |
+\section{POSIX error codes} |
+%---------------------------------------------------------------------------- |
+ |
+The POSIX error codes have numbers form 1 to 125 and are listed into |
+\texttt{include/errno.h}. |
+ |
+%---------------------------------------------------------------------------- |
+\section{S.Ha.R.K. error codes} |
+%---------------------------------------------------------------------------- |
+ |
+\begin{longtable}{|c|c|p{8cm}|} |
+\hline Name & N. & Description\\ \hline |
+\hline EWRONG\_INT\_NO & 126 & Wrong int number passed to handler-set or handler\_remove.\\ |
+\hline EUSED\_INT\_NO & 127 & Already used int number.\\ |
+\hline EUNUSED\_INT\_NO & 128 & Int number not used.\\ |
+\hline ETOOMUCH\_INITFUNC & 129 & Too much init functions posted. (Currently not used)\\ |
+\hline ETOOMUCH\_EXITFUNC & 130 & Too much exit functions posted.\\ |
+\hline ENO\_AVAIL\_TASK & 131 & Task limit reached. Up to TSSMax-1 tasks can be created. See include/ll/i386/tss-ctx.h and include/kernel/const.h\\ |
+\hline ENO\_AVAIL\_SCHEDLEVEL & 132 & The Task Model passed with task\_create cannot be accepted by any scheduling module.\\ |
+\hline ETASK\_CREATE & 133 & Error during task\_create.\\ |
+\hline ENO\_AVAIL\_RESLEVEL & 134 & A Resource Model passed with task\_create cannot be accepted by any resource module.\\ |
+\hline ENO\_GUARANTEE & 135 & The new task cannot be accepted by the Scheduling Modules\\ |
+\hline ENO\_AVAIL\_STACK\_MEM & 136 & No space left to allocate the task stack.\\ |
+\hline ENO\_AVAIL\_TSS & 137 & No TSS free. This error should never happen.\\ |
+\hline EUNVALID\_KILL & 138 & The PID you tried to kill is not a task or has the NO\_KILL flag set.\\ |
+\hline EUNVALID\_TASK\_ID & 139 & The PID passed to task\_activate is not correct.\\ |
+\hline EUNVALID\_GROUP & 140 & Group 0 is not a valid group.\\ |
+\hline EPORT\_NO\_MORE\_DESCR & 141 & HARTPORT: No more port descriptors available.\\ |
+\hline EPORT\_NO\_MORE\_INTERF & 142 & HARTPORT: No more free port interfaces.\\ |
+\hline EPORT\_INCOMPAT\_MESSAGE & 143 & HARTPORT: Incompatible message (Write on a read port or viceversa)\\ |
+\hline EPORT\_ALREADY\_OPEN & 144 & HARTPORT: The port is already open.\\ |
+\hline EPORT\_NO\_MORE\_HASHENTRY & 145 & HARTPORT: No more Hash entries to create a port.\\ |
+\hline EPORT\_2\_CONNECT & 146 & HARTPORT: Error creating the port.\\ |
+\hline EPORT\_UNSUPPORTED\_ACC & 147 & HARTPORT: Error in port\_connect.\\ |
+\hline EPORT\_WRONG\_OP & 148 & HARTPORT: Wrong operation.\\ |
+\hline EPORT\_WRONG\_TYPE & 149 & HARTPORT: Operation not supported by the port type.\\ |
+\hline EPORT\_UNVALID\_DESCR & 150 & HARTPORT: Invalid port descriptor.\\ |
+\hline ECAB\_UNVALID\_ID & 151 & CABS: Invalid CAB ID.\\ |
+\hline ECAB\_CLOSED & 152 & CABS: CAB Closed.\\ |
+\hline ECAB\_UNVALID\_MSG\_NUM & 153 & CABS: Invalid Message number.\\ |
+\hline ECAB\_NO\_MORE\_ENTRY & 154 & CABS: No more entries.\\ |
+\hline ECAB\_TOO\_MUCH\_MSG & 155 & CABS: Too much messages.\\ |
+\hline |
+\end{longtable} |
/new_sharkdoc/vol1/errors.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/util.tex |
=================================================================== |
--- new_sharkdoc/vol1/util.tex (nonexistent) |
+++ new_sharkdoc/vol1/util.tex (revision 1676) |
@@ -0,0 +1,441 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{Utility functions} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. provides a set of utility functions aimed at getting information |
+about the kernel state. Mainly, they allow a user to get the actual |
+system time and some information concerning the tasks' state. Moreover, |
+it allows to set exception handlers and to manage interrupts. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Reading time} |
+%---------------------------------------------------------------------------- |
+ |
+The S.Ha.R.K. Kernel does not have the concept of tick. Every time |
+interval and every absolute time in the system is measured usin the |
+Real-Time Clock available on the PC. To read the current time you |
+can use the following function: |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_GETTIME\index{sys\_gettime()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{TIME sys\_gettime(struct timespec *t);}] |
+\item [Description:]It returns the number of microseconds elapsed from |
+system's initialization, that is from the end of the \texttt{\_\_kernel\_register\_levels\_\_} |
+function. If the \texttt{t} value is not equal \texttt{NULL}, the |
+function fills also the timespec structure passed as parameter. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Getting information on tasks} |
+%---------------------------------------------------------------------------- |
+ |
+Since all the tasks are handled by a Module, it is a responsibility of each |
+Module to hide or not hide informations about the tasks handled by the system. |
+However, at the moment S.Ha.R.K. provides a function that simply prints the |
+tasks state on the console \footnote{Old versions of the kernel supported a |
+\texttt{void sys\_status(DWORD cw);} \index{sys\_status()}primitive. That |
+primitive is currently unsupported.}. |
+ |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+PERROR\index{perror()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void perror (const char *s);}] |
+\item [Description:]This is the POSIX \texttt{perror()} funcion, that prints |
+on the console (using \texttt{kern\_printf}) a message that explain |
+the meaning of the \texttt{errno} \index{errno} variable. Note that |
+each task has its own \texttt{errno} variable, as specified by the |
+\texttt{POSIX} standard. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+exec\_shadow\index{exec\_shadow} |
+\end{intest} |
+\begin{description} |
+\item [\texttt{PID exec\_shadow;}] |
+\item [Description:]This is the internal variable used by the Kernel to |
+track the running task. You can read its value to know the PID of |
+the current task. You CAN NOT modify this variable. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Printing messages on the console} |
+%---------------------------------------------------------------------------- |
+ |
+To print a simple message on the console, please use the c* functions |
+(cprintf\index{cprintf}, cputs\index{cputs}, \ldots{}) described |
+in Volume II. If tou are debugging \emph{the kernel}, you can use |
+kern\_printf \index{kern\_printf} to print very simple messages without |
+floating point arithmetic. |
+ |
+%---------------------------------------------------------------------------- |
+\chapter{Signals and Exception Handling} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\section{Signals} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. implements the specification of the signals and of the real-time |
+signald provided by the standard IEEE 1003.13 POSIX PSE51/PSE52. In |
+particular, you can use all the functions described into the IEEE |
+1003.1\{a,b\} standards, except that: |
+ |
+\begin{itemize} |
+\item all the \texttt{pid\_t} parameters and in general all parameters related |
+with processes should be ignored; |
+\item when in POSIX a signal cause the termination of the process, it causes |
+in S.Ha.R.K. the termination of the whole system (you can think S.Ha.R.K. |
+as a single process multithread kernel); |
+\item The \texttt{siginfo\_t} structure contains an additional parameter |
+called \texttt{si\_task} of type \texttt{PID}. It contains the \texttt{PID} |
+of the task that queued a particular real-time signal. |
+\end{itemize} |
+ |
+In particular, you can use these functions for signal handling: \texttt{kill}, |
+\texttt{sigemptyset}, \texttt{sigfillset}, \texttt{sigaddset}, |
+\texttt{sigdelset}, \texttt{sigismember}, \texttt{sigaction}, |
+\texttt{pthread\_sigmask} \footnote{If you are not using the POSIX scheduling |
+modules please use \texttt{task\_sigmask}}, \texttt{sigprocmask}, |
+\texttt{sigpending}, \texttt{sigsuspend}, \texttt{sigwait}, |
+\texttt{sigwaitinfo}, \texttt{sigtimedwait}, \texttt{sigqueue}, |
+\texttt{pthread\_kill} \footnote{If you are not using the POSIX scheduling |
+modules please use \texttt{task\_signal} (Note that \texttt{task\_kill} does not |
+send any signal, but issue a cancellation request on a task!)}, \texttt{alarm}, |
+\texttt{pause}, \texttt{sleep} (note the difference between \texttt{sleep}, |
+\texttt{task\_sleep} and \texttt{nanosleep}!), \texttt{raise}, \texttt{signal}. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Exception handling\label{ch:except}} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. provides a flexible mechanism to handle the exceptions of the Kernel. |
+The mechanism is based on the POSIX signals. In fact, S.Ha.R.K. exceptions are |
+remapped on the real-time signal \texttt{SIGHEXC} \footnote{see |
+\texttt{include/signal.h}.} (9). Every time something goes wrong, the system |
+calls the primitive \texttt{kern\_raise}, that simply queue a real-time signal |
+of number SIGHEXC. |
+ |
+The user can define its own exception handler simply remapping the SIGHEXC |
+signal using the POSIX primitive \texttt{sigaction}. To fullfil the typical |
+usage of an exception handler (exit the system after printing a message), the |
+default behavior of the signal handler has been redefined to print a text |
+message on system shutdown. \footnote{Older versions of the Kernel supported two |
+functions to be used for standard redefinition of the kernel signal handler. |
+These functions, called SET\_EXCHANDLER\_TXT\index{set\_exchandler\_txt()} and |
+SET\_EXCHANDLER\_GRX\index{set\_exchandler\_grx()}, are no more supported, and |
+can be removed from your code without problems.} |
+ |
+Here is a sample code that explain how to redefine a signal handler: |
+ |
+\begin{verbatim} |
+#include <kernel/kern.h> |
+ |
+void thehandler(int signo, siginfo_t *info, void *extra) { |
+ |
+ /* the signal handler: |
+ info.sivalue.sival_int contains the exception number |
+ (see include/bits/errno.h) |
+ |
+ info.si_task is the task that raised the exception |
+ extra is not used |
+ */ |
+ ... |
+} |
+ |
+... |
+ |
+int myfunc(...) { |
+ struct sigaction action; |
+ ... |
+ |
+ action.sa_flags = SA_SIGINFO; |
+ action.sa_sigaction = thehandler; |
+ action.sa_handler = 0; |
+ sigfillset(&action.sa_mask); |
+ sigaction(SIGHEXC, &action, NULL); |
+ |
+ ... |
+} |
+\end{verbatim} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+KERN\_RAISE\index{kern\_raise()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void kern\_raise(int n, PID p);}] |
+\item [Description:]This function uses the POSIX function sigqueue to put |
+a signal SIGHEXC into the signal queue. The parameter n is used as |
+the exception number, and it is passed into the siginfo\_t parameter |
+(into the sivalue.sival\_int field). The signal appears to be queued |
+by the task p (the p value is stored into the si\_task field of the |
+siginfo\_t structure passed as parameter). |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\chapter{Interrupt and HW Ports handling} |
+\label{ch:interr} |
+%---------------------------------------------------------------------------- |
+ |
+Generally speaking, I/O to and from an external peripheral device |
+can be handled in three different ways depending on the peripheral |
+type and on the application: |
+ |
+\begin{itemize} |
+\item \textbf{Polling}: the program cyclically checks the status of the |
+I/O port, waiting for a input data to be ready or an output data to |
+be transmittable; |
+\item \textbf{Interrupt}: the program enables the I/O interface to send |
+a hardware interrupt every time an input data is available or an output |
+data is transmittable; |
+\item \textbf{DMA}: the program enables the interface to use DMA mechaninsm |
+for directly transferring data to/from memory. |
+\end{itemize} |
+\noindent In this chapter we will analyse the support that the S.Ha.R.K. |
+kernel provides for using the second method (interrupt). |
+ |
+When an interrupt arrives, a code for the hand-shake with the interface |
+and for transferring data has to be executed. This code can run in |
+two different modes: |
+ |
+\begin{itemize} |
+\item it can be entirely encapsulated in a function to be executed immediately |
+on the interrupt arrival, in the context of the executing task (\textit{fast |
+handler}); |
+\item it can be entirely encapsulated in a task (\textit{safe handler}) |
+which is activated on the interrupt arrival and scheduled with its |
+own priority together with the other tasks. |
+\end{itemize} |
+\noindent The first method is appropriate when the interrupt needs |
+a fast response time. Its potential drawback is that if its computation |
+time is not low, the overall schedulabuility can be severly affected. |
+This is because the guarantee algorithm does not take into account |
+the execution time of the interrupt handlers. The second method, on |
+the contrary, is perfectly integrated with the kernel's scheduling |
+mechanism, but can cause considerable delays in transferring data. |
+ |
+S.Ha.R.K. provides great flexibility in interrupt handling, since |
+it allows each interrupt to be associated with a \textit{fast handler}, |
+a \texttt{safe handler}, or both. |
+ |
+On an interrupt's arrival the following operations are performed by |
+the kernel: |
+ |
+\begin{itemize} |
+\item The system checks whether a fast handler is associated with the interrupt. |
+If so, the interrupts are enabled and the handler is invoked. This |
+method allows a handler to be interrupted by a higher priority handler. |
+As an example, the keyboard handler (interrupt 1) can be interrupted |
+be the timer handler (interrupt 0). |
+\item The system checks whether a sporadic task (\emph{safe handler}) is |
+associated with the interrupt. If so, the task is activated and is |
+eligible to run with enabled interrupts. |
+\end{itemize} |
+\noindent The system provides a set of functions for accessing the |
+hardaware interfaces' ports. In the drivers directory you can find |
+examples of a S.Ha.R.K. device driver. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Setting an interrupt handler} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+HANDLER\_SET\index{handler\_set()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int handler\_set(int no, void (*fast)(int), PID |
+pi, BYTE lock);}] |
+\item [Description:]It installs function \texttt{fast} (fast handler) and |
+the sporadic task \texttt{p} (safe handler) on the interrupt identified |
+by \texttt{no}. The \texttt{no} parameter must belong to the range |
+1\ldots{}15 (interrupt 0 is associated to the timer and cannot be |
+intercepted). On the interrupt's arrival, function \texttt{fast} is |
+invoked and runs. Depending on the \texttt{lock} flag, the interrupts |
+are disabled (\texttt{lock} = TRUE) or enabled (\texttt{lock} = FALSE) |
+during handler execution. Furthermore, on the interrupt's arrival, |
+task \texttt{p} is activated. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+HANDLER\_REMOVE\index{handler\_remove()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void handler\_remove(int no);}] |
+\item [Description:]It removes the handler of the interrupt number \texttt{intno}; |
+the interrupt is masked. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Reading and writing from I/O ports} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+INP, INPW, INPD \index{inp()} \index{inpw()} \index{inpd()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{unsigned char inp(unsigned short \_port);}] |
+\item [\texttt{unsigned short inpw (unsigned short \_port);}] |
+\item [\texttt{unsigned long inpd(unsigned short \_port);}] |
+\item [Description:]They return the data read on port \texttt{\_port}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+OUTP, OUTPW, OUTPD \index{outp()} \index{outpw()} \index{outpd()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void outp(unsigned short \_port, unsigned char \_data);}] |
+\item [\texttt{void outpw(unsigned short \_port, unsigned short \_data);}] |
+\item [\texttt{void outpd(unsigned short \_port, unsigned long \_data)}] |
+\item [Description:]It writes the data \texttt{\_data} into the port \texttt{\_port}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Disabling/Enabling interrupts} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+KERN\_CLI\index{kern\_cli()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void kern\_cli(void);}] |
+\item [Description:]It disables interrupts (as the x86 \texttt{cli} instruction). |
+\end{description} |
+%---------------------------------------------------------------------------- |
+ |
+\begin{intest} |
+KERN\_STI\index{kern\_sti()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void kern\_sti(void);}] |
+\item [Description:]It enables interrupts (as the x86 \texttt{sti} instruction). |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Saving/Restoring interrupts} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+KERN\_FSAVE\index{kern\_fsave()}\index{SYS\_FLAGS} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{SYS\_FLAGS kern\_fsave(void);}] |
+\item [Description:]It disables interrupts (as the x86 \texttt{cli} instruction). |
+The CPU flags are returned by the function; in that way they can be |
+restored using kern\_frestore |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+KERN\_FRESTORE\index{kern\_frestore()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void kern\_frestore(SYS\_FLAGS f);}] |
+\item [Description:]It restores the interrupt state as it was when the |
+correspondent \texttt{kern\_fsave} was called. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Masking/Unmasking PIC interrupts} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+IRQ\_MASK\index{irq\_mask()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void irq\_mask(WORD irqno);}] |
+\item [Description:]It mask the interrupt number \texttt{irqno} on the |
+PC PIC. \texttt{irqno} must be in the interval {[}1..15{]}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+IRQ\_UNMASK\index{irq\_unmask()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void irq\_unmask(WORD irqno);}] |
+\item [Description:]It unmask the interrupt number \texttt{irqno} on the |
+PC PIC. \texttt{irqno} must be in the interval {[}1..15{]}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\chapter{Memory Management Functions} |
+%---------------------------------------------------------------------------- |
+ |
+The S.Ha.R.K. Kernel provides the standard set of memory allocations |
+functions provided by the Standard C libraries. In particular, the |
+functions listed in figure \ref{fig:malloc} can be used. |
+ |
+\begin{figure} |
+\begin{center} \fbox{\tt{ \begin{minipage}{6cm} \begin{tabbing} |
+123\=123\=123\=\kill |
+\#include <stdlib.h>\\ |
+void *calloc(size\_t nmemb, size\_t size);\\ |
+void *malloc(size\_t size);\\ |
+void free(void *ptr);\\ |
+void *realloc(void *ptr, size\_t size);\\ |
+\end{tabbing} \end{minipage} }} \end{center} |
+\caption{\label{fig:malloc}Memory allocation functions.} |
+\end{figure} |
+In particular \footnote{These descriptions came directly from the Linux man pages...}: |
+ |
+\begin{itemize} |
+\item calloc() allocates memory for an array of nmemb elements of size bytes |
+each and returns a pointer to the allocated memory. The memory is |
+set to zero. The value returned is a pointer to the allocated memory, |
+which is suitably aligned for any kind of variable, or NULL if the |
+request fails. |
+\item malloc() allocates size bytes and returns a pointer to the allocated |
+memory. The memory is not cleared. The value returned is a pointer |
+to the allocated memory, which is suitably aligned for any kind of |
+variable, or NULL if the request fails. |
+\item free() frees the memory space pointed to by ptr, which must have been |
+returned by a previous call to malloc(), calloc() or realloc(). Otherwise, |
+or if free(ptr) has already been called before, undefined behaviour |
+occurs. If ptr is NULL, no operation is performed. |
+\item realloc() changes the size of the memory block pointed to by ptr to |
+size bytes. The contents will be unchanged to the minimum of the old |
+and new sizes; newly allocated memory will be uninitialized. If ptr |
+is NULL, the call is equivalent to malloc(size); if size is equal |
+to zero, the call is equivalent to free(ptr). Unless ptr is NULL, |
+it must have been returned by an earlier call to malloc(), calloc() |
+or realloc(). It returns a pointer to the newly allocated memory, |
+which is suitably aligned for any kind of variable and may be different |
+from ptr, or NULL if the request fails or if size was equal to 0. |
+If realloc() fails the original block is left untouched - it is not |
+freed or moved. |
+\end{itemize} |
+ |
+The S.Ha.R.K. Kernel also provides a set of low-level memory management |
+functions that can be used to allocate memory with particular requirements |
+(for example, they are useful for getting memory blocks aligned to |
+a page (4 Kb) boundary or with addresses under 1/16 Mb). Description |
+of these functions is given in Chapter 3 of the S.Ha.R.K. Architecture |
+Manual. |
/new_sharkdoc/vol1/util.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/makefile |
=================================================================== |
--- new_sharkdoc/vol1/makefile (nonexistent) |
+++ new_sharkdoc/vol1/makefile (revision 1676) |
@@ -0,0 +1,4 @@ |
+MAIN = vol1 |
+MAIN_NAME = vol1 |
+ |
+include ../common/manual.mk |
/new_sharkdoc/vol1/makefile |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/sys.tex |
=================================================================== |
--- new_sharkdoc/vol1/sys.tex (nonexistent) |
+++ new_sharkdoc/vol1/sys.tex (revision 1676) |
@@ -0,0 +1,1192 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{System Start-up and Termination} |
+%---------------------------------------------------------------------------- |
+ |
+Each S.Ha.R.K. application starts as a sequential C program, with |
+the classical main funcion. The multitasking environment \index{system initialization} |
+is already initialized when the application starts. From the main |
+task you can call any system primitive. |
+ |
+The system finishes when a sys\_end or sys\_abort function is called, |
+or when the last user task is terminated. For more information, see |
+\emph{The Generic Kernel Internals} chapter of the S.Ha.R.K. Kernel |
+Architecture Manual. |
+ |
+The \texttt{sys\_atrunlevel()} primitive\index{sys\_atexit()} allows |
+to post some handlers, which are automatically executed by the kernel |
+when it changes runlevel. Such functions can be issued either in the |
+target execution environment (generally MS-DOS) or just before terminating |
+the S.Ha.R.K. kernel, depending on the third argument of the primitive. |
+The handlers posted through \texttt{sys\_atrunlevel()} may also be |
+called on a kernel abort due to fatal errors. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Initialization File\label{sec:InitFile}} |
+%---------------------------------------------------------------------------- |
+ |
+When the system starts, one of the things to be done before going |
+in multitasking mode is to initialize the devices, the resources and |
+the schedulers which will be used by the application. To do that, |
+the Kernel calls the \_\_kernel\_register\_levels\_\_ function, that |
+usually registers the following modules (see the S.Ha.R.K. Kernel |
+architecture Manual for more details): |
+ |
+\begin{description} |
+\item [Scheduling~Modules]A scheduling module implements a particular |
+Scheduling Algorithm (for example EDF, RM, Round Robin, and so on). |
+\item [Resource~Modules]A resource module implements a shared resource |
+access protocol (for example the semaphores, the mutexes, and so on). |
+\item [Other~devices]Such for example the File System, and other devices |
+that need to be initialized when the Multitasking Mode is not started |
+yet. |
+\end{description} |
+ |
+The function returns a TICK value (in microseconds) that is the time |
+that will be used for programming the periodic timer interrupt of |
+the PC. If a value of 0 is returned, the one-shot timer is used instead |
+(see the OSLib documentation for more informations). Typical return |
+values range from 250 to 2000 microseconds. |
+ |
+Here is a typical initialization function: |
+ |
+\begin{verbatim} |
+TIME __kernel_register_levels__(void *arg) { |
+ struct multiboot_info *mb = (struct multiboot_info *)arg; |
+ LEVEL EDF_level; |
+ |
+ EDF_level = EDF_register_level(EDF_ENABLE_ALL); |
+ RR_register_level(RRTICK, RR_MAIN_YES, mb); |
+ CBS_register_level(CBS_ENABLE_ALL, EDF_level); |
+ dummy_register_level(); |
+ |
+ SEM_register_module(); |
+ CABS_register_module(); |
+ |
+ return 1000; |
+} |
+\end{verbatim} |
+ |
+As you can see, the system initialization function registers an EDF, |
+a Round Robin and a CBS module. Then, It register a dummy Module (that |
+usually is the last of the Scheduling Modules). For more informations |
+about the Scheduling policies, see Section \ref{sec:sched}. Finally, |
+Semaphores and CABS are registered, and a value of 1 ms Tick time |
+is returned to initialize the PC's real-time clock. |
+ |
+For a survey of the architecture of the Scheduling Modules and the |
+Resource Modules see theKernel Overview Chapter of the S.Ha.R.K. Kernel |
+Architecture Manual. A set of Initialization functions can be found |
+on the kernel/init directory of the S.Ha.R.K. source tree. An explanation |
+of each registration function for each Module can be found in the |
+S.Ha.R.K. Module Repository Manual. |
+ |
+After the registration of the modules in the system, the Kernel switch |
+in Multitasking mode, and starts the execution of the handlers that |
+the modules have posted with the \texttt{sys\_atrunlevel} primitive. |
+Usually at least one Module will create and activate a task (for example, |
+the Round Robin Scheduling Module does that) that will start when |
+all the handlers will be processed. The body of that task is usually |
+called \_\_init\_\_() and provides an initialization for the most |
+commonly used devices (such the keyboard, and so on) and modules. |
+As the last thing, the function simply call the main() function, that |
+is, the user application starts. A sample of a typical \_\_init\_\_() |
+function is showed below: |
+ |
+\begin{verbatim} |
+TASK __init__(void *arg) { |
+ struct multiboot_info *mb = (struct multiboot_info *)arg; |
+ |
+ HARTPORT_init(); |
+ __call_main__(mb); |
+ return (void *)0; |
+} |
+\end{verbatim} |
+ |
+The source code of the \_\_init\_\_() function is usually inserted |
+in the initialization file after the \_\_kernel\_register\_levels\_\_ |
+function. For more information on \_\_call\_main\_\_ see the \texttt{include/kernel/func.h} |
+include file. |
+ |
+Using the new driver layer the \_\_init()\_\_ function slightly change. |
+First is executed the HARTPORT\_init function that initialize the |
+Hartik Port layer (if required), then a task that close all drivers |
+is created. The next step is the initialization of all used drivers, |
+followed by the registration of the shutdown task that will be executed |
+during the system shutdown procedure. At the end the function 'main' |
+is executed. A tipical example with the new \_\_init()\_\_ function |
+is: |
+ |
+\begin{verbatim} |
+TASK __init__(void *arg) { |
+ struct multiboot_info *mb = (struct multiboot_info *)arg; |
+ |
+ HARTPORT_init(); |
+ |
+ /* Create the shutdown task. */ |
+ /* It will be activated at RUNLEVEL SHUTDOWN */ |
+ set_shutdown_task(); |
+ |
+ /* Init the drivers */ |
+ device_drivers_init(); |
+ |
+ /* Set the shutdown task activation */ |
+ sys_atrunlevel(call_shutdown_task, NULL, RUNLEVEL_SHUTDOWN); |
+ __call_main__(mb); |
+ |
+ return (void *)0; |
+} |
+ \end{verbatim} |
+ |
+ATTENTION! In some initialization files the function that activate |
+the shutdown task is in the form: |
+ |
+\begin{verbatim} |
+#define SHUTDOWN_TIMEOUT_SEC 3 |
+ |
+void call_shutdown_task(void *arg) { |
+ struct timespec t; |
+ |
+ sys_gettime(&t); |
+ t.tv_sec += SHUTDOWN_TIMEOUT_SEC; |
+ |
+ /* Emergency timeout to exit from RUNLEVEL_SHUTDOWN |
+ kern_event_post(&t,(void *)((void *)sys_abort_shutdown), (void *)0); |
+ |
+ task_activate(shutdown_task_PID); |
+} |
+\end{verbatim} |
+ |
+This implementation say that the task has 3 seconds to perform drivers |
+stop. After that interval the system is forced to close even is some |
+drivers are not closed. If a longer time is needed a greater value |
+for \texttt{SHUTDOWN\_TIMEOUT\_SEC} constant must be used. If a shutdown |
+without the timer is preferred the function could be in the simpler |
+form: |
+ |
+\begin{verbatim} |
+void call_shutdown_task(void *arg) { |
+ task_activate(shutdown_task_PID); |
+} |
+\end{verbatim} |
+ |
+%---------------------------------------------------------------------------- |
+\subsection{Information about the dependencies among modules} |
+%---------------------------------------------------------------------------- |
+ |
+Some modules, drivers and ports need to use the semaphores managed |
+by specific resource sharing modules. In that case, the modules, drivers |
+and ports expect the semaphores to be initialized by the application |
+into the initialization file. Here there is a brief list of the modules |
+which require other module initialization \footnote{All those dependancies wish to be removed.}. |
+ |
+The HARTIK ports (module HARTPORT) use the semaphores, so you must |
+include and initialize the semaphores if your application or a module |
+used by your application uses the HARTIK ports. |
+ |
+The HARTIK ports are used by the following modules: |
+ |
+\begin{itemize} |
+\item ports/first |
+\item drivers/net |
+\item drivers/input |
+\item drivers/oldchar |
+\end{itemize} |
+The semaphores are also used by: |
+ |
+\begin{itemize} |
+\item ports/tftp |
+\item drivers/oldsnd. |
+\end{itemize} |
+ |
+%---------------------------------------------------------------------------- |
+\section{System primitives} |
+%---------------------------------------------------------------------------- |
+ |
+Here is a list of primitives whose use is related to the system initialization. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_ATRUNLEVEL\index{SYS\_ATRUNLEVEL} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int}]\texttt{sys\_atrunlevel(void (*func\_code)(void *),void |
+*parm, BYTE when);} |
+\item [Description:]The Generic Kernel supports the specification of the |
+functions to be called at system initialization and termination. These |
+functions can be registered through this system primitive; the parameters |
+for that function are: |
+\item [\texttt{f}]the function to be registered; |
+\item [\texttt{p}]the parameter to be passed to function \texttt{f} when |
+the function will be called; |
+\item [\texttt{when}]is the situation in witch that function will be called. |
+The correct values are the following: |
+ |
+\begin{description} |
+\item [\texttt{RUNLEVEL\_INIT}]Used when programming Modules; |
+\item [\texttt{RUNLEVEL\_SHUTDOWN}]The function will be called after a |
+call to \texttt{sys\_abort} or \texttt{sys\_end}; The system is still |
+in multitasking mode; |
+\item [\texttt{RUNLEVEL\_BEFORE\_EXIT}]The function will be called when |
+the Kernel exits from multitasking mode; |
+\item [\texttt{RUNLEVEL\_AFTER\_EXIT}]The function is called before the |
+system hangs (or returns to the host OS, if the proprietary extender |
+is used). |
+ |
+\end{description} |
+ |
+It is also possible to specify with an OR operator a flag \texttt{NO\_AT\_ABORT} |
+that disables the call to the functions if the system is exiting with |
+a \texttt{sys\_abort} function. |
+ |
+\end{description} |
+ |
+You can post at most \texttt{MAX\_RUNLEVEL\_FUNC} functions. See the |
+S.Ha.R.K. Kernel Architecture Manual for more details. |
+ |
+\begin{description} |
+\item [See]\textbf{also}: \texttt{sys\_init()}, \texttt{sys\_end()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+EXIT\index{exit} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void exit(int status);}] |
+\item [Description:]This function call terminates the Kernel. In this phase, |
+the Kernel tries to correctly close all the initialized modules and |
+drivers. The functions eventually posted with the \texttt{sys\_at\_runlevel} |
+call are also executed. |
+ |
+If called inside an event or inside an ISR, it does return to the |
+caller. The system shutdown will start when all the current interrupts |
+have been serviced, and the system has been rescheduled. Otherwise, |
+this function follows the POSIX specification. |
+\item [See]\textbf{also}: \texttt{\_exit()}, \texttt{sys\_panic()}, \texttt{sys\_atrunlevel()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+\_EXIT\index{\_exit} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void \_exit(int status);}] |
+\item [Description:]Same as \texttt{exit()}. functions posted through \texttt{sys\_at\_runlevel} |
+with \texttt{NO\_AT\_ABORT} set or functions posted with \texttt{atexit()} |
+are not executed. |
+\item [See]\textbf{also}: \texttt{exit()}, \texttt{atexit()}, \texttt{sys\_panic()}, |
+\texttt{sys\_atrunlevel()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_PANIC\index{sys\_end} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void sys\_panic(const char * fmt, ...);}] |
+\item [Description:]This function call print a message then call sys\_abort(333). |
+\item [See]\textbf{also}: \texttt{sys\_abort()}, \texttt{sys\_end()}, \texttt{sys\_atrunlevel()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_SHUTDOWN\_MESSAGE\index{sys\_\_shutdown\_message} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int sys\_shutdown\_message(char *fmt,...);}] |
+\item [Description:]This function call saves a message in a reserved area, |
+that will be printed at system shutdown. It does not end the system. |
+\item [See]\textbf{also}: \texttt{sys\_panic()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_ABORT\_SHUTDOWN\index{sys\_abort\_shutdown} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int sys\_abort\_shutdown(int err);}] |
+\item [Description:]This function will force the system to end the \texttt{SHUTDOWN} |
+runlevel if there are system tasks which cannot be stopped. If called |
+when the system is still in the \texttt{RUNLEVEL\_RUNNING} runlevel, |
+the function behaves like \texttt{exit()}. If called inside an OSLib |
+event or inside an IRQ,it does return to the caller. The system shutdown |
+will start when all the current interrupts have been serviced, and |
+the system has been rescheduled. Otherwise, this function does not |
+return. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+SYS\_SET\_REBOOT\index{sys\_set\_reboot} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int sys\_set\_reboot(int mode);}] |
+\item [Description:]This function sets the reboot \texttt{mode}, which |
+specifies what will happen after the system end. \texttt{mode} options |
+are: |
+\item [EXIT\_MODE\_HALT:]the system will call the halt (\texttt{HLT}) instruction. |
+\item [EXIT\_MODE\_COLD:]the system will perform the cold reboot (slow |
+reboot). |
+\item [EXIT\_MODE\_WARM:]the system will perform the warm reboot (fast |
+reboot). |
+\item [EXIT\_MODE\_REAL:]the system will return to the real mode (\textbf{default |
+selection}). |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\chapter{Task Management} |
+%---------------------------------------------------------------------------- |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task Model} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. tasks are defined using standard C functions which return |
+a \texttt{void *} type \footnote{for readability, that type has been called TASK.} and can have one void * argument, which is passed when the task |
+is created. A task is identified by a system-wide unique process identifier |
+(\texttt{PID}) and a consecutive number \footnote{a task with PID p has a consecutive number that is proc\_table{[}p{]}.task\_ID.}. |
+ |
+A task has tipically a set of Quality of Service requirements that |
+need to be fullfilled by the Kernel. The kernel uses its registered |
+Scheduling Modules to meet the QoS required by a specified task. The |
+QoS reuired is specified at creation time through a Task Model, that |
+is passed to the task creation primitives. |
+ |
+A Task, can be \textit{Periodic} or \textit{Aperiodic}. Periodic tasks |
+are automatically activated by the kernel with a desired period, whereas |
+aperiodic tasks can either be activated by an explicit system call |
+or upon the occurrence of a desired event. |
+ |
+The typical task code consists of an optional initialization of local |
+variables and resources, followed by a (finite or infinite) loop, |
+representing the task's body. The last instruction of such a loop |
+must be the primitive \texttt{task\_endcycle()}\index{task\_endcycle()} |
+or the primitive \texttt{task\_sleep()} \index{task\_sleep()} which |
+signals the end of a generic job. |
+ |
+The task can access a local and a global context by following the |
+C scoping rules; the local context is defined by the local variables |
+and the single optional input argument. The following example shows |
+a typical task code fragment: |
+ |
+\begin{verbatim} |
+void *my_task(void *par) { |
+ |
+ /* Local Context*/ |
+ int a, b, c; |
+ |
+ /* Initialization */ |
+ b = c = (int)par + 1; |
+ a = (int)par / 2; |
+ ... |
+ |
+ while (1) { |
+ |
+ /* Body here!*/ |
+ ... |
+ |
+ task_endcycle(); |
+ } |
+} |
+\end{verbatim} |
+ |
+\noindent \texttt{my\_task()} has just one integer input argument |
+(passed through the void * parameter) and three local variables\index{local task context}. |
+The life-cycle of the local variables is the same as the task one, |
+since they are allocated on the task's stack. Obviously they retain |
+their values between two consecutive jobs. |
+ |
+\noindent One of the most important parameters for a real-time task |
+$\tau_{i}$ is the \emph{deadline}, defined as the maximum time allowed |
+for a task job to terminate. More precisely, we distinguish between |
+the \emph{absolute deadline} (denoted by $d_{i}$) specified with |
+respect to time 0, and the \emph{Relative Deadline} (denoted by $D_{i}$) |
+specified with respect to the activation time $r_{i,k}$ of the $k$-th |
+job of task $\tau_{i}$. We have that: |
+\[ |
+d_{i}=r_{i,k}+D_{i}. |
+\] |
+ |
+\noindent Tasks can also have different level of criticality, for |
+example: |
+ |
+\begin{itemize} |
+\item \texttt{HARD}\index{HARD} tasks are the most critical in the system. |
+For this reason, they are subjected to a guarantee algorithm at creation |
+time. The system enforces a strict compliance to the deadline constraint |
+for this kind of tasks% |
+\footnote{The guarantee algorithm tries to verify that both the newly activated |
+hard task and the previously existing ones will finish within their |
+deadlines% |
+}. If a hard deadline is missed, the system raises an exception which, |
+by default, results in the program termination. Recovery actions can |
+be programmed for this kind of exception (as shown below). |
+\item \texttt{SOFT}\index{SOFT} tasks can miss some deadline, and are scheduled |
+in order not to jeopardize HARD tasks' schedulability. This is done |
+through a service mechanism (see \ref{sec:sched}) which guarantees |
+each soft task a predefined bandwidth (i.e., a fraction of processor |
+utilization) while preserving the guarantee performed on hard tasks. |
+\item \texttt{NRT}\index{NRT} (Non Real-Time) tasks are scheduled in background |
+according to their relative fixed priority. Typically, they are used |
+for monitoring or debugging purposes. |
+\end{itemize} |
+The Task criticality, periodicity and the deadlines are coded into |
+the Task Model that is passed to the creation primitive. Each new |
+Scheduling Module can use its own Task Model to include the specific |
+task QoS requirements. |
+ |
+Each task can be in one of a set of states; the states that a task |
+can be in depend on each particular Module. For example, typical Task |
+states can be: |
+ |
+\begin{itemize} |
+\item \texttt{\textbf{EXE}}\index{EXE}: at any time, in the system there |
+is only one task in the EXE state, and it is the task actually executing. |
+\item \texttt{\textbf{READY}}\index{READY}: it includes all active tasks |
+ready to execute, except for the currently running task. |
+\item \texttt{\textbf{SLEEP}}\index{SLEEP}: it includes all aperiodic tasks |
+which terminated a job and are waiting for the next activation. Moreover, |
+each created task (periodic or aperiodic) that has not been activated |
+is put in the SLEEP state. |
+\item \texttt{\textbf{IDLE}}\index{IDLE}: is the state of those periodic |
+tasks which terminated a job and are waiting for the next activation. |
+\item \texttt{\textbf{BLOCKED}}\index{BLOCKED}: it includes all the tasks |
+blocked on a semaphore. |
+\end{itemize} |
+ |
+%---------------------------------------------------------------------------- |
+\section{The scheduling policy% |
+\footnote{This section is derived from the Kernel overview chapter of the S.Ha.R.K. |
+Architecture Manual.% |
+}\label{sec:sched} } |
+%---------------------------------------------------------------------------- |
+ |
+The S.Ha.R.K. scheduling architecture is based on a \emph{Generic |
+Kernel}, which does not implement any particular scheduling algorithm, |
+but postpones scheduling decisions to external entities, the \emph{scheduling |
+modules}. External modules can implement periodic scheduling algorithms, |
+soft task management through real-time servers, semaphore protocols, |
+and resource management policies. |
+ |
+The Generic Kernel provides the mechanisms used by the modules to |
+perform scheduling and resource management thus allowing the system |
+to abstract from the specific algorithms that can be implemented. |
+The Generic Kernel simply provides the primitives without specifying |
+any algorithm, whose implementation resides in external modules, configured |
+at run-time with the Initialization function. |
+ |
+Scheduling Modules are used by the Generic Kernel to schedule tasks, |
+or serve aperiodic requests using an aperiodic server. The Scheduling |
+Modules are organized into levels, one Module for each level. These |
+levels can be thought as priority scheduling levels (their priority |
+correspond to the order which they appear in the Initialization function). |
+When the Generic Kernel has to perform a scheduling decision, it asks |
+the modules for the task to schedule, according to fixed priorities: |
+first, it invokes a scheduling decision to the highest priority module, |
+then (if the module does not manage any task ready to run), it asks |
+the next high priority module, and so on. The Generic Kernel schedules |
+the first task of the highest priority non empty module's queue. |
+ |
+In this way, the Scheduling policy can be tuned simply modifying the |
+Initialization function. The standard distribution of the S.Ha.R.K. |
+Kernel includes a set of predefined Initialization functions that |
+can be used when developing a new application. For more informations |
+see the S.Ha.R.K. Module Manual, where each Scheduling Modules and |
+each predefined initialization functioon are described in detail. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task Creation\index{task creation}} |
+%---------------------------------------------------------------------------- |
+ |
+In order to run a S.Ha.R.K. task, three steps have to be performed: |
+parameters definition, creation, and activation. To improve the system |
+flexibility, each task can be characterized by a large number of parameters, |
+most of which are optional. For this reason, a set of structures derived |
+from \texttt{TASK\_MODEL}\index{MODEL} structure have been introduced |
+to simplify the parameters' definition phase. The first thing to do |
+in order to define a task is to declare a Model variable and initialize |
+it using the pmacro provided (see the S.Ha.R.K. Module Manual for |
+more informations). |
+ |
+\noindent Once the task's parameters have been set, the task can be |
+created using the \texttt{task\_create} or the \texttt{task\_createn} |
+system call. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_CREATEN\index{task\_createn()} and TASK\_CREATE\index{task\_create()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{PID task\_createn(char *name, TASK (*body)(), |
+TASK\_MODEL *m, ...);}] |
+\item [\texttt{PID task\_create(char *name, TASK (*body)(), |
+TASK\_MODEL *m, RES\_MODEL *r);}] |
+\item [Description:]\texttt{task\_createn} creates a new task. \texttt{name} |
+is a pointer to a string representing the task name; \texttt{body()} |
+is a pointer to the task body (i.e. the name of the C function containing |
+the task code); \texttt{m} specifies the Model that contain the QoS |
+specification of the task (the value can not be equal to NULL). Then, |
+follow a list of Resource Models terminated with NULL (see the S.Ha.R.K. |
+Module Manual for the available Task Models and Resource Models). |
+\texttt{task\_create} is a redefinition of \texttt{task\_createn} |
+that can be used when there is at least one Resource Model to be passed |
+to the creation primitive. |
+\item [Return]\textbf{value}: The function returns the identifier of the |
+newly created task, or -1 if the task creation fails (in this case |
+the \texttt{errno()} system call can be used to determine the error's |
+cause). |
+\item [See]\textbf{also}: \texttt{task\_activate()}, \texttt{task\_kill()}. |
+\item [Example]~ |
+\end{description} |
+ |
+\begin{verbatim} |
+int main(int argc, char **argv) { |
+ HARD_TASK_MODEL m; |
+ hard_task_default_model(m); |
+ hard_task_def_wcet(m,ASTER_WCET); |
+ hard_task_def_mit(m,10000); |
+ hard_task_def_group(m,1); |
+ hard_task_def_ctrl_jet(m); |
+ |
+ p1 = task_create("Aster", aster, &m, NULL); |
+ if (p1 == -1) { |
+ perror("Error: Could not create task <aster> ..."); |
+ exit(1); |
+ } |
+} |
+\end{verbatim} |
+ |
+ |
+%---------------------------------------------------------------------------- |
+\section{Group Creation} |
+%---------------------------------------------------------------------------- |
+ |
+Group creation is a feature provided by S.Ha.R.K. that allows a user |
+to create a set of tasks. The group creation differs from the creation |
+made by the task\_create and task\_createn primitives because in group |
+creation the acceptance test is done for the whole set of task (and |
+not for every task in sequence) only when every task which belong |
+to the set has been initialized in the system. After the acceptance |
+test, the user have to inquire the Scheduling Module to see the tasks |
+that have been accepted and successfully created in the system. |
+ |
+The primitives provided by S.Ha.R.K. to support group creation are: |
+ |
+\begin{itemize} |
+\item group\_create |
+\item group\_create\_accept |
+\item group\_create\_reject |
+\end{itemize} |
+The documentation about group creation can be found in the \emph{Group |
+creation HOWTO} available on the S.Ha.R.K. website. |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task Activation and Termination} |
+%---------------------------------------------------------------------------- |
+ |
+When a task is created, it is put in the \texttt{SLEEP} state, where |
+it is kept until activation, which can be triggered by an external |
+interrupt or by an explicit \texttt{task\_activate()} primitive). |
+Periodic jobs that complete execution are handled by the registered |
+Scheduling Modules (usually they are put in an \texttt{IDLE} state |
+or similar), from which they will be automatically re-activated by |
+the system timer. Aperiodic jobs that complete execution return to |
+the \texttt{SLEEP} state, where they wait for an explicit re-activation. |
+ |
+Some scheduling models (such as the EDF and RM modules) support release |
+offsets. In an offset is given in the task model, the \texttt{task\_activate()} |
+will put the task in the \texttt{IDLE} state, waiting for the first |
+release to occur. |
+ |
+A task can be destroyed using the \texttt{task\_kill()} system call, |
+that frees its descriptor. A task can kill itself using the \texttt{task\_abort()} |
+system call. |
+ |
+In S.Ha.R.K., tasks can be members of groups to allow simultaneous |
+activation or termination. A task can be put in a group through a |
+macro that works on the task model passed at task creation. The name |
+of the macro depends on the name of the Task Model used; usually its |
+name is like \texttt{XXX\_task\_def\_group(group\_number)}, where |
+XXX is the name of the task Model; the group\_number 0 indicates that |
+a task belongs to no groups. |
+ |
+Task cancellation, join, the cleanup handlers and the task specific |
+data works as the POSIX standard; only the name of the primitives |
+are changed from \texttt{pthread\_XXX} to \texttt{task\_XXX}. In any |
+case, the \texttt{pthread\_XXX} versions are available for POSIX compatibility. |
+ |
+\textbf{Warning}: \texttt{task\_kill()} kills a task only if the cancellation |
+type of the task is set to asynchronous. If the cancellation type |
+is set to deferred, the task will terminate only when it reach a cancellation |
+point. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_ACTIVATE\index{task\_activate()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_activate(PID p);}] |
+\item [Description:]It activates task \texttt{p}. Usually the activation |
+will insert the task into the ready queue. (If the task has an offset, |
+the task will be put in the ready queue after the offset.) Returns |
+0 in case of success or -1 in case of error; the \texttt{errno} variable |
+is set to \texttt{EUNVALID\_TASK\_ID}. |
+\item [See]\textbf{also}: \texttt{task\_create(), task\_kill(), group\_activate()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_KILL\index{task\_kill()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_kill(PID p);}] |
+\item [Description:]It asks for a cancellation of the task p. It returns |
+-1 in case of error, 0 otherwise. If an error occurred, the errno |
+variable is set to \texttt{EINVALID\_KILL}. A task which has the NO\_KILL |
+flag set can not be killed. If the task has already been killed but |
+it is not died yet, the primitive does nothing. A task that has the |
+cancellation type set to asynchronous will die just when it will be |
+scheduled again by the system; instead, if the cancellation type is |
+set to deferred, the task will die only at the reaching of a cancellation |
+point. This function is the correspondent of the \texttt{pthread\_cancel()} |
+primitive. |
+\item [See]\textbf{also}: \texttt{task\_create(), task\_activate(), group\_kill()}. |
+\end{description} |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_ABORT\index{task\_abort()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_abort(void *returnvalue);}] |
+\item [Description:]It aborts the calling task, removing it from the system. |
+If the task is joinable, the return value will be stored by the kernel |
+and given to any task that calls a task\_join primitive on the died |
+task. |
+\item [See]\textbf{also}: \texttt{task\_create(), task\_activate(), task\_kill()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_BLOCK\_ACTIVATION\index{task\_block\_activation()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_block\_activation(PID p);}] |
+\item [Description:]It blocks all explicit activation of a task made with |
+\texttt{task\_activate} and \texttt{group\_activate}. The activations |
+made after this call are buffered (counted) in an internal counter. |
+It returns 0 in case of success or -1 in case of error. In the latter |
+case, \texttt{errno} is set to \texttt{EUNVALID\_TASK\_ID}. If the |
+activations were already blocked, it does nothing. |
+\item [See]\textbf{also}: \texttt{task\_unblock\_activation(), task\_activate()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_UNBLOCK\_ACTIVATION\index{task\_unblock\_activation()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_unblock\_activation(PID p);}] |
+\item [Description:]It unblocks the activations of a task after a call |
+to task\_block\_activation. After this call, the task can be explicitly |
+activated. It returns the number of buffered activations, or -1 if |
+an error occurred. If an error occurred, the errno variable is set |
+to EUNVALID\_TASK\_ID. If the activations were not blocked, it simply |
+returns 0. Note that the primitive simply returns the number of buffered |
+activations, \emph{without} activating the task. |
+\item [See]\textbf{also}: \texttt{task\_block\_activation(), task\_activate()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+GROUP\_ACTIVATE\index{group\_activate()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int group\_activate(WORD g);}] |
+\item [Description:]It activates all tasks belonging to group \texttt{g}. |
+Returns 0 in case of success or -1 in case of error; the \texttt{errno} |
+variable is set to \texttt{EUNVALID\_GROUP}. |
+\item [See]\textbf{also}: \texttt{task\_create(), task\_activate(), group\_kill()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+GROUP\_KILL\index{group\_kill()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void group\_kill(WORD g);}] |
+\item [Descrizione:]It kills all tasks belonging to group \texttt{g}. It |
+returns -1 in case of error, 0 otherwise. If an error occurred, the |
+errno variable is set to \texttt{EUNVALID\_GROUP}. The kill request |
+to a single task that belong to a group is done in a way similar to |
+that done in the primitive \texttt{task\_kill()}. |
+\item [See]\textbf{also}: \texttt{task\_create(), task\_activate(), group\_activate()}, |
+\texttt{task\_kill()}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task Instances} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. supports the concept of instance for its task. A typical |
+task function is composed by an initialization part and a body part |
+that does the work for that the task was created; for example: |
+ |
+\begin{verbatim} |
+void *mytask(void *arg) { |
+ /* initialization part */ |
+ |
+ for (;;) { |
+ /* body */ |
+ ... |
+ |
+ task_endcycle(); |
+ } |
+} |
+\end{verbatim} |
+ |
+In the example, the task will never terminate, and it also calls the |
+\texttt{task\_endcycle} primitive to say to the Kernel that the current instance |
+is terminated \footnote{The concept of instance is introduced into S.Ha.R.K. |
+because in that way the Kernel can directly support task Quality Of Service |
+parameters like deadlines, periods and so on in a native way. Note that the |
+concept of instance is not covered by the POSIX standard, that only support a |
+fixed priority scheduler. In POSIX, a periodic task can only be implemented |
+using the Real-Time extensions and in particular using the Timer feature. |
+S.Ha.R.K. implements also that approach, however the native primitives are |
+better in terms of efficiency.}. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_ENDCYCLE\index{task\_endcycle()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_endcycle(void);}] |
+\item [Description:]It terminates the currently executing job of the calling |
+task. The behaviour of this primitive may sligtly change depending |
+on the Scheduling Module registered at initialization time. Tipically, |
+the \texttt{task\_endcycle} primitive suspends the task until an automatic |
+reactivation that is made internally by the Kernel. Moreover, the |
+\texttt{task\_endcycle()} primitive usually keeps track of pending |
+activations \footnote{There is a pending activation when a task is activated before the |
+current instance has finished. In this case, if the \texttt{task\_endcycle()} |
+primitive is called and there is a pending activation, it simply does |
+nothing.}. Previous versions of the kernel supported a \texttt{task\_sleep()}\index{task\_sleep()} |
+primitive with similar behavior. That function is currently unsupported. |
+The primitive is a cancellation point. |
+\item [Implementation:]This primitive is implemented as task\_message(NULL, 1); |
+\footnote{Note on the implementation: this primitive is implemented as |
+\texttt{task\_message(NULL, 1);}} |
+\item [See]\textbf{also:} \texttt{task\_activate}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task (thread) specific data} |
+%---------------------------------------------------------------------------- |
+ |
+These functions works in a way equal to their POSIX counterparts. |
+These primitives are used for managing task specific data, that are |
+a few data variables that can be referred in a common way independently |
+from the task that asks for it. The system also ensures a proper cleanup |
+when the task is killed. As an example, the \texttt{errno} variable |
+can be thought as a task specific data. In this manual only their |
+interfaces are described; for more informations, see the POSIX standard. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_KEY\_CREATE\index{task\_key\_create()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_key\_create(task\_key\_t *key, void |
+(*destructor)(void *));}] |
+\item [Description:]It creates a task key that can be used to refer a task\_specific |
+data. The name of the POSIX counterpart is \texttt{pthread\_key\_create}. |
+\end{description} |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_GETSPECIFIC\index{task\_getspecific()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void *task\_getspecific(task\_key\_t key);}] |
+\item [Description:]It gets the current value for the key (note that the |
+value of the key vary from task to task). The name of the POSIX counterpart |
+is \texttt{pthread\_getspecific}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_SETSPECIFIC\index{task\_setspecific()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_setspecific(task\_key\_t key, const void |
+*value); }] |
+\item [Description:]It sets the current value for the key. The name of |
+the POSIX counterpart is \texttt{pthread\_setspecific}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_KEY\_DELETE\index{task\_key\_delete()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_key\_delete(task\_key\_t key);}] |
+\item [Description:]It deletes the current key. The name of the POSIX counterpart |
+is \texttt{pthread\_key\_delete}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Task cancellation} |
+%---------------------------------------------------------------------------- |
+ |
+These primitives are used when managing task cancellation. They are |
+directly derived from the POSIX standard. Nothe that the POSIX interface |
+is also available. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_CLEANUP\_PUSH\index{task\_cleanup\_push()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_cleanup\_push(void (*routine)(void |
+*), void *arg);}] |
+\item [Description:]It pushes the specified cancellation cleanup handler |
+routine onto the cancellation cleanup stack. The name of the POSIX |
+counterpart is \texttt{pthread\_cleanup\_push}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_CLEANUP\_POP\index{task\_cleanup\_pop()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_cleanup\_pop(int execute);}] |
+\item [Description:]It removes the routine at the top of the cancellation |
+cleanup stack of the calling thread. If \texttt{execute} is not equal |
+0, the routine previously pushed is called. The name of the POSIX |
+counterpart is \texttt{pthread\_cleanup\_pop}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_TESTCANCEL\index{task\_testcancel()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_testcancel(void);}] |
+\item [Description:]creates a cancellation point in the calling task. The |
+primitive has no effect if cancelability is disabled. The name of |
+the POSIX counterpart is \texttt{pthread\_testcancel}. |
+\end{description} |
+ |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_SETCANCELSTATE\index{task\_setcancelstate()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_setcancelstate(int state, int *oldstate);}] |
+\item [Description:]This primitive sets the cancelability state of the |
+calling thread to the indicate \emph{state} \emph{and} returns the |
+previous cancelability state at the location referenced by \emph{oldstate}. |
+Legal values for state are \texttt{TASK\_CANCEL\_ENABLE} and \texttt{TASK\_CANCEL\_DISABLE}. |
+\texttt{pthread\_setcancelstate} is the name of the POSIX counterpart. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_SETCANCELTYPE\index{task\_setcanceltype()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [int task\_setcanceltype(int type, int *oldtype);] |
+\item [Description:]This primitive sets the cancelability type of the calling |
+thread to the indicate \emph{type} and returns the previous cancelability |
+type at the location referenced by \emph{oldtype}. Legal values for |
+state are \texttt{TASK\_CANCEL\_DEFERRED} and \texttt{TASK\_CANCEL\_ASINCHRONOUS}. |
+The name of the POSIX counterpart is \texttt{pthread\_setcanceltype}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Join} |
+%---------------------------------------------------------------------------- |
+ |
+The join primitives allow a task to wait for the termination of another task |
+\footnote{not of an instance of a task!}. The return value of the terminated |
+task is passed to the join primitive and the caller can use the value. These |
+primitives are directly derived from the POSIX standard. It means that a join |
+can be done only on a joinable task. But note that when a task created with the |
+creation primitives \footnote{\texttt{task\_create}, \texttt{task\_createn}, |
+\texttt{group\_create}} starts it is \emph{not} in the joinable state |
+\footnote{this is done to remain similar to the previous versions of the Hartik |
+Kernel...}. This behaviour differs from the standard behavior of the POSIX |
+standard, which specifies that every new task shall be in the joinable state. |
+However, S.Ha.R.K. provides also the \texttt{pthread\_create} primitive that is |
+\emph{fully compliant} with the standard. Finally, a S.Ha.R.K. task can switch |
+between the jonable and non-joinable state using the primitives |
+\texttt{task\_joinable} and \texttt{task\_unjoinable} \footnote{In the POSIX |
+standard, only the \texttt{pthread\_detach} primitive is available.}. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_JOIN\index{task\_join()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_join(PID p, void **value);}] |
+\item [Description:]The primitive suspends the execution of the calling |
+task until the task p terminates, unless the task p has already terminated. |
+On return from a successful \texttt{task\_join} call with a non-\texttt{NULL} |
+\emph{value} argument, the value returned by the thread through a |
+task\_abort shall be made available in the location referenced by |
+\emph{value}. When the primitive returns successfully the target task |
+has been terminated. The primitive returns 0 in case of success, otherwise |
+it returns \texttt{EINVAL} if the value \texttt{p} does not refer |
+to a task that can be joined, \texttt{ESRCH} if the value \texttt{p} |
+does not refer to a valid task, and \texttt{EDEADLK} if a deadlock |
+was detected. The name of the POSIX counterpart is \texttt{pthread\_join}. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_JOINABLE\index{task\_joinable()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_joinable(PID p);}] |
+\item [Description:]This function set the detach state of a task p to joinable. |
+This function is not present in Posix standard. It returns ESRCH if |
+p is non a valid task. |
+\end{description} |
+\pagebreak |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_UNJOINABLE\index{task\_unjoinable()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{int task\_unjoinable(PID p);}] |
+\item [Description:]This function sets the detach state of a task to detached. |
+The name of the POSIX counterpart is \texttt{pthread\_detach}. The |
+function returns \texttt{EINVAL} if \texttt{p} can not be joined (or |
+currently a task has done a join on it), or \texttt{ESRCH} if \texttt{p} |
+is not correct. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Preemption control} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. provides two primitives that set the preemptability of a |
+task. A non-preemptive task can not be preempted by another task; |
+interrupts are handled in the usual way. These primitives can be used |
+to implement short critical sections. Note the difference between |
+this kind of non -preemption and the interrupt disabling done using |
+kern\_cli and kern\_sti: in the latter case, interrupt can not preempt |
+the critical sections. A new task usually starts in a preemptive state. |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_NOPREEMPT\index{task\_nopreempt()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [void task\_nopreempt(void);] |
+\item [Description:]After the call of this primitive, the task is non-preemptive. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_PREEMPT\index{task\_preempt()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [void task\_nopreempt(void);] |
+\item [Description:]After the call of this primitive, the task become again |
+preemptive. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Suspending a task} |
+%---------------------------------------------------------------------------- |
+ |
+The following system calls can be used by a task to suspend itself |
+for a known or unknown time. (Note: it is dangerous to use these system |
+calls in a hard real-time task.) |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+TASK\_DELAY\index{task\_delay()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\texttt{void task\_delay(DWORD t);}] |
+\item [Description:]It causes the calling task to be blocked for at least |
+\texttt{t} microseconds. Note that \texttt{t} is the \emph{minimum} |
+delay time. In facts, after \texttt{t} microseconds the task is inserted |
+in the ready queue and can be delayed by higher priority tasks. This |
+function was inherited from the previous versions of Hartik. Please, |
+use the POSIX counterpart \texttt{nanosleep} instead! |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Job ExecutionTime (JET) estimation} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. provides a set of primitives that allows to precisely estimate |
+the system load. These primitives can be used to tune the parameters |
+that are given at task creation, and to get statistics about the system |
+load. |
+ |
+The execution time estimation is done on a task basis. That is, S.Ha.R.K. |
+provides three primitives that allows the user to estimate the JET |
+of every task. For every task, it is possible to know the mean execution |
+time, the maximum execution time, the time consumed by the current |
+instance and the time consumed by the last \texttt{JET\_TABLE\_DIM} |
+instances. |
+ |
+The user have to explicitly enable the Kernel to record the JET informations |
+for a specific task. This is done at task creation time; usually a |
+macro that enable the JET is provided in the definition of every task |
+model (see the S.Ha.R.K. Module Manual). |
+ |
+Here is an example of the use of the JET functions: |
+ |
+\begin{verbatim} |
+/* The Goofy Task */ |
+void *goofy(void *arg) { |
+ int i; |
+ for (;;) { |
+ for (i = 0; i < 100; i++) |
+ kern_printf("Yuk!"); |
+ task_endcycle(); |
+ } |
+} |
+ |
+PID goofy_PID; |
+ |
+/* a NRT task that never finish */ |
+ |
+void *jetcontrol(void *arg) { |
+ TIME sum, max, curr, last[5]; |
+ int nact; |
+ |
+ for (;;) { |
+ if (jet_getstat(p, &sum, &max, &nact, &curr) == -1) |
+ continue; |
+ for (j = 0; j < 5; j++) last[j] = 0; |
+ jet_gettable(p, &last[0], 5); |
+ printf_xy(1, 20, WHITE,"goofy_PID=%d mean=%d max=%d nact=%d", |
+ goofy_PID, sum / (nact == 0 ? 1 : nact), max, nact); |
+ printf_xy(1, 21, WHITE, "L1=%d L2=%d L3=%d L4=%d L5=%d", |
+ last[0], last[1], last[2], last[3], last[4]); |
+ } |
+} |
+ |
+*int main(int argc, char **argv) { |
+ ... |
+ |
+ /* The task goofy is created, specifying that the Kernel |
+ should take care of the JET data */ |
+ |
+ HARD_TASK_MODEL m; |
+ |
+ hard_task_default_model(m); |
+ |
+ /* ... other hard_task_XXX macros */ |
+ hard_task_def_ctrl_jet(m); /* JET enabling */ |
+ goofy_PID = task_create("Goofy", goofy, &m, NULL); |
+ |
+ /* ... creation of the JET control task, and so on */ |
+} |
+\end{verbatim} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+JET\_GETSTAT\index{jet\_getstat()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [int jet\_getstat(PID p, TIME *sum, TIME *max, int *n, TIME |
+*curr);] |
+\item [Description:]This primitive returns some JET informations about |
+the task p. The informations retrieved are stored into the following |
+parameters: |
+ |
+\begin{description} |
+\item [\texttt{sum}]is the task total execution time since it was created |
+or since the last call to the \texttt{jet\_delstat} function; |
+\item [\texttt{max}]is the maximum time used by a task instance since it |
+was created or since the last call to the \texttt{jet\_delstat} function; |
+\item [\texttt{n}]is the number of terminated instances which sum and max |
+refers to; |
+\item [\texttt{curr}]is the total execution time of the current instance. |
+\end{description} |
+ |
+If a parameter is passed as \texttt{NULL} the information is not returned. |
+The function returns 0 if the \texttt{PID} passed is correct, \texttt{-1} |
+if the PID passed does not correspond to a valid PID or the task does |
+not have the \texttt{JET\_ENABLE} bit set. |
+ |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+JET\_DELSTAT\index{jet\_delstat()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [int jet\_delstat(PID p);] |
+\item [Description:]The primitive voids the actual task execution time |
+data mantained by the Generic Kernel. The function returns 0 if the |
+PID passed is correct, \texttt{-1} if the PID passed does not correspond |
+to a valid PID or the task does not have the \texttt{JET\_ENABLE} |
+bit set. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\begin{intest} |
+JET\_GETTABLE\index{jet\_gettable()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [int jet\_gettable(PID p, TIME *table, int n);] |
+\item [Description:]The primitive returns the last \texttt{n} execution |
+times of the task \texttt{p}. If the parameter n is less than 0, it |
+returns only the last values stored since the last call to \texttt{jet\_gettable} |
+(up to a maximum of \texttt{JET\_TABLE\_DIM} values). If the value |
+is greater than 0, the function returns the last \texttt{min(n,~JET\_TABLE\_DIM)} |
+values registered. The return value is \texttt{-1} if the task passed |
+as parameter does not exist or the task does not have the \texttt{JET\_ENABLE} |
+bit set, otherwise the number of values stored into the array is returned. |
+The table passed as parameter should store at least \texttt{JET\_TABLE\_DIM} |
+elements. |
+\end{description} |
+ |
/new_sharkdoc/vol1/sys.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol1/introd.tex |
=================================================================== |
--- new_sharkdoc/vol1/introd.tex (nonexistent) |
+++ new_sharkdoc/vol1/introd.tex (revision 1676) |
@@ -0,0 +1,361 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{Introduction} |
+%---------------------------------------------------------------------------- |
+ |
+Real-time computing is required in many application domains, ranging |
+from embedded process control to multimedia systems. Each application |
+has peculiar characteristics in terms of timing constraints and computational |
+requirements (such as periodicity, criticality of the deadlines, tolerance |
+to jitter, and so on). For this reason, a lot of different scheduling |
+algorithms and resource allocation protocols have been proposed to |
+conform to such different application demands, from the classical |
+fixed or dynamic priority allocation schemes to adaptive or feedback-based |
+systems. |
+ |
+However, most of the new approaches have been only theoretically analyzed, |
+and sometimes evaluated using a scheduling simulator. In this case, |
+the algorithm performance is not evaluated on real examples, but only |
+on a synthetic workload. This choice is often dictated from the fact |
+that writing a kernel from scratch every time a new scheduling algorithm |
+is proposed would be unrealistic and would not offer the availability |
+of meaningful applications. A more effective approach is to modify |
+an existing kernel (such as Linux), since most of the existing applications |
+and device drivers written for the host OS can be used in a straightforward |
+fashion. On the other hand, a general purpose kernel is designed aiming |
+at specific goals and generally its architecture is not modular enough |
+for replacing or modifying the scheduling policy. Moreover, classical |
+OSs do not allow to easily define a scheduling policy for resources |
+other than the CPU and this poses a further limitation for testing |
+novel research solutions. This is mainly due to the fact that the |
+classical OS structure does not permit a precise \emph{device scheduling} |
+(due to problems involving resource contention, priority inversion, |
+interrupt accounting, long non-preemptive sections, and so on). A |
+small kernel providing short non-preemptable sections, aperiodic real-time |
+threads for handling interrupts, and a distinction between \emph{device |
+drivers} accessing the hardware and \emph{device managers} implementing |
+the \emph{device scheduling} algorithms would help the progress in |
+this research field. The problems explained above emerge both in the |
+educational and research environments, when the focus is oriented |
+in developing and testing new scheduling algorithms rather than hacking |
+the code of a complex system. |
+ |
+S.Ha.R.K. (Soft and Hard Real-time Kernel), is a research kernel purposely |
+designed to help the implementation and testing of new scheduling |
+algorithms, both for the CPU and for other resources. The kernel can |
+be used to perform early validation of the scheduling algorithms produced |
+in the research labs, and to show the application of real-time scheduling |
+in real-time systems courses. These goals are fulfilled by making |
+a trade off between simplicity and flexibility of the programming |
+interface on one hand and efficiency on the other. This approach allows |
+a developer to focus his/her attention on the real algorithmic issues, |
+thus saving significant time in the implementation of new solutions. |
+Another important design guideline is the use of standard naming conventions |
+for the support libraries in order to ease the porting of meaningful |
+applications written for other platforms. The results have been satisfactory |
+for applications such as an MPEG player, a set of network drivers |
+and a FFT library. |
+ |
+The kernel provides the basic mechanisms for queue management and |
+dispatching and uses one or more external configurable modules to |
+perform scheduling decisions. These external modules can implement |
+periodic scheduling algorithms, soft task management through real-time |
+servers, semaphore protocols, and resource management policies. The |
+modules implementing the most common algorithms (such as RM, EDF, |
+Round Robin, and so on) are already provided, and it is easy to develop |
+new modules. Each new module can be created as a set of functions |
+that \emph{abstract} from the implementation of the other scheduling |
+modules and from the resource handling functions. Also the applications |
+can be developed independently from a particular system configuration, |
+so that new modules can be added or replaced to evaluate the effects |
+of specific scheduling policies in terms of predictability, overhead, |
+and performance. Low-level drivers for the most typical hardware resources |
+(like network cards, graphic cards, and hard disks) are also provided, |
+without imposing any form of device scheduling. In this way, device |
+scheduling can be implemented by the user to test new solutions. To |
+avoid the implementation of a new non-standard programming interface, |
+which would discourage people from using the kernel, S.Ha.R.K. implements |
+the standard POSIX 1003.13 PSE52 interface |
+% |
+% Tool: no such reference! |
+% |
+% \cite{POSIX1003.1,POSIX1003.13} |
+. |
+ |
+This manual was derived from the Hartik User Manual release 3.3.1. |
+ |
+%---------------------------------------------------------------------------- |
+\section{General Description} |
+%---------------------------------------------------------------------------- |
+ |
+S.Ha.R.K. has been designed as a library of functions which extends |
+the classical C library, by providing a multiprogramming environment |
+with an explicit management of time. From a logical point of view, |
+the system is based on a \emph{Host} computer where the application |
+is developed and on a \emph{Target} computer where the application |
+executes. Development tools are located on the host system, where |
+a general purpose operating system is used. After its compilation, |
+the application is loaded on the target system using the appropriate |
+\emph{loader}. This separation, typical of many hard real-time development |
+systems, enables the final application to run on a variety of target |
+systems, ranging from typical PC to embedded micro-controllers. From |
+a practical point of view, host and target may be the same computer |
+and in the rest of this manual we will not further distinguish between |
+them. |
+ |
+S.Ha.R.K. has been developed focusing on modularity of the kernel |
+source code. S.Ha.R.K. is fundamentally a set of routines that runs |
+on top of a library for OS development called OSLib (see http://oslib.sourceforge.net) |
+that has these requirements: |
+ |
+\begin{description} |
+ |
+\item [Operating~System~(OS)]You can compile OSLib/S.Ha.R.K. programs |
+using some different host OS. In theory, any OS supporting gcc can |
+be used; in practice, we successfully compiled OSLib/S.Ha.R.K. from |
+Linux, DOS and Cygwin. |
+ |
+\item [Compiler]The used compiler is gcc. You can use the gcc version that |
+you prefer (we tested gcc 3.3.3 and older version), the important |
+thing is that the linker must produce ELF binaries (in order to be |
+MultiBoot compliant and to avoid problems with the Linux source code |
+inside S.Ha.R.K.). An ELF cross-compile version of gcc is included |
+inside the DJGPP distribution on the S.Ha.R.K. website, so you can |
+easily compile OSLib/S.Ha.R.K. programs inside a standard DOS environment. |
+To compile under Cygwin, it is required to build an ELF cross-compile |
+gcc/linker couple. |
+ |
+\item [Other~utilities]GNU Make \index{Make}, uname, pwd, cp, rm, X (these |
+utilities can be found in the utility package on the S.Ha.R.K. web |
+site). |
+ |
+\item [Target~Requirements]The target have to be at least a PC based on |
+Intel 80486 (or compatible) - SMP is not supported - with at least |
+4Mb of RAM. In order to load OSLib/S.Ha.R.K. programs (MultiBoot compliant), |
+the target must have GRUB installed, or it must run a real mode operating |
+system (such as MS-DOS or FreeDOS). If you intend to boot OSLib/S.Ha.R.K. |
+programs from DOS, you also have to download our DOS eXtender X. |
+ |
+\end{description} |
+ |
+Compilation and application linking can be done using the \emph{make}\index{make} |
+utility, available in any of the development environments mentioned |
+above. In this case, a {}``makefile''\index{makefile} containing |
+the names of all of the .C files composing the application and the |
+directives to link the needed libraries have to be written. For more |
+information, you can look at the installation txt file from the website |
+download page. |
+ |
+%---------------------------------------------------------------------------- |
+\section{SHARK.CFG} |
+%---------------------------------------------------------------------------- |
+ |
+Inside \texttt{shark.cfg} you can find the main parameters for S.Ha.R.K. |
+configuration. All the stettings inside this file will be crucial |
+to run correctly S.Ha.R.K. and to get the maximum performaces on a |
+x86 machines. The most important options related to the Real-Time |
+behaviour are: |
+ |
+\begin{description} |
+\item MEM\_START = [number] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Kernel image start point. The kernel image file will be loaded starting |
+from this physical memory address. Default value is 0x220000, but DOS users, |
+should set an high address (like 0x1720000) if Smartdrive or other tools which |
+require Extended Memory are used. |
+\end{itemize} |
+ |
+\begin{description} |
+\item TSC = [TRUE,FLASE] |
+\end{description} |
+ |
+\begin{itemize} |
+\item This option enables the Time Step Counter inside the CPU (Pentium |
+or higher). Kern\_gettime function will use the TSC register which |
+is faster and more precise than the external PIT. The default value |
+is TRUE. If the system cannot find the TSC, this feature will be disabled |
+and PIT will be used to get the system time. |
+\end{itemize} |
+ |
+\begin{description} |
+\item APIC = [TRUE,FALSE] |
+\end{description} |
+ |
+\begin{itemize} |
+\item This option enables the APIC (Pentium Pro or higher). As TSC, APIC |
+is faster and more precise than the standard PIT. It will be used |
+to generate the timer interrupts. The default value is TRUE. If the |
+system cannot find the APIC, the feature will be disabled. On some |
+embedded systems or old PC, the APIC check could hang the system, |
+so you must disable it manually. APIC requires the TSC. |
+\end{itemize} |
+ |
+\begin{description} |
+\item TIMER\_OPT = [1000,2000,4000,8000] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Enable TSC read timer optimization. The 4 values are suggested for |
+different CPU speeds, allowing different wraparound performance: TIMER\_OPT = |
+1000 for CPU < 1 GHz, wraparound of 585 years; TIMER\_OPT = 2000 for 1 GHz < |
+CPU < 2 GHz, wraparound of 146 years; TIMER\_OPT = 4000 for 2 GHz < CPU < 4 GHz, |
+wraparound of36 years; TIMER\_OPT = 8000 for CPU < 8 GHz, wraparound of 292 |
+years. |
+\end{itemize} |
+ |
+\begin{description} |
+\item TRACER = [NO,OLD,NEW] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Select the tracer to be used for tracing events. While TRACER = OLD is for |
+backward compatibility, TRACER = NEW should be the preferred option when event |
+tracing is required. The event tracer can be disabled by selecting TRACER = NO. |
+\end{itemize} |
+ |
+\begin{description} |
+\item BIOS = [X,VM86] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Select the BIOS interrupt access mode. BIOS = X means that you must use |
+x.exe as shark loader if shark needs to call BIOS interrupt (Ex. to enable |
+graphics); BIOS = VM86 means that shark call the BIOS interrupts as Virtual |
+Machine 86, and you can load a graphical demo also through GRUB. |
+\item Notice that VM86 MODE IS NOT COMPATIBLE WITH SOME VGA CARDS (like MATROX). |
+\end{itemize} |
+ |
+\begin{description} |
+\item FB = [VESA,FINDPCI,VGA16] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Select the FrameBuffer configuration. It can use the VBE interrupts to |
+enable the selected video mode (VESA), or enable the VGA16 (4 bit per plane) |
+video mode (VGA16). Using FINDPCI, the FrameBuffer driver will try to find a |
+PCI/AGP graphical card. If a card is found, FB will use a specific driver to |
+enable it; however, few graphic adapters are currently supported with specific |
+drivers. Since almost all adapters support the VESA standard, FB = VESA is |
+usually the best choice. |
+\end{itemize} |
+ |
+\begin{description} |
+\item FG = [NORMAL,FORCE\_PXC] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Select the FrameGrabber configuration. FORCE\_PXC forces the frame grabber to init a PXC200 card, and should be used carefully. |
+\end{itemize} |
+ |
+\begin{description} |
+\item SHARK\_FS = [YES,NO] |
+\end{description} |
+ |
+\begin{itemize} |
+\item Select the S.Ha.R.K. file system support. SHARK\_FS = YES makes the kernel |
+to include the File System library, which supports the FAT16 filesystem only. If |
+you don't have a FAT16 filesystem, set SHARK\_FS = NO. |
+\end{itemize} |
+ |
+\begin{description} |
+\item [{\Large NOTE:}]{\Large You must recompile S.Ha.R.K. if you modify} |
+\texttt{\Large shark.cfg}{\Large \par} |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{Predefined Types and Constants} |
+%---------------------------------------------------------------------------- |
+ |
+Tables~\ref{t:types}, \ref{t:task}, \ref{t:stati}, \ref{t:limits} |
+show a subset of the predefined data types in S.Ha.R.K., a subset |
+of the possible task states and Models and the system basic constants. |
+ |
+\begin{table} |
+\begin{center}\begin{tabular}{|l|l|} |
+\hline |
+\emph{Type} & \emph{Description} \\ |
+\hline |
+BYTE & unsigned char, {[}0, 255{]} \\ |
+WORD & unsigned int, {[}0, 65535{]} \\ |
+DWORD & unsigned long, {[}0, 0xFFFFFFFF{]} \\ |
+TIME & unsigned long, {[}0, 0xFFFFFFFF{]} \\ |
+PID & Task identifier \\ |
+TASK & task \\ |
+PORT & communication endpoints \\ |
+CAB & cyclic asynchronous buffers \\ |
+\hline |
+\end{tabular}\end{center} |
+\caption{\label{t:types}Predefined types.} |
+\end{table} |
+ |
+\begin{table} |
+\begin{center}\begin{tabular}{|l|c|} |
+\hline |
+\emph{Identifier} & \emph{Value}\\ |
+\hline |
+FREE & 0 \\ |
+EXE & 1 \\ |
+SLEEP & 2 \\ |
+WAIT\_JOIN & 3 \\ |
+WAIT\_COND & 4 \\ |
+WAIT\_SIG & 5 \\ |
+WAIT\_SEM & 6 \\ |
+WAIT\_NANOSLEEP & 7\\ |
+WAIT\_SIGSUSPEND & 8 \\ |
+WAIT\_MQSEND & 9\\ |
+WAIT\_MQRECEIVE & 10 \\ |
+\hline |
+\end{tabular}\end{center} |
+ |
+\caption{\label{t:stati}Task states. (Note that a scheduling module can add |
+its private task states.)} |
+\end{table} |
+ |
+\begin{table} |
+\begin{center}\begin{tabular}{|l|c|} |
+\hline |
+\emph{Identifier} & Class \\ |
+\hline |
+HARD\_TASK\_MODEL & Periodic and sporadic hard tasks \\ |
+SOFT\_TASK\_MODEL & Periodic and aperiodic soft tasks\\ |
+NRT\_TASK\_MODEL & Non-real-time tasks \\ |
+JOB\_TASK\_MODEL & A task instance (job) that can be inserted into another module \\ |
+DUMMY\_TASK\_MODEL & Model used for the Dummy Task \\ |
+ELASTIC\_TASK\_MODEL & Elastic task, used with the Elastic Module \\ |
+\hline |
+\end{tabular}\end{center} |
+ |
+\caption{\label{t:task}Basic Task Models included with the default distribution |
+(see include/kernel/model.h).} |
+\end{table} |
+ |
+\begin{table} |
+\begin{center}\begin{tabular}{|l|c|} |
+\hline |
+\emph{Identifier} & \emph{Value} \\ |
+\hline |
+MAX\_PROC & 66 \\ |
+MAX\_RUNLEVEL\_FUNC & 40 \\ |
+JET\_TABLE\_DIM & 20 \\ |
+MAX\_CANCPOINTS & 20 \\ |
+MAX\_SIGINTPOINTS & 20 \\ |
+MAX\_SCHED\_LEVEL & 16 \\ |
+MAX\_RES\_LEVEL & 8 \\ |
+MAX\_LEVELNAME & 20 \\ |
+MAX\_MODULENAME & 20 \\ |
+MAX\_TASKNAME & 20 \\ |
+NIL & -1 \\ |
+RUNLEVEL\_STARTUP & 0 \\ |
+RUNLEVEL\_INIT & 1 \\ |
+RUNLEVEL\_RUNNING & 3 \\ |
+RUNLEVEL\_SHUTDOWN & 2 \\ |
+RUNLEVEL\_BEFORE\_EXIT & 4 \\ |
+RUNLEVEL\_AFTER\_EXIT & 5 \\ |
+NO\_AT\_ABORT & 8 \\ |
+\hline |
+\end{tabular}\end{center} |
+ |
+\caption{\label{t:limits}System constants (see include/kernel/const.h).} |
+\end{table} |
+ |
/new_sharkdoc/vol1/introd.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol2/graph.tex |
=================================================================== |
--- new_sharkdoc/vol2/graph.tex (nonexistent) |
+++ new_sharkdoc/vol2/graph.tex (revision 1676) |
@@ -0,0 +1,241 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{The Frame Buffer Library} |
+%---------------------------------------------------------------------------- |
+ |
+The S.Ha.R.K. system provides support for all modern SVGA cards through the |
+Linux Frame Buffer driver. Using the \texttt{grx} graphic library upon it is |
+possible to draw points, lines, rectangles, boxes, circles, and text on 16 bit |
+per plane (bpp) SVGA graphic modes. |
+ |
+In order to use graphics, a program must include the |
+\texttt{drivers/shark\_fb26.h} header file. Then, it must initialize the Frame |
+Buffer using \texttt{FB26\_init()}. At this point the drawing library must be |
+connected to the frame buffer with the function \texttt{FB26\_use\_grx()}. Now a |
+graphic mode can be opened using \texttt{FB26\_setmode()}, and then the drawing |
+functions can be used. The \emph{num number}, needed as a parameter indicate |
+which frame buffer is used. At the end, the program can switch back to text mode |
+through \texttt{FB26\_close()}. |
+ |
+\vspace{7mm} |
+ |
+\begin{intest} |
+FB26\_INIT \index{FB26\_init()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int FB26\_init(void);}] |
+\item [\textbf{Description:}] It initializes the rame buffer and internal data structures |
+to access the hardware. The function returns -1 on error, 0 otherwise. In order |
+to use the graphic primitives, a program must call this function. |
+\end{description} |
+ |
+\begin{intest} |
+FB26\_OPEN\index{fb26\_open()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int FB26\_open(int num);}] |
+\item [\textbf{Description:}] Open the frame buffer number \texttt{num}. The function |
+returns -1 on error, 0 otherwise. The frame buffer must be already initialized |
+with \texttt{FB26\_init}. |
+\end{description} |
+ |
+\begin{intest} |
+FB26\_SETMODE\index{FB26\_setmode()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int grx\_setmode(int num, unsigned chat *mode);}] |
+\item [\textbf{Description:}] It opens the graphic mode identified by the \texttt{mode} |
+parameter. The mode number can be obtained using \texttt{grx\_getmode()}. The |
+parameter \texttt{mode} is a string in the format |
+``\texttt{widthxheight-bpp}'' (ex. ``\texttt{640x480-16}''). If the mode is |
+supported and can be opened, the function returns 1, otherwise it returns -1. |
+\end{description} |
+ |
+\begin{intest} |
+FB26\_CLOSE\index{FB26\_close()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int FB26\_close(int num);}] |
+\item [\textbf{Description:}] It closes the frame buffer \texttt{num} returning to text |
+mode. |
+\end{description} |
+ |
+%---------------------------------------------------------------------------- |
+\section{The Frame Buffer graphics functions} |
+%---------------------------------------------------------------------------- |
+ |
+The GRX library allows to use graphics with 16 bpp; the number of bits per |
+pixel, the graphic depth, determines the number of colors that can be |
+simultaneously displayed on a single screen. In 16 bpp modes, each pixel is |
+represented by two bytes. Since 16 is not divisible by 3, a component (the green |
+one) is described by 6 bits, whereas the other two are described by 5 bits. The |
+\texttt{RGB16()} macros help to code RGB values in a pixel value for all these |
+graph functions. |
+ |
+\vspace{7mm} |
+ |
+\begin{intest} |
+RGB16\index{rgb16()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{WORD rgb16(WORD r, WORD g, WORD b);}] |
+\item [\textbf{Description:}] It returns the color value defined by the 3 parameters |
+(\texttt{red}, \texttt{green} and \texttt{blue}) in the format required by |
+drawing function. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_CLEAR\index{grx\_clear()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_clear(DWORD color);}] |
+\item [\textbf{Description:}] It clears the graphic screen by filling it with the color |
+specified in the parameter \texttt{color}. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_PLOT\index{grx\_plot()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_plot(WORD x, WORD y, DWORD col);}] |
+\item [\textbf{Description:}] It draws a pixel of color \texttt{c} at coordinates |
+(\texttt{x},\texttt{y}) on the screen. For efficiency reasons no checks are |
+performed on \texttt{x} and \texttt{y}. Only the \texttt{bpp} less significative |
+bits of \texttt{col} are used (where \texttt{bpp} is the number of bits per |
+plane in the current graphic mode). |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_GETPIXEL\index{grx\_getpixel()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{DWORD grx\_getpixel(WORD x, WORD y);}] |
+\item [\textbf{Description:}] It returns the color of pixel at coordinates |
+(\texttt{x}, \texttt{y}) on the screen. For efficiency reasons no checks are |
+performed on \texttt{x} and \texttt{y}. Only the \texttt{bpp} less significative |
+bits of the returned value are used (where \texttt{bpp} is the number of bits |
+per plane in the current graphic mode). |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_PUTIMAGE\index{grx\_putimage()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_putimage(WORD x1, WORD y1, WORD x2, WORD y2, WORD *img);}] |
+\item [\textbf{Description:}] It writes a rectangular bitmap from system memory to video |
+memory. (\texttt{x1}, \texttt{y1}) is the top left corner, while |
+(\texttt{x2},\texttt{y2}) is the right bottom corner. It fills the specified box |
+with the data in the buffer pointed by \texttt{*img}. The memory buffer must |
+contain the pixels in the same representation used in the video memory, starting |
+at the top left corner, from left to right, and then, line by line, from up to |
+down, without any gaps and interline spaces. |
+\item [See also:] \texttt{grx\_getimage()}. |
+\end{description} |
+ |
+\begin{description} |
+\item [Example:] |
+\end{description} |
+ |
+ |
+\begin{tt} |
+\begin{verbatim} |
+BYTE videobuff[200][200]; |
+... |
+ |
+void *videotask(void *arg) { |
+ int done = 0; |
+ ... |
+ |
+ while (!done) { |
+ done = decodeframe(videobuff, 200, 200); |
+ grx_put(X, Y, X + 200, Y + 200, videobuff); |
+ task_endcycle(); |
+ } |
+} |
+\end{verbatim} |
+\end{tt} |
+ |
+\begin{intest} |
+GRX\_GETIMAGE\index{grx\_getimage()} |
+\end{intest} |
+\begin{description} |
+\item [\textbf{void grx\_getimage(WORD x1, WORD y1, WORD x2, WORD y2, WORD *img);}] |
+\item [\textbf{Description:}] It reads a rectangular bitmap from video memory to system |
+memory. (\texttt{x1}, \texttt{y1}) is the top left corner, while |
+(\texttt{x2},\texttt{y2}) is the right bottom corner. It fills the specified |
+buffer pointed by \texttt{*img} with the data contained in the selected video |
+box. The memory buffer must be large enough to contain the box (in general, the |
+correct buffer dimension is $(y2-y1+1)*(x2-x1+1)*bpp$). |
+\item [See]\textbf{also}: \texttt{grx\_putimage()}. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_RECT\index{grx\_rect()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int grx\_rect(WORD x1, WORD y1, WORD x2, WORD y2, DWORD col);}] |
+\item [\textbf{Description:}] It draws an empty rectangle with top left corner at |
+(\texttt{x1},\texttt{y1}) and bottom right corner at (\texttt{x2},\texttt{y2}). |
+The rectangle is drawn with color \texttt{col}. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_BOX\index{grx\_box()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{int grx\_box(WORD x1, WORD y1, WORD x2, WORD y2, DWORD col);}] |
+\item [\textbf{Description:}] It draws a filled rectangle with top left corner at |
+(\texttt{x1},\texttt{y1}) and bottom right corner at (\texttt{x2},\texttt{y2}). |
+The box is drawn with color \texttt{col}. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_LINE\index{grx\_line()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_line(WORD x1, WORD y1, WORD x2, WORD y2, DWORD col);}] |
+\item [\textbf{Description:}] It draws a line from (\texttt{x1}, \texttt{y1}) to |
+(\texttt{x2},\texttt{y2}) using color \texttt{col}. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_TEXT\index{grx\_text()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_text(char *text, WORD x, WORD y, DWORD fg, DWORD bg);}] |
+\item [\textbf{Description:}] It writes a 0 terminated text string in graphic mode at |
+position (\texttt{x},\texttt{y}). The string is pointed by \texttt{text}, |
+\texttt{fg} is the foreground color, and \texttt{bg} is the background color. |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_CIRCLE\index{grx\_circle()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_circle(WORD x, WORD y, WORD r, DWORD col);}] |
+\item [\textbf{Description:}] It draws a circle of radius \texttt{r} and color |
+\texttt{col}, centered at (\texttt{x}, \texttt{y}). |
+\end{description} |
+ |
+\begin{intest} |
+GRX\_DISC\index{grx\_disc()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void grx\_disc(WORD x, WORD y, WORD r, DWORD col);}] |
+\item [\textbf{Description:}] It draws a filled circle of radius \texttt{r} and color |
+\texttt{col}, centered at (\texttt{x}, \texttt{y}). |
+\end{description} |
/new_sharkdoc/vol2/graph.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol2/console.tex |
=================================================================== |
--- new_sharkdoc/vol2/console.tex (nonexistent) |
+++ new_sharkdoc/vol2/console.tex (revision 1676) |
@@ -0,0 +1,123 @@ |
+%---------------------------------------------------------------------------- |
+\chapter{The Console Library} |
+%---------------------------------------------------------------------------- |
+ |
+The output on the screen in text mode is supported by a group of functions that |
+act on the whole screen and modify, each time, the cursor's position. Since such |
+functions are not reentrant, they must be used in mutual exclusion. |
+ |
+In order to use the library for displaying on the screen, the |
+``\texttt{cons.h}'' file must be included. This file contains the values for |
+the usable colors whose symbolic names are listed below: \texttt{BLACK, BLUE, |
+GREEN, CYAN, RED, MAGENTA, BROWN, GRAY, LIGHTGRAY, LIGHTBLUE, LIGHTGREEN, |
+LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE}. |
+ |
+Two global read-only variables \texttt{cons\_columns} and \texttt{cons\_rows} |
+contain the number of screen columns and the number of screen rows, |
+respectively. They can be used to write applications that are indipendent from |
+the screen dimensions. |
+ |
+\vspace{7mm} |
+ |
+\begin{intest} |
+CPUTC, CPUTS, CPRINTF \index{cputc()}\index{cputs()}\index{cprintf()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void cputc(char c); }] |
+\item [\textbf{void cputs(char {*}s); }] |
+\item [\textbf{int cprintf(char {*}fmt,... ); }] |
+\item [\textbf{Description:}] \texttt{cputc}, \texttt{cupts} and \texttt{cprintf} are used |
+to print on the screen a character, a string, or a formatted string, |
+respectively. In the latter case, the standard C I/O formatting conventions are |
+used. |
+\item [\textbf{Warning:}]since these functions modify the cursor position, they are not |
+reentrant, and must be used in a mutually exclusive fashion. |
+\end{description} |
+ |
+\begin{intest} |
+PUTC\_XY, PUTS\_XY, PRINTF\_XY, GETC\_XY \index{putc\_xy()} \index{puts\_xy()} |
+\index{printf\_xy()} \index{getc\_xy()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void putc\_xy(int x,int y,char attr,char c) }] |
+\item [\textbf{void puts\_xy(int x,int y,char attr,char {*}s) }] |
+\item [\textbf{int printf\_xy(int x,int y,char attr,char {*}fmt,...) }] |
+\item [\textbf{char getc\_xy(int x,int y,char {*}attr,char {*}c) }] |
+\item [\textbf{Description:}] These functions are similar to the previously defined ones; |
+the only difference is that since they're reentrant can be used concurrently by |
+multiple tasks (the others cannot be used for this purpose because they modify |
+the cursor's state). \texttt{getc\_xy} is used to read the charcater and its |
+attribute at a specific position on the screen. |
+\end{description} |
+ |
+\begin{intest} |
+CLEAR, \_CLEAR, SCROLL, \_SCROLL \index{clear()} \index{\_clear()} |
+\index{\_scroll()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void \_clear(char c,char attr,int x1,int y1,int x2,int y2) }] |
+\item [\textbf{void clear(void) }] |
+\item [\textbf{void \_scroll(char attr,int x1,int y1,int x2,int y2) }] |
+\item [\textbf{void scroll(void) }] |
+\item [\textbf{Description:}] the \texttt{clear} and \texttt{scroll} functions are used |
+for clearing the screen and for scrolling it upwards. They are based on the |
+\texttt{\_clear()} and \texttt{\_scroll()} functions used for clearing or |
+scrolling a window (defined by \texttt{x1, y1, x2, y2}) by filling the area with |
+\texttt{attr} color and, in the case of \texttt{\_clear}, with character |
+\texttt{c} as well. |
+\end{description} |
+ |
+\begin{intest} |
+SET\_ACTIVE\_PAGE, SET\_VISUAL\_PAGE,\\ |
+GET\_ACTIVE\_PAGE, GET\_VISUAL\_PAGE |
+\index{set\_active\_page()} \index{set\_visual\_page()} |
+\index{get\_active\_page()} \index{get\_visual\_page()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void set\_active\_page(int page) }] |
+\item [\textbf{void set\_visual\_page(int page) }] |
+\item [\textbf{int get\_active\_page(void) }] |
+\item [\textbf{int get\_visual\_page(void) }] |
+\item [\textbf{Description:}] The video cards working in text mode use the CGA hardware |
+scheme. In this scheme, every screen occupies 4000 bytes (80 columns x 25 rows; |
+each position is associated with two bytes, one for codifying the character and |
+another for codifying the color). The video card memory is in general bigger, |
+therefore multiple screen pages can be used simultaneously. The currently |
+visualized screen is called the \texttt{visual page}, whereas the screen the |
+output is directed to is called the \texttt{active page}. The cited functions |
+are essentially used for handling, at a given instant, the visual page or the |
+active page. SUGGESTION: if the active page or the visual page are modified, |
+they should be restored to the original (0) value on exit; the same is true for |
+the cursor. |
+\end{description} |
+ |
+\begin{intest} |
+PLACE, CURSOR, CURSOR\_INFO |
+\index{place()} \index{cursor()} \index{cursor\_info()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void place(int x, int y) }] |
+\item [\textbf{void cursor(int start\_scanline, int end\_scanline) }] |
+\item [\textbf{void cursor\_info(int {*}x, int {*}y) }] |
+\item [\textbf{Description:}] These functions are used for handling the cursor. More |
+specifically, \texttt{place} sets the cursor position (\texttt{x} belongs to the |
+range 0\ldots{}79, \texttt{y} to 0\ldots{}24). |
+\end{description} |
+ |
+\begin{intest} |
+CURSOR\_BLOB, CURSOR\_STD, CURSOR\_OFF |
+\index{cursor\_blob()} \index{cursor\_std()} \index{cursor\_off()} |
+\end{intest} |
+ |
+\begin{description} |
+\item [\textbf{void cursor\_blob(void) }] |
+\item [\textbf{void cursor\_std(void) }] |
+\item [\textbf{void cursor\_off(void) }] |
+\item [\textbf{Description:}] These macros call the \texttt{cursor()} function to set the |
+cursor shape to be a big rectangle, the standard underscore, or invisible. |
+\end{description} |
/new_sharkdoc/vol2/console.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol2/vol2.tex |
=================================================================== |
--- new_sharkdoc/vol2/vol2.tex (nonexistent) |
+++ new_sharkdoc/vol2/vol2.tex (revision 1676) |
@@ -0,0 +1,74 @@ |
+\documentclass[english]{report} |
+\usepackage[T1]{fontenc} |
+\usepackage[latin1]{inputenc} |
+\usepackage{geometry} |
+\geometry{verbose,a4paper} |
+\usepackage{makeidx} |
+\makeindex |
+\usepackage{graphicx} |
+ |
+\makeatletter |
+ |
+\newenvironment{intest}{\noindent\large\bf\hspace*{1pt}} |
+{\vspace*{-5pt}\\\line(1,0){433}} |
+ |
+\topmargin=-0.2 truein |
+\textheight=8.6 truein |
+\textwidth=6.1 truein |
+\oddsidemargin=1cm |
+\headsep=1.3cm |
+ |
+\usepackage{babel} |
+\makeatother |
+\begin{document} |
+ |
+\thispagestyle{empty} |
+ |
+\begin{center}{\LARGE S.Ha.R.K. User Manual}\end{center}{\LARGE \par} |
+\vfill{} |
+ |
+\begin{center}{\large Volume II}\end{center} |
+ |
+\begin{center}{\large Programming Libraries}\end{center}{\large \par} |
+\vfill{} |
+ |
+\begin{center}Written by\end{center} |
+\begin{center}Giorgio Buttazzo (giorgio at sssup.it)\end{center} |
+\begin{center}Paolo Gai (pj at sssup.it)\end{center} |
+\begin{center}Luigi Palopoli (luigi at gandalf.sssup.it)\end{center} |
+\begin{center}Luca Abeni (luca at gandalf.sssup.it)\end{center} |
+\begin{center}Giuseppe Lipari (lipari at gandalf.sssup.it)\end{center} |
+\begin{center}Gerardo Lamastra (lamastra at sssup.it)\end{center} |
+\begin{center}Antonino Casile (casile at sssup.it)\end{center} |
+\begin{center}Massimiliano Giorgi (massy at gandalf.sssup.it)\end{center} |
+\begin{center}Tullio Facchinetti (tullio.facchinetti at unipv.it)\end{center} |
+\vfill{} |
+ |
+\begin{center}\includegraphics[width=2cm]{../common/sssup.ps}\end{center} |
+ |
+\begin{center}Scuola Superiore di Studi e Perfezionamento S. Anna\end{center} |
+\begin{center}RETIS Lab\end{center} |
+\begin{center}Via Carducci, 40 - 56100 Pisa\end{center} |
+ |
+\pagebreak |
+\tableofcontents{} |
+ |
+\include{intro} |
+\include{linuxc26} |
+\include{input} |
+\include{graph} |
+\include{fg} |
+\include{cpu} |
+\include{netlib} |
+\include{rtc} |
+\include{soundlib} |
+\include{console} |
+\include{file} |
+\include{snapshot} |
+ |
+\printindex{} |
+ |
+\bibliographystyle{alpha} |
+\bibliography{../common/biblio} |
+ |
+\end{document} |
/new_sharkdoc/vol2/vol2.tex |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol2/images/driver1.dia |
=================================================================== |
--- new_sharkdoc/vol2/images/driver1.dia (nonexistent) |
+++ new_sharkdoc/vol2/images/driver1.dia (revision 1676) |
@@ -0,0 +1,11 @@ |
+ í[Ûrâ8}ÏW¸W"$ù>2Åd²5©ÉÎTd/OÀ |
+xÇØ-BxÙo_ÉfBð ²@U ì4ÝÔ§OwK|üô4òGÅ^´T ªÐ º^0h©÷w¿ÙꧮG>ð¿ADF |
+ÿF«:dlü¡ÙN§ÀÅ ð½ ió_âû¤É êÅ¢¼TàFĽù]ÂXäõ&*ÑÚ#ý(®JÍåú¡FÊ#ñ[êéCòRs5Í%=+tÉö"J~«üå8UTiU;±ÇEØl)Ñ#Þ_ÈÌ¥b..NÛúiúHó]EZjH4ð¼>7~:Øã_ó°½|¾||^ÜÇòfzaèS¤X4¡ÕíÄ}âsY5T]ûÇX¸æùo2ôö3z¶Eâ òÜÕ@\(Ñ2õ\6ì>I®TûLöG/öz>-zz/`;S?Ûúìê$ÑxñõÞj+ +÷®M +jlîÏ¥ñ7[)Ñ45×ÍzVnÓIoeÈ71áæê?/hW/ð<â¼ °÷í³ùðn \¹Êò9|RYÏ!<·¥þËÓWÆ#_n~Æá³Ù +#;Ü|°(SÝëe5GüÙI0ðiªÝÑÐùÛ¹46«fútÔíQ§÷]&QDüY×Ð=¤Þ`ÈÊkÕt{î2 H\B³xN»ãzú,zsáå¸ý}b~êú=rDÇG0°Ñ0Î?αίø%SÑA5Q=#S¶IZ»$ÉoÁW:àP¾Q8¿$^A:eL°"Ãâ¾ò@F?ãÏGXUb6ѯwúÕ¯Ô¤ÌëA|û'ÈÁ°çõL,ûÝzß«b#øÒ2Âzx>;F´xÙh0¤"«">ÝM (æG\Ùüh~ÄXð#ÂÒ ÒGHß[½XÙ{Ôj$÷FÌìÐáe}âþ¦fq@ ÷&o®¿ßÿ¥``\ý~Ó¾»þñ]¹iÿ}Õyg|!1sÎxdM¬©×gM¤É¦M'ëJdJçͪ:ðÊR´v¨q@Äiì ²ÊH¨-yà¤iìGiùµÝùòg»su,)w^RÙñØѬ!°&µ¨Äø¹ª³£ìª²ú6aGk«JbTUiÕv}òKÑo5@HÔ60DÉQÐPäëÎÕåÝIûòòêööÝl¦,ôÀ#_î$jÜx-víZO +ÉM« +Dzťniç<¡Ö!Æ<@£ûatià&CÙr M,Ë}¤?Î/:G°¿nDQ8Í*^¸¤VSsקÁ`Uj Q×Ää +Úb¹GqÇsDñë?ÊCEÄV¤*,L¶'ÅV"§t7tv@ãºÆÑÁ=Z2÷Q¹!èXzrp@ÌMà@l |
+XÚÙaY6ÌbV9¢óÀÐiþ?èDp{7X.WêÓ@8º.¨Û&RÚ²1[!Ú6NöÊÁéÉ7IXÌækaí¢òJniÐLaik Wj Áz +®\L!¢y È4%#³¸jð9C<Ã!ÑuiÀðÄR»±u´Q?XÄ,ªMw,Mj>C:[ÿ¬ØAu³ Øüã\ ÷¡!Û¹þãêAÒ÷,ó^w}Xøfû°¨ö¹¯X3]f¤0éØPv ÃóX@Óp»Dä<¶h ç*çkÇöf°(S\ê9ؼ«mþ¦×ÉïÅ.N~PvqòK iD> |
\ No newline at end of file |
/new_sharkdoc/vol2/images/driver1.dia |
---|
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: new_sharkdoc/vol2/images/driver2.dia |
=================================================================== |
--- new_sharkdoc/vol2/images/driver2.dia (nonexistent) |
+++ new_sharkdoc/vol2/images/driver2.dia (revision 1676) |
@@ -0,0 +1,27 @@ |
+ í][SÛH~ϯP9/»U¦ïaÈa]*LÂrÝ}J ¬íØk/ûÛ÷tË KÛÝÚ¨JT%LÓ§O÷Ñ÷}§oüòëÙ4ºMæ4ÏöáAdù8Í&{ó³w?éÁ¯o^ý2NãáßdÏ"ølaöWEqýóÎÎÝÝÞ/â"£izÉÎãé4ÞB;7¯¢èÛ |
+ÆqÛÏÆE1O/n$ÊâY²7¸/ÿÌól<(K-Ë]æÓ|ÝÆÓ½ÁëÏîk°³¬fçI=ÏÔ}OyÿÑ\5/c6©ú:W«]ç÷×+Eê±ÿSfYj ²É×ûüuÙ¤åuÕ5´ÑH1ç4[µ}3-;"M)ýÚë¸obÞÄ<¼tñé:ó8-VÍ\äù4³ÒR1¿I6·³¸§2ϹB6¯ýsZùwÚÿ9.^â@ùñÃÛ³î8§ãç_Ä'%j¹KÇÅÕ§/º«¬ý>Pí·é"½&uO³Â[õ÷~ª¯CãÇ_ß2ÊÚá~¬õá~rÅwÂìi®Åv¾×ëÕr/íò£ |
+ù:Óø>/«ûH»ÑróM/äÿN.¥{§Eãù8ú):K¾G""ï +>â§ýSõjè[é ëü!8C¨:½ |
+Mõ_\T«q6&&2b(ÄÑÍl¶¾Ø2M8íýI¹8:üpþÏ*£?¥ÙÍ"f7Ó¸Þì þ¹A&<ó.6{u±GãY:½6ÇÙb-{40úå¯þ-Þ&EzÛë·à*I'Wµmh ËõM<ÂEâ&vÑ3 |
+ãíÕO²YR?tIv3+m½ÔJ-Ô4ÁåÎ#Rld[èPH9¢!¡Ã`]5¦~|è8>8¤²Ç¿Ø°j=6xÁ ·¤è¶Ø Sý°A _¬ßw%" |
+3$1Éf/ó,ûdcçÊzÖQTØQ³Ys T.¯«¨Ë Æó\Ù÷Àá`ì*D¬±`Õ«:ä"[xþ#?ßvü5¶89üq@;LsÈ5À¨Äðè| +ê\¬-5$2¡ChÛAF +R:d08# +9'C FtÓðkS<~ýããÉû^>úuA×Ȥ!=¨¹¡@B¦ + ¥µÃµPÄæsÏÊM1jÚ¨q².~¡BÚL Ù]-¡¶.mOHd6ïF!Æ%¥162Æj¨¬*xd4øYVÊNë |
+íAWÂë |
+Íè |
+´Bw@VÒ~N*¨X¸^T ã%ù j|p` +±KbÃIrwoíz×ñÁa.¢,/¢yòt£»´¸~îGáè6'y4ËÇI¿"O©Äg)!)Ùz`jÀ<(¨f§·Àã\î³ XA' |
+,x`5Zëc}1פî&(øaÊp8"8v£¢ +%Ì |
+RH& +t?¼ÕLµ5^Ö$aSWòÿ< |