Subversion Repositories shark

Rev

Rev 1676 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1676 tullio 1
%----------------------------------------------------------------------------
2
\chapter{Utility functions}
3
%----------------------------------------------------------------------------
4
 
5
S.Ha.R.K. provides a set of utility functions aimed at getting information
6
about the kernel state. Mainly, they allow a user to get the actual
7
system time and some information concerning the tasks' state. Moreover,
8
it allows to set exception handlers and to manage interrupts.
9
 
10
%----------------------------------------------------------------------------
11
\section{Reading time}
12
%----------------------------------------------------------------------------
13
 
14
The S.Ha.R.K. Kernel does not have the concept of tick. Every time
15
interval and every absolute time in the system is measured usin the
16
Real-Time Clock available on the PC. To read the current time you
17
can use the following function:
18
 
19
%----------------------------------------------------------------------------
20
\begin{intest}
21
SYS\_GETTIME\index{sys\_gettime()}
22
\end{intest}
23
 
24
\begin{description}
25
\item [\texttt{TIME sys\_gettime(struct timespec *t);}]
26
\item [Description:]It returns the number of microseconds elapsed from
27
system's initialization, that is from the end of the \texttt{\_\_kernel\_register\_levels\_\_}
28
function. If the \texttt{t} value is not equal \texttt{NULL}, the
29
function fills also the timespec structure passed as parameter.
30
\end{description}
31
 
32
%----------------------------------------------------------------------------
33
\section{Getting information on tasks}
34
%----------------------------------------------------------------------------
35
 
36
Since all the tasks are handled by a Module, it is a responsibility of each
37
Module to hide or not hide informations about the tasks handled by the system.
38
However, at the moment S.Ha.R.K. provides a function that simply prints the
39
tasks state on the console \footnote{Old versions of the kernel supported a
40
\texttt{void sys\_status(DWORD cw);} \index{sys\_status()}primitive. That
41
primitive is currently unsupported.}.
42
 
43
\pagebreak
44
 
45
%----------------------------------------------------------------------------
46
\begin{intest}
47
PERROR\index{perror()}
48
\end{intest}
49
 
50
\begin{description}
51
\item [\texttt{void perror (const char *s);}]
52
\item [Description:]This is the POSIX \texttt{perror()} funcion, that prints
53
on the console (using \texttt{kern\_printf}) a message that explain
54
the meaning of the \texttt{errno} \index{errno} variable. Note that
55
each task has its own \texttt{errno} variable, as specified by the
56
\texttt{POSIX} standard.
57
\end{description}
58
 
59
%----------------------------------------------------------------------------
60
\begin{intest}
61
exec\_shadow\index{exec\_shadow}
62
\end{intest}
63
\begin{description}
64
\item [\texttt{PID exec\_shadow;}]
65
\item [Description:]This is the internal variable used by the Kernel to
66
track the running task. You can read its value to know the PID of
67
the current task. You CAN NOT modify this variable.
68
\end{description}
69
 
70
%----------------------------------------------------------------------------
71
\section{Printing messages on the console}
72
%----------------------------------------------------------------------------
73
 
74
To print a simple message on the console, please use the c* functions
75
(cprintf\index{cprintf}, cputs\index{cputs}, \ldots{}) described
76
in Volume II. If tou are debugging \emph{the kernel}, you can use
77
kern\_printf \index{kern\_printf} to print very simple messages without
78
floating point arithmetic.
79
 
80
%----------------------------------------------------------------------------
81
\chapter{Signals and Exception Handling}
82
%----------------------------------------------------------------------------
83
 
84
%----------------------------------------------------------------------------
85
\section{Signals}
86
%----------------------------------------------------------------------------
87
 
88
S.Ha.R.K. implements the specification of the signals and of the real-time
89
signald provided by the standard IEEE 1003.13 POSIX PSE51/PSE52. In
90
particular, you can use all the functions described into the IEEE
91
1003.1\{a,b\} standards, except that:
92
 
