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{Kernel Internals}
3
%----------------------------------------------------------------------------
4
 
5
Since the Generic Kernel does not implement any memory protection,
6
all the Modules have access to the internal data structures used
7
for scheduling. Although the Modules could modify these data
8
structures, typically they do not need to do so.
9
 
10
%----------------------------------------------------------------------------
11
\section{Kernel types}
12
%----------------------------------------------------------------------------
13
 
14
The Generic Kernel defines a set of primitive data types, that are
15
briefly described below:
16
 
17
\begin{description}
18
\item [PID]This type is used to contain a task index. It is an
19
integer pointing to an entry of the task descriptor table. This
20
type can have values in the range {[}0...MAXPROC-1{]}, plus an
21
invalid value, NIL (that is, -1).
22
 
23
\item [IQUEUE]This type is used to implement the task queues typically used in
24
scheduling operations. For more information see Section \ref{KernSupport_Code}.
25
 
26
\item [TASK]This type is simply a
27
redefinition of the \texttt{void {*}} type and it can be used for
28
readiness ad the returned value in the task function declaration.
29
 
30
\item [LEVEL,~RLEVEL]They are used to index the Module descriptor
31
Tables. They are integers and they point to a particular entry.
32
The values of these types are
33
{[}0...\texttt{MAX\_SCHED\_LEVEL-1}{]} for the \texttt{LEVEL} type
34
and {[}0...\texttt{MAX\_RES\_LEVEL}{]} for the \texttt{RLEVEL}
35
type.
36
 
37
\item [bandwidth\_t]This type is used to store a real number
38
in the range {[}0,1{]}. It is a 32 bit unsigned integer and its
39
value is interpreted as $\frac{x}{MAX\_ BANDWIDTH}$.
40
 
41
\item
42
[task\_key\_t]This is an integer type and it is used as an index
43
for task specific data (similar to POSIX's Thread Specific Data).
44
\end{description}
45
 
46
%----------------------------------------------------------------------------
47
\section{Descriptors}
48
%----------------------------------------------------------------------------
49
 
50
In this section we present all the descriptors defined in the
51
Generic Kernel. If not specified, these data structures are
52
defined in the \texttt{include/kernel/descr.h} file and they are
53
used (usually as arrays) in the \texttt{kernel/kern.c} file.
54
 
55
%----------------------------------------------------------------------------
56
\subsection{Task Descriptor}
57
\label{KernSupport_Task_descriptor}
58
%----------------------------------------------------------------------------
59
 
60
The \texttt{proc\_des} structures used to define task control blocks
61
\footnote{The name of this structure is derived from the previous versions of
62
Hartik. However, it is a \textit{task} descriptor and not a \textit{process}
63
descriptor.}. In the following paragraphs the fields of the task descriptor are
64
described \footnote{The following fields have been removed from the structure in
65
the last releases: request\_time, priority, timespec\_priority, prev, next.}.
66
 
67
\begin{description}
68
\item [DWORD~task\_ID]Progressive number assigned to a task at its
69
creation.
70
 
71
\item [LEVEL~task\_level]This field points to the Module
72
that owns the task. The Generic kernel uses this field to redirect
73
the calls to the Module owning the task.
74
 
75
\item
76
[CONTEXT~context]This field contains an index in the OS Lib
77
context array that handles the context of a task.
78
 
79
\item
80
[BYTE~{*}stack]This field is a pointer to the memory used as a
81
task stack.
82
 
83
\item [TASK~(*body)()]This field is the pointer to
84
the first instruction of a task body, and it is used at
85
initialization time.
86
 
87
\item [char~name[MAX\_TASKNAME]]This is a
88
symbolic name, whose length is defined by the
89
\texttt{MAX\_TASKNAME} constant.
90
 
91
\item [WORD~status]This is the
92
task status.
93
 
94
\item [WORD~pclass]This field is the Class code of
95
the Task Model used during task creation. It can be used by
96
Modules to know the typology of the task (useful if the task
97
supports many types of Models; see
98
%
99
% Tool: such section does not exists.
100
%
101
%Section
102
%\ref{SchedModules_LevelCalls},
103
\texttt{level\_accept\_task\_model}
104
%function)
105
.
106
 
107
\item [WORD~group]This is the task group. The value 0
108
is used to index a single task. This field is not used as a GID in
109
classical Unix systems but is used to kill or activate a group of
110
tasks in an atomic way.
111
 
112
\item [WORD~stacksize]Stack dimension (in
113
bytes).
114
 
115
\item [DWORD~control]Task Status flags. A description of
116
the bits in this field is reported in
117
Section\ref{Modelli_TASK_MODEL}.
118
 
119
\item
120
[int~frozen\_activations]Number of frozen activations. Useful only
121
if the \texttt{FREEZE\_ACTIVATION} flag of the \texttt{control}
122
field is active (see Section \ref{Kernel_Attivazione}).
123
 
124
\item
125
[int~sigmask]This is the blocked signal task mask (see
126
\texttt{kernel/signal.c} and also \cite{POSIX1003.1}).
127
 
128
\item
129
[int~sigpending]This is the pending signal task mask (see
130
\texttt{kernel/signal.c} and also \cite{POSIX1003.1}).
131
 
132
\item
133
[int~sigwaiting]This is the mask of the signals on which a task is
134
waiting, blocked on a \texttt{sigwait} primitive (or similar).
135
 
136
\item [int~avail\_time]This field contains the remaining
137
computation time of a task (see Section
138
\ref{KernSupport_Capacita}).
139
 
140
\item [PID~shadow]This is the shadow
141
pointer (see Section \ref{oview_Shadows}).
142
 
143
\item
144
[struct~\_task\_handler\_rec~{*}cleanup\_stack]Pointer to the
145
first element of the cleanup stack.
146
 
147
\item [int~errnumber]This is
148
an error number local to the running task. The symbol
149
\texttt{errno} defined into the C standard is implemented as a
150
macro that refers to this field of the running task.
151
 
152
\item
153
[TIME~jet\_table{[}JET\_TABLE\_DIM{]}]This table contains the
154
computation times consumed by the last JET\_TABLE\_DIM instances
155
of the task. The table is handled as a circular buffer.
156
 
157
\item
158
[int~jet\_tvalid]This is the number of valid items in the
159
\texttt{jet\_table} table.
160
 
161
\item [int~jet\_curr]This is the
162
current element in the \texttt{jet\_table} table.
163
 
164
\item
165
[TIME~jet\_max]This field contains the maximum time (in
166
microseconds) consumed by a task, among all its instances.
167
 
168
\item
169
[TIME~jet\_sum]This field accumulates the execution times (in
170
microseconds) of all task instances from the start of the task (or
171
from the last call to \texttt{jet\_delstat}). This field, together
172
with the \texttt{jet\_n} field, is used to compute the mean
173
execution time of a task instance.
174
 
175
\item [TIME~jet\_n]This field contains the number of instances involved in the
176
computation of \texttt{jet\_sum}.
177
 
178
\item [PID~waiting\_for\_me]This field contains
179
the identifier of the task which is currently blocked for a
180
\texttt{task\_join} on the current task. The field value is NIL if
181
no task is blocked for a join on it.
182
 
183
\item
184
[void~{*}return\_value]This is the value returned by a task when
185
it dies. This value is memorized if the task is joinable, waiting
186
for someone to synchronize on it with a join.
187
 
188
\item
189
[void~{*}keys{[}PTHREAD\_KEYS\_MAX{]}]This array contains the task
190
specific data.
191
 
192
\item
193
[struct~condition\_struct~{*}cond\_waiting]This field is NULL or
194
it points to the condition variable on which the task is
195
blocked \footnote{This field is present because if a task is killed during
196
a block on a condition wait, the POSIX standard requires that the
197
task reacquires the mutex linked to that condition before it
198
dies.}.
199
 
200
\item [int~delay\_timer]This field is used in the
201
implementation of the blocking primitives with timeout. Usually
202
this field contains the OS Lib index of the event created for the
203
wake-up.
204
 
205
\item [int~wcet]This field can be used by Modules to
206
store some temporal information. It is generally used in
207
conjunction with the \texttt{avail\_time} field.
208
\end{description}
209
 
210
%----------------------------------------------------------------------------
211
\subsection{Level descriptor}
212
\label{KernSupport_Level_Descriptor}
213
%----------------------------------------------------------------------------
214
 
215
In this Section we describe the fields contained in the
216
\texttt{level\_des} structure, that implements the Scheduling
217
Module Descriptor. These Modules will fill the proposed interface,
218
defining also all the interface functions. If a Module does not
219
implement an interface function, it redefines that function in a
220
way that it will raise an exception if called. The fields defined
221
for the \texttt{level\_des} structure are the following:
222
 
223
\begin{description}
224
\item [Private~Functions,~Public~Functions]The rest of the interface is made of
225
a set of function pointers that implements the \emph{virtual} functions of the
226
Scheduling Modules. That functions are described in the Chapter
227
\ref{CapSchedulingModules}. All that functions have as first parameter a LEVEL
228
field that can be used to find the Module Descriptor and then the private
229
structures of that Modules \footnote{The behaviour of the LEVEL parameter passed
230
to that function is the same of the hidden paramether \emph{this} of many Object
231
Oriented languages.}.
232
\end{description}
233
 
234
%----------------------------------------------------------------------------
235
\subsection{Resource module descriptor}
236
\label{KernSupport_Descrittore_GestioneRisorse}
237
%----------------------------------------------------------------------------
238
 
239
In this Section we describe the fields contained in the
240
\texttt{resource\_des} structure, which implements the Resource
241
Module Descriptor. These Modules will fill the proposed interface,
242
defining all the required functions. If a Module does not
243
implement an interface function, it redefines that function in a
244
way that it will raise an exception if it is called. The fields
245
defined for the \texttt{resource\_des} structure are the
246
following:
247
 
248
\begin{description}
249
\item [char~res\_name{[}MAX\_MODULENAME{]}]This filed contains a
250
symbolic Name of the Module, for statistical purposes. The file
251
\texttt{include/modules/codes.h} contains the name of the Modules
252
distributed with the Kernel. \item [WORD~res\_code]This field
253
contains a numeric identifier that identifies a Module in an
254
unique way. The codes of the Modules distributed with the kernel
255
are written in the file \texttt{include/modules/codes.h}. \item
256
[BYTE~res\_version]This is a version number for the Module. The
257
version numbers of the Modules distributed with the Kernel are
258
reported in the file \texttt{include/modules/codes.h}. \item
259
[int~rtype]This field is used to identify the extended interface
260
implemented by a Resource Module. This field is necessary to
261
implement some primitives that use a particular extended
262
interface, that need to know which of the resource modules
263
registered in the kernel have a particular extension. \item
264
[Resource~Calls]The rest of the interface is made of a set of
265
function pointers that implement the \emph{virtual} functions of
266
the Resource Modules. These functions are described in Chapter
267
\ref{CapModuliRisorsa}. All these functions have as first
268
parameter a RLEVEL field that can be used as the similar parameter
269
of the Scheduling Module virtual functions.
270
\end{description}
271
 
272
%----------------------------------------------------------------------------
273
\section{System states}
274
%----------------------------------------------------------------------------
275
 
276
As mentioned in Section \ref{oview_Status} the concept of task
277
state has a local meaning, and it is stored in the \texttt{status}
278
field of its task descriptor.
279
 
280
The values that the status field can have are divided in four
281
intervals, described in Table \ref{KernSupport_Tab_StatusCodes}.
282
 
283
\begin{table}
284
\begin{center}
285
\begin{tabular}{|p{4cm}|p{9cm}|}
286
\hline
287
Interval reserved to & Codes\\ \hline \hline
288
 
289
Generic Kernel & {[}0...\texttt{MODULE\_STATUS\_BASE}-1{]} \\ \hline
290
Scheduling Algorithm \foreignlanguage{english}{} & {[}\texttt{MODULE\_STATUS\_BASE}
291
...\texttt{APER\_STATUS\_BASE}-1{]}\\ \hline
292
 
293
Aperiodic Servers \foreignlanguage{english}{} & {[}\texttt{APER\_STATUS\_BASE}
294
...\texttt{LIB\_STATUS\_BASE}-1{]}\\ \hline
295
 
296
Others (Resource Handling, libraries, etc.) \foreignlanguage{english}{} &
297
\texttt{>= LIB\_STATUS\_BASE}\\ \hline
298
\end{tabular}
299
\end{center}
300
\caption{Partitioning of the codes for the status field of the task descriptor.}
301
\label{KernSupport_Tab_StatusCodes}
302
\end{table}
303
 
304
Each Module Should use the codes in the correct range of values.
305
 
306
This approach allows to handle many Module configurations. The
307
fact that two Scheduling Modules use the same status code for
308
different meanings is not a problem, because the codes are used
309
internally to the Modules.
310
 
311
%----------------------------------------------------------------------------
312
\section{Kernel Global Variables}
313
\label{KernSupport_Variabili}
314
%----------------------------------------------------------------------------
315
 
316
The following global variables are defined in the Generic Kernel
317
and can be used by the Modules.
318
 
319
\begin{description}
320
 
321
\item [proc\_des~proc\_table{[}{]}]This variable is the task descriptor array.
322
Not all the entries of this array are used. The descriptor really allocated are
323
handled by the \texttt{task\_create} primitive.
324
 
325
\item [level\_des~{*}level\_table{[}{]}]This variable is the array that
326
memorizes a set of \emph{pointers} to the Scheduling Modules
327
Descriptors. When a Module registers itself into the Kernel, an
328
entry of this array is allocated, and it points to an
329
\emph{extension} of the \texttt{level\_des} descriptor type. In an
330
object oriented interpretation it can be thought as a polymorphic
331
Module array (see Section \ref{Modelli_MetodologiaOOP}).
332
 
333
\item [resource\_des~{*}resource\_table{[}{]}]This variable memorizes an
334
array of pointers to extension of the resource\_des structure. For
335
this variable the same comments for the level\_table apply.
336
 
337
\item [PID~exec]This variable contains the task returned by the
338
Scheduling Module scheduling operation. Typically this variable is
339
used only into the \texttt{scheduler()} function of the Generic
340
Kernel. This variable cannot be modified, it can only be read and
341
checked with the field \texttt{exec\_shadow}. This variable has
342
the value \texttt{NIL} (-1) when a primitive blocks the running
343
task, and the scheduler is not yet called. This variable
344
\emph{does not} point to the running task. Use
345
\texttt{exec\_shadow} instead!
346
 
347
\item [PID~exec\_shadow]This variable points to the running task. It can be
348
different from the value contained into \texttt{exec} because of the Shadow
349
mechanism (see Section \ref{oview_Shadows}). This variable cannot be modified,
350
it can only be read and check with the field \texttt{exec}. This variable has
351
the value \texttt{NIL} (-1) when a primitive blocks the running task, and the
352
scheduler is not yet called. When a reference to the running task is needed,
353
this variable has to be used.
354
 
355
\item [int~cap\_timer]This variable is different from -1 only if the Generic
356
Kernel or a Module created a capacity event. This variable can be used by the
357
Scheduling Modules that do not utilize the \texttt{CONTROL\_CAP flag} for their
358
tasks (see Section \ref{KernSupport_Capacita}).
359
 
360
\item [struct~timespec~schedule\_time]This variable contains the system time in
361
which the scheduler was called the last time. The first thing the Kernel
362
function \texttt{scheduler()} does is the setting of that variable. This
363
variable is also used as finish time for an execution time interval.
364
 
365
\item [struct~timespec~cap\_lasttime]This variable is a copy of the
366
\texttt{schedule\_time} variable, done at each call of the \texttt{scheduler()}
367
function. The value of that variable is used as the start time of the last
368
interval executed by a task. It is used to implement the time accounting.
369
 
370
\item [DWORD~res\_levels]This variable is the number of resource
371
module level descriptors allocated. It is modified only by the
372
\texttt{resource\_alloc\_descriptor} function
373
%
374
% Tool: such section does not exists.
375
%
376
% (see Section \ref{SchedModules_RegFunctions})
377
.
378
 
379
\item [int~task\_counter]This variable is a variable that counts the number of
380
User tasks actually present into the system (see Section
381
\ref{Kernel_Inizializzazione}).
382
 
383
\item [int~system\_counter]This
384
variable is a variable that counts the number of System tasks
385
actually present into the system (see Section
386
\ref{Kernel_Inizializzazione}).
387
 
388
%
389
% Tool: no more sys_end nor sys_abort. Check this in the code!
390
%
391
% \item [int~mustexit]This variable
392
% is used by the system primitives \texttt{sys\_end} and
393
% \texttt{sys\_abort} to block the context changes into the event
394
% handlers.
395
 
396
\item [int~calling\_runlevel\_func]This variable is a
397
flag. It is set to 1 when the system executes some system
398
functions (registered through the \texttt{sys\_atrunlevel()}
399
function). This flag influence the \texttt{task\_activate}
400
primitive, because that primitive has to do different stuffs
401
depending on the value of that variable (see the code of the
402
primitive in the file \texttt{kernel/activate.c}).
403
 
404
\item
405
[IQUEUE~freedesc]This variable is the free task descriptor queue.
406
It is handled by the Kernel and must be used by a Scheduling
407
Module into the call \texttt{task\_end} call to free a task
408
descriptor of a task terminated correctly.
409
 
410
\item
411
[TIME~sys\_tick]If the OS Lib is initialized with the \textit{one
412
shot timer} the variable contains the system tick (in
413
microseconds). Otherwise, the one-shot timer is used, and this
414
variable has a value of \texttt{0}.
415
\end{description}
416
 
417
%----------------------------------------------------------------------------
418
\section{Temporal protection}
419
\label{KernSupport_Capacita}
420
%----------------------------------------------------------------------------
421
 
422
The Generic Kernel supports task temporal protection through a set
423
of procedures and data structures that may be used by the
424
Scheduling Modules. The generic Kernel does force to use its own
425
functions, so a Module can define itself a policy to ensure
426
temporal protection. In this Section the proposed functions to
427
implement the temporal protection are described.
428
 
429
The Generic Kernel handles the time capacity of the tasks in the
430
system using the creation and the deletion of a specific OS Lib
431
event that simply reschedules the system. The end of the capacity
432
is seen by the Modules as a normal epilogue done in the case of a
433
preemption.
434
 
435
The timer event is created when a task is dispatched, and it is
436
deleted by all the primitives that may cause preemption. In an
437
instant there is at least one capacity event pending, that is the
438
event of the running task.
439
 
440
The Generic Kernel defines for each task the bit
441
\texttt{CONTROL\_CAP} that is memorized into the field
442
\texttt{control} of the task descriptor. That bit is set by the
443
Scheduling Modules to require for a task the creation of the
444
capacity event at dispatch time.
445
 
446
The Scheduling Modules have also to check the capacity exhaustion
447
each time a task is descheduled.
448
 
449
Capacities are handled using the following variables provided by
450
the Kernel:
451
 
452
\begin{itemize}
453
 
454
\item The \texttt{wcet} field of the task descriptor usually memorizes a
455
characteristic time for a task (i.e., it is used to store a worst-case execution
456
time or a mean execution time). It is included in the task descriptor to avoid
457
the allocation of such an information for all the modules. It is \emph{not} used
458
by the Generic Kernel.
459
 
460
\item The \texttt{avail\_time} field of the task descriptor is used to handle
461
the available execution time for a task. The capacity event generated by the
462
Generic Kernel at dispatch time has an activation time that is equal to
463
\texttt{schedule\_time + avail\_time}. The field is updated by the generic
464
kernel each time a task is descheduled, decrementing the slice just executed by
465
the task.
466
 
467
\item The \texttt{cap\_timer} field is used by the Generic Kernel to know
468
whether a capacity event is or not pending. If the field is equal to -1, there
469
are no events, otherwise the value is the index of the capacity event. If the
470
field is not equal to -1 the Generic kernel will delete automatically the event
471
each time the system is rescheduled. The Generic Kernel does not check who has
472
created the event pointed by \texttt{cap\_timer}, so a Scheduling Module that
473
not use the flag \texttt{CONTROL\_CAP} can create a capacity event and put his
474
index into \texttt{cap\_timer}, avoiding the removal of the event directly in
475
the code of the Module.
476
 
477
\item The \texttt{cap\_lasttime} field contains the time of the previous
478
reschedule of the system. The accounting of the computation times is done from
479
the difference between \texttt{schedule\_time} and \texttt{cap\_lasttime}. The
480
time used by the Kernel primitives is accounted in the running task.
481
 
482
\end{itemize}
483
 
484
The functions called by the capacity event have only to reschedule
485
the system. The Scheduling Modules that have to generate
486
themselves the capacity event can store their events in the
487
\texttt{cap\_timer} filed if they want an event to be removed at
488
each preemption. The events can call the Generic Kernel Function
489
called \texttt{capacity\_timer} (it does not accept any
490
parameter).
491
 
492
%----------------------------------------------------------------------------
493
\subsection{Negative capacities}
494
%----------------------------------------------------------------------------
495
 
496
The contents of the \texttt{avail\_time} field can be negative.
497
This fact, theoretically impossible, can happen for two reasons:
498
 
499
\begin{itemize}
500
\item first, the OS LIb event handler can not guarantee the
501
delivery of a capacity event at exact time (a small delay of some
502
microseconds may occur). So, a capacity event may be delivered
503
after the capacity is exhausted, so that the task capacity becomes
504
negative. We can suppose that negatives values are smaller than
505
the usual time for the tasks; \item second, because the shadow
506
mechanism can execute a task that has finished his budget; that
507
task will not be descheduled until the shadow of the higher
508
priority task points to it. This behavior is correct because we
509
want that the blocking task will ends its critical section to
510
limit the blocking time of the higher priority tasks. This
511
approach is supported by some theoretical results (see
512
\cite{Gha95}).
513
\end{itemize}
514
 
515
Scheduling modules can use two strategies to cope with the problem
516
given by negative capacities.
517
 
518
The first solution is to recharges the capacity with an amount
519
equal to $Q_{s}$; if the capacity is still negative, the task will
520
{}``loose a turn''. This solution is good for algorithms that
521
provide a periodic replenishment (like for example Round Robin,
522
Polling Server or Deferrable Server) but not for algorithms like
523
Sporadic Server or Constant Bandwidth Server, where the
524
replenishment is due to the capacity usage (in these algorithms
525
the server would not become active).
526
 
527
The second solution is to replenish the budget up to $Q_{s}$; this
528
solution is good for all types of algorithms, but we have to
529
consider that the server utilization factor becomes
530
$\frac{Q_{s}+\Delta}{T_{s}}$.
531
 
532
%----------------------------------------------------------------------------
533
\section{Utility functions}
534
%----------------------------------------------------------------------------
535
 
536
This section contains a set of utility functions that can be used
537
to simplify the writing of the Modules. Often these functions are
538
simple redefinitions of the OS Lib functions. Use these functions
539
instead of those provided by the OS Lib.
540
 
541
%----------------------------------------------------------------------------
542
\subsection{Event Handling}
543
\label{KernSupport_GestioneEventi}
544
%----------------------------------------------------------------------------
545
 
546
The Generic Kernel uses the Generic kernel event handling provided
547
by the OS Lib. The following functions should be used (see
548
\texttt{include/kernel/func.h}):
549
 
550
\begin{itemize}
551
\item \texttt{kern\_event\_post} can be used to post an event. The
552
redefinition adds a check on the index, raising an exception if
553
the OS Lib event queue is full. \item \texttt{kern\_event\_delete}
554
can be used to remove an OSLIB event. The unique parameter of the
555
funcion is the eveni ID returned by the kern\_event\_post
556
function. \item \texttt{event\_need\_reschedule}, with no
557
parameters. It has to be called into the event handlers that have
558
to reschedule the system. The Modules never have to call the
559
schedule function into event handlers.
560
\end{itemize}
561
 
562
%----------------------------------------------------------------------------
563
\subsection{Exception Handling}
564
%----------------------------------------------------------------------------
565
 
566
The Generic Kernel exception handling is based on the real-time
567
signal interface of the POSIX standard. In particular, the
568
exceptions are implemented with the signal number 9, SIGHEXC, that
569
typically writes a message to the console and ends the system.
570
 
571
The function to use to raise an exception is: \begin{center}
572
\fbox{\tt{ void kern\_raise(int n, PID p); }} \end{center}
573
 
574
As a result of this function call, a real-time signal is enqueued
575
into the system and the n parameter is passed into the field
576
\texttt{si\_value} of the structure \texttt{siginfo\_t} passed as
577
a parameter to the signal handler.
578
 
579
%----------------------------------------------------------------------------
580
\subsection{Memory Management}
581
\label{KernSupport_GestioneMemoria}
582
%----------------------------------------------------------------------------
583
 
584
The Generic kernel provides a memory allocator based on Flux
585
OS-Kit LMM\cite{Bry97}. The LMM is in the \texttt{kernel/mem}
586
directory; the functions defined in this subsection are in the
587
file \texttt{kernel/mem.c}. These functions must be called with
588
interrupt disabled.
589
 
590
The allocator divides the memory into three regions that can be
591
specified with some \#defines into the flag parameter of some
592
functions:
593
 
594
\begin{itemize}
595
\item Memory addresses below 1 Mb (flag field set to
596
\texttt{MEMORY\_UNDER\_1M}) \item Memory addresses from 1 Mb to 16
597
Mb (flag field set to \texttt{MEMORY\_FROM\_1M\_TO\_16M}) \item
598
Memory addresses below 16 Mb (flag field set to
599
\texttt{MEMORY\_UNDER\_16M}) \item Memory addresses over 16 Mb
600
(flag field set to \texttt{0})
601
\end{itemize}
602
 
603
Memory management functions are described below (see also Figure
604
\ref{KernSupport_mem_functions}):
605
 
606
\begin{figure}
607
\begin{center}
608
\begin{minipage}{6cm}
609
\begin{verbatim}
610
void *kern_alloc(DWORD s);
611
void *kern_alloc_aligned(size_t size, lmm_flags_t flags,
612
      int align_bits, DWORD align_ofs);
613
void *kern_alloc_gen(size_t size, lmm_flags_t flags,
614
      int align_bits, DWORD align_ofs,
615
      DWORD bounds_min, DWORD bounds_max);
616
void kern_free(void *block, size_t size);
617
void *kern_alloc_page(lmm_flags_t flags);
618
void kern_free_page(void *block);
619
void *DOS_alloc(DWORD size);
620
void DOS_free(void *ptr, DWORD size);
621
\end{verbatim}
622
\end{minipage}
623
\end{center}
624
\label{KernSupport_mem_functions}
625
\caption{Memory allocation functions.}
626
\end{figure}
627
 
628
\begin{description}
629
\item [\texttt{kern\_alloc}]This function allocates a memory block
630
of s bytes returning a \texttt{void~{*}}. All the addresses given
631
are supposed to be good for the block. The function returns
632
\texttt{NULL} if there is not a free memory block with the
633
required size. \item [\texttt{kern\_alloc\_aligned}]This functions
634
allocates an aligned memory block. The first \texttt{align\_bits}
635
of the block must be equal to the lowest \texttt{align\_bits} of
636
\texttt{align\_ofs}. In other words, \texttt{align\_bits}
637
specifies an alignment as a power of 2, whereas
638
\texttt{align\_ofs} is a natural offset. The function returns
639
\texttt{NULL} if there is not a block with the required
640
characteristics. \item [\texttt{kern\_alloc\_gen}]This function
641
allocates an aligned memory block in a way similar to
642
\texttt{kern\_alloc\_aligned}, with the additional condition that
643
the block must be found within the addresses \texttt{bounds\_min}
644
and \texttt{bounds\_max}. \item [\texttt{kern\_free}]This function
645
will free a block allocated with one of the previous functions.
646
Note that this function requires the dimension of the block to
647
allocate. \item [\texttt{kern\_alloc\_page}]This function
648
allocates an aligned page of memory (4 Kb). \item
649
[\texttt{kern\_free\_page}]This function frees a page allocated
650
with the \texttt{kern\_alloc\_page} function. \item
651
[\texttt{DOS\_alloc,~DOS\_free}]These functions allocate memory
652
under the first Mb.
653
\end{description}
654
 
655
%----------------------------------------------------------------------------
656
\subsection{Context switch}
657
%----------------------------------------------------------------------------
658
 
659
The creation and the deletion of a context in the Generic Kernel
660
is made using the OS Lib functions, properly renamed into
661
\texttt{kern\_context\_create} and \texttt{kern\_context\_delete}.
662
 
663
To change context, the Generic Kernel provides two functions,
664
\texttt{kern\_context\_save} and \texttt{kern\_context\_load}.
665
First function can be used to start a kernel primitive (disabling
666
interrupts, whereas the second can be used to enable the
667
interrupts, change the context using the OS Lib functions,
668
dispatch pending signals and test for asynchronous cancellation.
669
Note that currently the kernel primitives run on the same stack of
670
the caller thread, and the primitives are simply called disabling
671
the interrupts.
672
 
673
These functions must never be called into the standard interface
674
of the scheduling modules. When a OS Lib event need to reschedule
675
the system because there is a preemption, the function
676
\texttt{event\_need\_reschedule} must be called instead.
677
 
678
The functions described in this paragraph are into the
679
\texttt{include/kernel/func.h} file.
680
 
681
%----------------------------------------------------------------------------
682
\subsection{Queues, arrays and pointers}
683
\label{KernSupport_Code}
684
%----------------------------------------------------------------------------
685
 
686
To simplify the use of the internal Kernel references, the
687
following approach is used:
688
 
689
\begin{itemize}
690
\item Whenever possible, the descriptor arrays are statically
691
allocated. \item Each descriptor is identified by an integer which
692
represents the index in the descriptor array (e.g. PID, LEVEL,
693
RLEVEL).
694
\end{itemize}
695
 
696
To handle task queues, the Generic Kernel provides some utility
697
functions which can speed up the Module writing; however a module
698
can use its own functions to enqueue tasks.
699
 
700
The implemented functions do not use any fields of the task
701
descriptor; they are implemented with a double linked list. The
702
prototypes of the functions for queue management are shown in
703
Figure \ref{KernSupport_queue_functions}. They are into the file
704
\texttt{kernel/iqueue.c}, and \texttt{include/kernel/iqueue.h},
705
described below.
706
 
707
\begin{figure}
708
\texttt{\#define IQUEUE\_NO\_PRIORITY 1}
709
\texttt{\#define IQUEUE\_NO\_TIMESPEC 2}
710
\texttt{struct IQUEUE\_shared \{ }
711
\texttt{~~PID prev{[}MAX\_PROC{]}; }
712
\texttt{~~PID next{[}MAX\_PROC{]}; }
713
\texttt{~~struct timespec {*}timespec\_priority; }
714
\texttt{~~DWORD {*}priority; }
715
\texttt{\};}
716
\texttt{typedef struct \{ }
717
\texttt{~~PID first; }
718
\texttt{~~PID last; }
719
\texttt{~~struct IQUEUE\_shared {*}s; }
720
\texttt{\} IQUEUE; }
721
\texttt{~}
722
\texttt{void iq\_init (IQUEUE {*}q, IQUEUE {*}share, int flags);}
723
\texttt{void iq\_priority\_insert (PID p, IQUEUE {*}q); }
724
\texttt{void iq\_timespec\_insert (PID p, IQUEUE {*}q); }
725
\texttt{void iq\_insertfirst (PID p, IQUEUE {*}q); }
726
\texttt{void iq\_insertlast (PID p, IQUEUE {*}q);}
727
\texttt{void iq\_extract (PID p, IQUEUE {*}q); }
728
\texttt{PID iq\_getfirst ( IQUEUE {*}q); }
729
\texttt{PID iq\_getlast ( IQUEUE {*}q); }
730
\texttt{PID iq\_query\_first(IQUEUE {*}q);}
731
\texttt{PID iq\_query\_last(IQUEUE {*}q);}
732
\texttt{struct timespec {*}iq\_query\_timespec(PID p, IQUEUE
733
{*}q);}
734
\texttt{DWORD {*}iq\_query\_priority (PID p, IQUEUE {*}q);}
735
\texttt{PID iq\_query\_next (PID p, IQUEUE {*}q);}
736
\texttt{PID iq\_query\_prev (PID p, IQUEUE {*}q);}
737
\texttt{int iq\_isempty (IQUEUE {*}q);}
738
\caption{Prototypes of the task queue handling functions.}
739
\label{KernSupport_queue_functions}
740
\end{figure}
741
 
742
 
743
Basically, an IQUEUE has an \char`\"{}I\char`\"{}nternal prev/next
744
structure, that may be shared between one or more queue. Of
745
course, the user MUST guarantee that the same task will not be
746
inserted in two IQUEUEs that share the same prev/next buffer.
747
 
748
Internal queue initialization:
749
 
750
\begin{description}
751
\item [share~=~\&x]the internal data structure of the IQUEUE x is
752
used to enqueue the tasks. \item [\texttt{share~=~NULL}]an
753
internal data structure to handle prev/next pairs is dynamically
754
allocated (The amount of memory that is allocated can be reduced
755
using the flags). \item [flags]can be used to reduce the memory
756
usage of an IQUEUE when \texttt{share=NULL}:
757
 
758
\begin{description}
759
\item [\texttt{IQUEUE\_NO\_PRIORITY}]the iqueue do not provide
760
internally a priority field \item
761
[\texttt{IQUEUE\_NO\_TIMESPEC}]the iqueue do not provide
762
internally a timespec field
763
\end{description}
764
 
765
note that, if these flags are used, the corresponding insert
766
functions will not work!. The default value for the flags is, of
767
course, 0.
768
 
769
\end{description}
770
The queue insertion is made by the following functions:
771
 
772
\begin{description}
773
\item [iq\_insert]insertion based on the \texttt{priority} field.
774
\item [iq\_timespec\_insert]same as above but use the
775
\texttt{timespec\_priority} field \item [iq\_insertfirst]insert in
776
the first position of the queue \item [iq\_insertlast]insert in
777
the last position of the queue
778
\end{description}
779
 
780
The queue extraction functions: basically extracts a task p from
781
the queue q. There are three versions of the function:
782
 
783
\begin{description}
784
\item [iq\_extract]extracts given a task p (that must be inserted
785
in the queue); \item [iq\_getfirst]extracts the first task in the
786
queue, NIL if the queue is empty; \item [iq\_getlast]extracts the
787
last task in the queue, NIL if the queue is empty;
788
\end{description}
789
 
790
Seven queue query functions are also provided. The first two
791
functions (query first/last) return the first and the last task in
792
the queue, NIL if the queue is empty. The second two functions
793
(query priority/timespec) can be used to get/set the priority or
794
the timespec field used when queuing. The third two functions
795
(query next/prev) can be used to scan the queue elements. The last
796
function can be used to test if a queue is empty.
797
 
798
%----------------------------------------------------------------------------
799
\subsection{Initialization functions}
800
%----------------------------------------------------------------------------
801
 
802
The Generic Kernel supports the specification of the functions to
803
be called at system initialization and termination (see Section
804
\ref{Kernel_Inizializzazione}). These functions can be registered
805
through the following system primitive:
806
 
807
\begin{center}
808
\fbox{\tt{
809
\texttt{int sys\_atrunlevel(void ({*}f)(void {*}),void {*}p, BYTE when);
810
}}}
811
\end{center}
812
 
813
The parameters for that function are:
814
 
815
\begin{description}
816
 
817
\item [\texttt{f}]the function to be registered;
818
 
819
\item [\texttt{p}]the parameter to be passed to function \texttt{f} when the
820
function will be called;
821
 
822
\item [\texttt{when}]is the situation in witch that function will be called. The
823
correct values are the following:
824
 
825
\begin{description}
826
 
827
\item [\texttt{RUNLEVEL\_INIT}]The function will be called after Module
828
registration, when the system is just entered in multitasking mode but no thread
829
executed yet;
830
 
831
\item [\texttt{RUNLEVEL\_SHUTDOWN}]The function will be called after a call to
832
\texttt{sys\_abort} or \texttt{sys\_end}; The system is still in multitasking
833
mode;
834
 
835
\item [\texttt{RUNLEVEL\_BEFORE\_EXIT}]The function will be called when the
836
Kernel exits from multitasking mode;
837
 
838
\item [\texttt{RUNLEVEL\_AFTER\_EXIT}]The function is called before the system
839
hangs (or returns to the host OS, if the proprietary extender is used).
840
 
841
\end{description}
842
 
843
It is also possible to specify with an OR operator a flag
844
\texttt{NO\_AT\_ABORT} that disables the call to the functions if
845
the system is exiting with a \texttt{sys\_abort} function.
846
\end{description}
847
 
848
You can post at most \texttt{MAX\_RUNLEVEL\_FUNC} functions.
849
 
850
%----------------------------------------------------------------------------
851
\subsection{Interrupt disabling, printf and system termination}
852
%----------------------------------------------------------------------------
853
 
854
The Generic Kernel redefines the following OS Lib functions (see
855
the \texttt{include/kernel/func.h} file):
856
 
857
\begin{description}
858
\item [\texttt{cli}]renamed in \texttt{kern\_cli} \item
859
[\texttt{sti}]renamed in \texttt{kern\_sti} \item
860
[\texttt{ll\_fsave}]renamed in \texttt{kern\_fsave} \item
861
[\texttt{ll\_frestore}]renamed in \texttt{kern\_frestore}.
862
\end{description}
863
 
864
To display some messages to the console, the Generic Kernel
865
provides two functions called \texttt{printk} and
866
\texttt{kern\_printf}. These functions are similar to the standard
867
C \texttt{printf} function, except that they write directly to the
868
console. The \texttt{printk} function allows to specify a kind of
869
``importance'' for the message that the function displays. For
870
more information look at the file \texttt{include/kernel/func.h}
871
and \texttt{include/kernel/log.h}.
872
 
873
Finally, a clean system termination can be obtained through the \texttt{exit}
874
primitive. For more information look at the file \texttt{include/kernel/func.h}
875
and read Section \ref{Kernel_Inizializzazione}.