93
\begin{itemize}
94
\item all the \texttt{pid\_t} parameters and in general all parameters related
95
with processes should be ignored;
96
\item when in POSIX a signal cause the termination of the process, it causes
97
in S.Ha.R.K. the termination of the whole system (you can think S.Ha.R.K.
98
as a single process multithread kernel);
99
\item The \texttt{siginfo\_t} structure contains an additional parameter
100
called \texttt{si\_task} of type \texttt{PID}. It contains the \texttt{PID}
101
of the task that queued a particular real-time signal.
102
\end{itemize}
103
 
104
In particular, you can use these functions for signal handling: \texttt{kill},
105
\texttt{sigemptyset}, \texttt{sigfillset}, \texttt{sigaddset},
106
\texttt{sigdelset}, \texttt{sigismember}, \texttt{sigaction},
107
\texttt{pthread\_sigmask} \footnote{If you are not using the POSIX scheduling
108
modules please use \texttt{task\_sigmask}}, \texttt{sigprocmask},
109
\texttt{sigpending}, \texttt{sigsuspend}, \texttt{sigwait},
110
\texttt{sigwaitinfo}, \texttt{sigtimedwait}, \texttt{sigqueue},
111
\texttt{pthread\_kill} \footnote{If you are not using the POSIX scheduling
112
modules please use \texttt{task\_signal} (Note that \texttt{task\_kill} does not
113
send any signal, but issue a cancellation request on a task!)}, \texttt{alarm},
114
\texttt{pause}, \texttt{sleep} (note the difference between \texttt{sleep},
115
\texttt{task\_sleep} and \texttt{nanosleep}!), \texttt{raise}, \texttt{signal}.
116
 
117
%----------------------------------------------------------------------------
118
\section{Exception handling\label{ch:except}}
119
%----------------------------------------------------------------------------
120
 
121
S.Ha.R.K. provides a flexible mechanism to handle the exceptions of the Kernel.
122
The mechanism is based on the POSIX signals. In fact, S.Ha.R.K. exceptions are
123
remapped on the real-time signal \texttt{SIGHEXC} \footnote{see
124
\texttt{include/signal.h}.} (9). Every time something goes wrong, the system
125
calls the primitive \texttt{kern\_raise}, that simply queue a real-time signal
126
of number SIGHEXC.
127
 
128
The user can define its own exception handler simply remapping the SIGHEXC
129
signal using the POSIX primitive \texttt{sigaction}. To fullfil the typical
130
usage of an exception handler (exit the system after printing a message), the
131
default behavior of the signal handler has been redefined to print a text
132
message on system shutdown. \footnote{Older versions of the Kernel supported two
133
functions to be used for standard redefinition of the kernel signal handler.
134
These functions, called SET\_EXCHANDLER\_TXT\index{set\_exchandler\_txt()} and
135
SET\_EXCHANDLER\_GRX\index{set\_exchandler\_grx()}, are no more supported, and
136
can be removed from your code without problems.}
137
 
138
Here is a sample code that explain how to redefine a signal handler:
139
 
140
\begin{verbatim}
141
#include <kernel/kern.h>
142
 
143
void thehandler(int signo, siginfo_t *info, void *extra) {
144
 
145
    /* the signal handler:
146
    info.sivalue.sival_int contains the exception number
147
    (see include/bits/errno.h)
148
 
149
    info.si_task is the task that raised the exception
150
    extra is not used
151
    */
152
    ...
153
}
154
 
155
...
156
 
157
int myfunc(...) {
158
    struct sigaction action;
159
    ...
160
 
161
    action.sa_flags = SA_SIGINFO;
162
    action.sa_sigaction = thehandler;
163
    action.sa_handler = 0;
164
    sigfillset(&action.sa_mask);
165
    sigaction(SIGHEXC, &action, NULL);
166
 
167
    ...
168
}
169
\end{verbatim}
170
 
171
%----------------------------------------------------------------------------
172
\begin{intest}
173
KERN\_RAISE\index{kern\_raise()}
174
\end{intest}
175
 
176
\begin{description}
177
\item [\texttt{void kern\_raise(int n, PID p);}]
178
\item [Description:]This function uses the POSIX function sigqueue to put
179
a signal SIGHEXC into the signal queue. The parameter n is used as
180
the exception number, and it is passed into the siginfo\_t parameter
181
(into the sivalue.sival\_int field). The signal appears to be queued
182
by the task p (the p value is stored into the si\_task field of the
183
siginfo\_t structure passed as parameter).
184
\end{description}
185
 
186
%----------------------------------------------------------------------------
187
\chapter{Interrupt and HW Ports handling}
188
\label{ch:interr}
189
%----------------------------------------------------------------------------
190
 
191
Generally speaking, I/O to and from an external peripheral device
192
can be handled in three different ways depending on the peripheral
193
type and on the application:
194
 
195
\begin{itemize}
196
\item \textbf{Polling}: the program cyclically checks the status of the
197
I/O port, waiting for a input data to be ready or an output data to
198
be transmittable;
199
\item \textbf{Interrupt}: the program enables the I/O interface to send
200
a hardware interrupt every time an input data is available or an output
201
data is transmittable;
202
\item \textbf{DMA}: the program enables the interface to use DMA mechaninsm
203
for directly transferring data to/from memory.
204
\end{itemize}
205
\noindent In this chapter we will analyse the support that the S.Ha.R.K.
206
kernel provides for using the second method (interrupt).
207
 
208
When an interrupt arrives, a code for the hand-shake with the interface
209
and for transferring data has to be executed. This code can run in
210
two different modes:
211
 
212
\begin{itemize}
213
\item it can be entirely encapsulated in a function to be executed immediately
214
on the interrupt arrival, in the context of the executing task (\textit{fast
215
handler});
216
\item it can be entirely encapsulated in a task (\textit{safe handler})
217
which is activated on the interrupt arrival and scheduled with its
218
own priority together with the other tasks.
219
\end{itemize}
220
\noindent The first method is appropriate when the interrupt needs
221
a fast response time. Its potential drawback is that if its computation
222
time is not low, the overall schedulabuility can be severly affected.
223
This is because the guarantee algorithm does not take into account
224
the execution time of the interrupt handlers. The second method, on
225
the contrary, is perfectly integrated with the kernel's scheduling
226
mechanism, but can cause considerable delays in transferring data.
227
 
228
S.Ha.R.K. provides great flexibility in interrupt handling, since
229
it allows each interrupt to be associated with a \textit{fast handler},
230
a \texttt{safe handler}, or both.
231
 
232
On an interrupt's arrival the following operations are performed by
233
the kernel:
234
 
235
\begin{itemize}
236
\item The system checks whether a fast handler is associated with the interrupt.
237
If so, the interrupts are enabled and the handler is invoked. This
238
method allows a handler to be interrupted by a higher priority handler.
239
As an example, the keyboard handler (interrupt 1) can be interrupted
240
be the timer handler (interrupt 0).
241
\item The system checks whether a sporadic task (\emph{safe handler}) is
242
associated with the interrupt. If so, the task is activated and is
243
eligible to run with enabled interrupts.
244
\end{itemize}
245
\noindent The system provides a set of functions for accessing the
246
hardaware interfaces' ports. In the drivers directory you can find
247
examples of a S.Ha.R.K. device driver.
248
 
249
%----------------------------------------------------------------------------
250
\section{Setting an interrupt handler}
251
%----------------------------------------------------------------------------
252
 
253
%----------------------------------------------------------------------------
254
\begin{intest}
255
HANDLER\_SET\index{handler\_set()}
256
\end{intest}
257
 
258
\begin{description}
259
\item [\texttt{int handler\_set(int no, void (*fast)(int), PID
260
pi, BYTE lock);}]
261
\item [Description:]It installs function \texttt{fast} (fast handler) and
262
the sporadic task \texttt{p} (safe handler) on the interrupt identified
263
by \texttt{no}. The \texttt{no} parameter must belong to the range
264
1\ldots{}15 (interrupt 0 is associated to the timer and cannot be
265
intercepted). On the interrupt's arrival, function \texttt{fast} is
266
invoked and runs. Depending on the \texttt{lock} flag, the interrupts
267
are disabled (\texttt{lock} = TRUE) or enabled (\texttt{lock} = FALSE)
268
during handler execution. Furthermore, on the interrupt's arrival,
269
task \texttt{p} is activated.
270
\end{description}
271
 
272
%----------------------------------------------------------------------------
273
\begin{intest}
274
HANDLER\_REMOVE\index{handler\_remove()}
275
\end{intest}
276
 
277
\begin{description}
278
\item [\texttt{void handler\_remove(int no);}]
279
\item [Description:]It removes the handler of the interrupt number \texttt{intno};
280
the interrupt is masked.
281
\end{description}
282
 
283
%----------------------------------------------------------------------------
284
\section{Reading and writing from I/O ports}
285
%----------------------------------------------------------------------------
286
 
287
%----------------------------------------------------------------------------
288
\begin{intest}
289
INP, INPW, INPD \index{inp()} \index{inpw()} \index{inpd()}
290
\end{intest}
291
 
292
\begin{description}
293
\item [\texttt{unsigned char inp(unsigned short \_port);}]
294
\item [\texttt{unsigned short inpw (unsigned short \_port);}]
295
\item [\texttt{unsigned long inpd(unsigned short \_port);}]
296
\item [Description:]They return the data read on port \texttt{\_port}.
297
\end{description}
298
 
299
%----------------------------------------------------------------------------
300
\begin{intest}
301
OUTP, OUTPW, OUTPD \index{outp()} \index{outpw()} \index{outpd()}
302
\end{intest}
303
 
304
\begin{description}
305
\item [\texttt{void outp(unsigned short \_port, unsigned char \_data);}]
306
\item [\texttt{void outpw(unsigned short \_port, unsigned short \_data);}]
307
\item [\texttt{void outpd(unsigned short \_port, unsigned long \_data)}]
308
\item [Description:]It writes the data \texttt{\_data} into the port \texttt{\_port}.
309
\end{description}
310
 
311
%----------------------------------------------------------------------------
312
\section{Disabling/Enabling interrupts}
313
%----------------------------------------------------------------------------
314
 
315
%----------------------------------------------------------------------------
316
\begin{intest}
317
KERN\_CLI\index{kern\_cli()}
318
\end{intest}
319
 
320
\begin{description}
321
\item [\texttt{void kern\_cli(void);}]
322
\item [Description:]It disables interrupts (as the x86 \texttt{cli} instruction).
323
\end{description}
324
%----------------------------------------------------------------------------
325
 
326
\begin{intest}
327
KERN\_STI\index{kern\_sti()}
328
\end{intest}
329
 
330
\begin{description}
331
\item [\texttt{void kern\_sti(void);}]
332
\item [Description:]It enables interrupts (as the x86 \texttt{sti} instruction).
333
\end{description}
334
 
335
%----------------------------------------------------------------------------
336
\section{Saving/Restoring interrupts}
337
%----------------------------------------------------------------------------
338
 
339
%----------------------------------------------------------------------------
340
\begin{intest}
341
KERN\_FSAVE\index{kern\_fsave()}\index{SYS\_FLAGS}
342
\end{intest}
343
 
344
\begin{description}
345
\item [\texttt{SYS\_FLAGS kern\_fsave(void);}]
346
\item [Description:]It disables interrupts (as the x86 \texttt{cli} instruction).
347
The CPU flags are returned by the function; in that way they can be
348
restored using kern\_frestore
349
\end{description}
350
 
351
%----------------------------------------------------------------------------
352
\begin{intest}
353
KERN\_FRESTORE\index{kern\_frestore()}
354
\end{intest}
355
 
356
\begin{description}
357
\item [\texttt{void kern\_frestore(SYS\_FLAGS f);}]
358
\item [Description:]It restores the interrupt state as it was when the
359
correspondent \texttt{kern\_fsave} was called.
360
\end{description}
361
 
362
%----------------------------------------------------------------------------
363
\section{Masking/Unmasking PIC interrupts}
364
%----------------------------------------------------------------------------
365
 
366
%----------------------------------------------------------------------------
367
\begin{intest}
368
IRQ\_MASK\index{irq\_mask()}
369
\end{intest}
370
 
371
\begin{description}
372
\item [\texttt{void irq\_mask(WORD irqno);}]
373
\item [Description:]It mask the interrupt number \texttt{irqno} on the
374
PC PIC. \texttt{irqno} must be in the interval {[}1..15{]}.
375
\end{description}
376
 
377
%----------------------------------------------------------------------------
378
\begin{intest}
379
IRQ\_UNMASK\index{irq\_unmask()}
380
\end{intest}
381
 
382
\begin{description}
383
\item [\texttt{void irq\_unmask(WORD irqno);}]
384
\item [Description:]It unmask the interrupt number \texttt{irqno} on the
385
PC PIC. \texttt{irqno} must be in the interval {[}1..15{]}.
386
\end{description}
387
 
388
%----------------------------------------------------------------------------
389
\chapter{Memory Management Functions}
390
%----------------------------------------------------------------------------
391
 
392
The S.Ha.R.K. Kernel provides the standard set of memory allocations
393
functions provided by the Standard C libraries. In particular, the
394
functions listed in figure \ref{fig:malloc} can be used.
395
 
396
\begin{figure}
397
\begin{center} \fbox{\tt{ \begin{minipage}{6cm} \begin{tabbing}
398
123\=123\=123\=\kill
399
\#include <stdlib.h>\\
400
void *calloc(size\_t nmemb, size\_t size);\\
401
void *malloc(size\_t size);\\
402
void free(void *ptr);\\
403
void *realloc(void *ptr, size\_t size);\\
404
\end{tabbing} \end{minipage} }} \end{center}
405
\caption{\label{fig:malloc}Memory allocation functions.}
406
\end{figure}
407
In particular \footnote{These descriptions came directly from the Linux man pages...}:
408
 
409
\begin{itemize}
410
\item calloc() allocates memory for an array of nmemb elements of size bytes
411
each and returns a pointer to the allocated memory. The memory is
412
set to zero. The value returned is a pointer to the allocated memory,
413
which is suitably aligned for any kind of variable, or NULL if the
414
request fails.
415
\item malloc() allocates size bytes and returns a pointer to the allocated
416
memory. The memory is not cleared. The value returned is a pointer
417
to the allocated memory, which is suitably aligned for any kind of
418
variable, or NULL if the request fails.
419
\item free() frees the memory space pointed to by ptr, which must have been
420
returned by a previous call to malloc(), calloc() or realloc(). Otherwise,
421
or if free(ptr) has already been called before, undefined behaviour
422
occurs. If ptr is NULL, no operation is performed.
423
\item realloc() changes the size of the memory block pointed to by ptr to
424
size bytes. The contents will be unchanged to the minimum of the old
425
and new sizes; newly allocated memory will be uninitialized. If ptr
426
is NULL, the call is equivalent to malloc(size); if size is equal
427
to zero, the call is equivalent to free(ptr). Unless ptr is NULL,
428
it must have been returned by an earlier call to malloc(), calloc()
429
or realloc(). It returns a pointer to the newly allocated memory,
430
which is suitably aligned for any kind of variable and may be different
431
from ptr, or NULL if the request fails or if size was equal to 0.
432
If realloc() fails the original block is left untouched - it is not
433
freed or moved.
434
\end{itemize}
435
 
436
The S.Ha.R.K. Kernel also provides a set of low-level memory management
437
functions that can be used to allocate memory with particular requirements
438
(for example, they are useful for getting memory blocks aligned to
439
a page (4 Kb) boundary or with addresses under 1/16 Mb). Description
440
of these functions is given in Chapter 3 of the S.Ha.R.K. Architecture
441
Manual.