1 |
28 |
unneback |
<!-- Copyright (C) 2003 Red Hat, Inc. -->
|
2 |
|
|
<!-- This material may be distributed only subject to the terms -->
|
3 |
|
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
4 |
|
|
<!-- or later (the latest version is presently available at -->
|
5 |
|
|
<!-- http://www.opencontent.org/openpub/). -->
|
6 |
|
|
<!-- Distribution of the work or derivative of the work in any -->
|
7 |
|
|
<!-- standard (paper) book form is prohibited unless prior -->
|
8 |
|
|
<!-- permission is obtained from the copyright holder. -->
|
9 |
|
|
<HTML
|
10 |
|
|
><HEAD
|
11 |
|
|
><TITLE
|
12 |
|
|
>Degrees of Configurability</TITLE
|
13 |
|
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
14 |
|
|
<META
|
15 |
|
|
NAME="GENERATOR"
|
16 |
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
17 |
|
|
"><LINK
|
18 |
|
|
REL="HOME"
|
19 |
|
|
TITLE="The eCos Component Writer's Guide"
|
20 |
|
|
HREF="cdl-guide.html"><LINK
|
21 |
|
|
REL="UP"
|
22 |
|
|
TITLE="Overview"
|
23 |
|
|
HREF="overview.html"><LINK
|
24 |
|
|
REL="PREVIOUS"
|
25 |
|
|
TITLE="Approaches to Configurability"
|
26 |
|
|
HREF="overview.approaches.html"><LINK
|
27 |
|
|
REL="NEXT"
|
28 |
|
|
TITLE="Warnings"
|
29 |
|
|
HREF="overview.warning.html"></HEAD
|
30 |
|
|
><BODY
|
31 |
|
|
CLASS="SECT1"
|
32 |
|
|
BGCOLOR="#FFFFFF"
|
33 |
|
|
TEXT="#000000"
|
34 |
|
|
LINK="#0000FF"
|
35 |
|
|
VLINK="#840084"
|
36 |
|
|
ALINK="#0000FF"
|
37 |
|
|
><DIV
|
38 |
|
|
CLASS="NAVHEADER"
|
39 |
|
|
><TABLE
|
40 |
|
|
SUMMARY="Header navigation table"
|
41 |
|
|
WIDTH="100%"
|
42 |
|
|
BORDER="0"
|
43 |
|
|
CELLPADDING="0"
|
44 |
|
|
CELLSPACING="0"
|
45 |
|
|
><TR
|
46 |
|
|
><TH
|
47 |
|
|
COLSPAN="3"
|
48 |
|
|
ALIGN="center"
|
49 |
|
|
>The <SPAN
|
50 |
|
|
CLASS="APPLICATION"
|
51 |
|
|
>eCos</SPAN
|
52 |
|
|
> Component Writer's Guide</TH
|
53 |
|
|
></TR
|
54 |
|
|
><TR
|
55 |
|
|
><TD
|
56 |
|
|
WIDTH="10%"
|
57 |
|
|
ALIGN="left"
|
58 |
|
|
VALIGN="bottom"
|
59 |
|
|
><A
|
60 |
|
|
HREF="overview.approaches.html"
|
61 |
|
|
ACCESSKEY="P"
|
62 |
|
|
>Prev</A
|
63 |
|
|
></TD
|
64 |
|
|
><TD
|
65 |
|
|
WIDTH="80%"
|
66 |
|
|
ALIGN="center"
|
67 |
|
|
VALIGN="bottom"
|
68 |
|
|
>Chapter 1. Overview</TD
|
69 |
|
|
><TD
|
70 |
|
|
WIDTH="10%"
|
71 |
|
|
ALIGN="right"
|
72 |
|
|
VALIGN="bottom"
|
73 |
|
|
><A
|
74 |
|
|
HREF="overview.warning.html"
|
75 |
|
|
ACCESSKEY="N"
|
76 |
|
|
>Next</A
|
77 |
|
|
></TD
|
78 |
|
|
></TR
|
79 |
|
|
></TABLE
|
80 |
|
|
><HR
|
81 |
|
|
ALIGN="LEFT"
|
82 |
|
|
WIDTH="100%"></DIV
|
83 |
|
|
><DIV
|
84 |
|
|
CLASS="SECT1"
|
85 |
|
|
><H1
|
86 |
|
|
CLASS="SECT1"
|
87 |
|
|
><A
|
88 |
|
|
NAME="OVERVIEW.DEGRESS">Degrees of Configurability</H1
|
89 |
|
|
><P
|
90 |
|
|
>Components can support configurability in varying degrees. It is not
|
91 |
|
|
necessary to have any configuration options at all, and the only user
|
92 |
|
|
choice is whether or not to load a particular package. Alternatively
|
93 |
|
|
it is possible to implement highly-configurable code. As an example
|
94 |
|
|
consider a typical facility that is provided by many real-time
|
95 |
|
|
kernels, mutex locks. The possible configuration options include:</P
|
96 |
|
|
><P
|
97 |
|
|
></P
|
98 |
|
|
><OL
|
99 |
|
|
TYPE="1"
|
100 |
|
|
><LI
|
101 |
|
|
><P
|
102 |
|
|
>If no part of the application and no other component requires mutexes
|
103 |
|
|
then there is no point in having the mutex code compiled into a
|
104 |
|
|
library at all. This saves having to compile the code. In addition
|
105 |
|
|
there will never be any need for the user to configure the detailed
|
106 |
|
|
behavior of mutexes. Therefore the presence of mutexes is a
|
107 |
|
|
configuration option in itself.</P
|
108 |
|
|
></LI
|
109 |
|
|
><LI
|
110 |
|
|
><P
|
111 |
|
|
>Even if the application does make use of mutexes directly or
|
112 |
|
|
indirectly, this does not mean that all mutex functions have to be
|
113 |
|
|
included. The minimum functionality consists of lock and unlock
|
114 |
|
|
functions. However there are variants of the locking primitive such as
|
115 |
|
|
try-lock and try-with-timeout which may or may not be needed.</P
|
116 |
|
|
><P
|
117 |
|
|
>Generally it will be harmless to compile the try-lock function even if
|
118 |
|
|
it is not actually required, because the function will get eliminated
|
119 |
|
|
at link-time. Some users might take the view that the try-lock
|
120 |
|
|
function should never get compiled in unless it is actually needed, to
|
121 |
|
|
reduce compile-time and disk usage. Other users might argue that there
|
122 |
|
|
are very few valid uses for a try-lock function and it should not be
|
123 |
|
|
compiled by default to discourage incorrect uses. The presence of a
|
124 |
|
|
try-lock function is a possible configuration option, although it may
|
125 |
|
|
be sensible to default it to true.</P
|
126 |
|
|
><P
|
127 |
|
|
>The try-with-timeout variant is more complicated because it adds a
|
128 |
|
|
dependency: the mutex code will now rely on some other component to
|
129 |
|
|
provide a timer facility. To make things worse the presence of this
|
130 |
|
|
timer might impact other components, for example it may now be
|
131 |
|
|
necessary to guard against timer interrupts, and thus have an
|
132 |
|
|
insidious effect on code size. The presence of a lock-with-timeout
|
133 |
|
|
function is clearly a sensible configuration option, but the default
|
134 |
|
|
value is less obvious. If the option is enabled by default then the
|
135 |
|
|
final application image may end up with code that is not actually
|
136 |
|
|
essential. If the option is disabled by default then users will have
|
137 |
|
|
to enable the option somehow in order to use the function, implying
|
138 |
|
|
more effort on the part of the user. One possible approach is to
|
139 |
|
|
calculate the default value based on whether or not a timer component
|
140 |
|
|
is present anyway.</P
|
141 |
|
|
></LI
|
142 |
|
|
><LI
|
143 |
|
|
><P
|
144 |
|
|
>The application may or may not require the ability to create and
|
145 |
|
|
destroy mutexes dynamically. For most embedded systems it is both less
|
146 |
|
|
error-prone and more efficient to create objects like mutexes
|
147 |
|
|
statically. Dynamic creation of mutexes can be implemented using a
|
148 |
|
|
pre-allocated pool of mutex objects, involving some extra code to
|
149 |
|
|
manipulate the pool and an additional configuration option to define
|
150 |
|
|
the size of the pool. Alternatively it can be implemented using a
|
151 |
|
|
general-purpose memory allocator, involving quite a lot of extra code
|
152 |
|
|
and configuration options. However this general-purpose memory
|
153 |
|
|
allocator may be present anyway to support the application itself or
|
154 |
|
|
some other component. The ability to create and destroy mutexes
|
155 |
|
|
dynamically is a configuration option, and there may not be a sensible
|
156 |
|
|
default that is appropriate for all applications.</P
|
157 |
|
|
></LI
|
158 |
|
|
><LI
|
159 |
|
|
><P
|
160 |
|
|
>An important issue for mutex locks is the handling of priority
|
161 |
|
|
inversion, where a high priority thread is prevented from running
|
162 |
|
|
because it needs a lock owned by a lower priority thread. This is only
|
163 |
|
|
an issue if there is a scheduler with multiple priorities: some
|
164 |
|
|
systems may need multi-threading and hence synchronization primitives,
|
165 |
|
|
but a single priority level may suffice. If priority inversion is a
|
166 |
|
|
theoretical possibility then the application developer may still want
|
167 |
|
|
to ignore it because the application has been designed such that the
|
168 |
|
|
problem cannot arise in practice. Alternatively the developer may want
|
169 |
|
|
some sort of exception raised if priority inversion does occur,
|
170 |
|
|
because it should not happen but there may still be bugs in the code.
|
171 |
|
|
If priority inversion can occur legally then there are three main ways
|
172 |
|
|
of handling it: priority ceilings, priority inheritance, and ignoring
|
173 |
|
|
the problem. Priority ceilings require little code but extra effort on
|
174 |
|
|
the part of the application developer. Priority inheritance requires
|
175 |
|
|
more code but is automatic. Ignoring priority inversion may or may not
|
176 |
|
|
be acceptable, depending on the application and exactly when priority
|
177 |
|
|
inversion can occur. Some of these choices involve additional
|
178 |
|
|
configuration options, for example there are different ways of raising
|
179 |
|
|
an exception, and priority inheritance may or may not be applied
|
180 |
|
|
recursively.</P
|
181 |
|
|
></LI
|
182 |
|
|
><LI
|
183 |
|
|
><P
|
184 |
|
|
>As a further complication some mutexes may be hidden inside a
|
185 |
|
|
component rather than being an explicit part of the application. For
|
186 |
|
|
example, if the C library is configured to provide a
|
187 |
|
|
<TT
|
188 |
|
|
CLASS="FUNCTION"
|
189 |
|
|
>malloc</TT
|
190 |
|
|
> call then there may be an associated mutex
|
191 |
|
|
to make the function automatically thread-safe, with no need for
|
192 |
|
|
external locking. In such cases the memory allocation component of the
|
193 |
|
|
C library can impose a constraint on the kernel, requiring that
|
194 |
|
|
mutexes be provided. If the user attempts to disable mutexes anyway
|
195 |
|
|
then the configuration tools will report a conflict.</P
|
196 |
|
|
></LI
|
197 |
|
|
><LI
|
198 |
|
|
><P
|
199 |
|
|
>The mutex code should contain some general debugging code such as
|
200 |
|
|
assertions and tracing. Usually such debug support will be enabled or
|
201 |
|
|
disabled at a coarse level such as the entire system or everything
|
202 |
|
|
inside the kernel, but sometimes it will be desirable to enable the
|
203 |
|
|
support more selectively. One reason would be memory requirements: the
|
204 |
|
|
target may not have enough memory to hold the system if all debugging
|
205 |
|
|
is enabled. Another reason is if most of the system is working but
|
206 |
|
|
there are a few problems still to resolved; enabling debugging in the
|
207 |
|
|
entire system might change the system's timing behavior too much, but
|
208 |
|
|
enabling some debug options selectively can still be useful. There
|
209 |
|
|
should be configuration options to allow specific types of debugging
|
210 |
|
|
to be enabled at a fine-grain, but with default settings inherited
|
211 |
|
|
from an enclosing component or from global settings.</P
|
212 |
|
|
></LI
|
213 |
|
|
><LI
|
214 |
|
|
><P
|
215 |
|
|
>The mutex code may contain specialized code to interact
|
216 |
|
|
with a debugging tool running on the host. It should be
|
217 |
|
|
possible to enable or disable this debugging code, and there may
|
218 |
|
|
be additional configuration options controlling the detailed
|
219 |
|
|
behavior.</P
|
220 |
|
|
></LI
|
221 |
|
|
></OL
|
222 |
|
|
><P
|
223 |
|
|
>Altogether there may be something like ten to twenty configuration
|
224 |
|
|
options that are specific to the mutex code. There may be a similar
|
225 |
|
|
number of additional options related to assertions and other debug
|
226 |
|
|
facilities. All of the options should have sensible default values,
|
227 |
|
|
possibly fixed, possibly calculated depending on what is happening
|
228 |
|
|
elsewhere in the configuration. For example the default setting for
|
229 |
|
|
an assertion option should generally inherit from a kernel-wide
|
230 |
|
|
assertion control option, which in turn inherits from a global option.
|
231 |
|
|
This allows users to enable or disable assertions globally or at
|
232 |
|
|
a more fine-grained level, as desired.</P
|
233 |
|
|
><P
|
234 |
|
|
>Different components may be configurable to different degrees, ranging
|
235 |
|
|
from no options at all to the fine-grained configurability of the
|
236 |
|
|
above mutex example (or possibly even further). It is up to component
|
237 |
|
|
writers to decide what options should be provided and how best to
|
238 |
|
|
serve the needs of application developers who want to use that
|
239 |
|
|
component.</P
|
240 |
|
|
></DIV
|
241 |
|
|
><DIV
|
242 |
|
|
CLASS="NAVFOOTER"
|
243 |
|
|
><HR
|
244 |
|
|
ALIGN="LEFT"
|
245 |
|
|
WIDTH="100%"><TABLE
|
246 |
|
|
SUMMARY="Footer navigation table"
|
247 |
|
|
WIDTH="100%"
|
248 |
|
|
BORDER="0"
|
249 |
|
|
CELLPADDING="0"
|
250 |
|
|
CELLSPACING="0"
|
251 |
|
|
><TR
|
252 |
|
|
><TD
|
253 |
|
|
WIDTH="33%"
|
254 |
|
|
ALIGN="left"
|
255 |
|
|
VALIGN="top"
|
256 |
|
|
><A
|
257 |
|
|
HREF="overview.approaches.html"
|
258 |
|
|
ACCESSKEY="P"
|
259 |
|
|
>Prev</A
|
260 |
|
|
></TD
|
261 |
|
|
><TD
|
262 |
|
|
WIDTH="34%"
|
263 |
|
|
ALIGN="center"
|
264 |
|
|
VALIGN="top"
|
265 |
|
|
><A
|
266 |
|
|
HREF="cdl-guide.html"
|
267 |
|
|
ACCESSKEY="H"
|
268 |
|
|
>Home</A
|
269 |
|
|
></TD
|
270 |
|
|
><TD
|
271 |
|
|
WIDTH="33%"
|
272 |
|
|
ALIGN="right"
|
273 |
|
|
VALIGN="top"
|
274 |
|
|
><A
|
275 |
|
|
HREF="overview.warning.html"
|
276 |
|
|
ACCESSKEY="N"
|
277 |
|
|
>Next</A
|
278 |
|
|
></TD
|
279 |
|
|
></TR
|
280 |
|
|
><TR
|
281 |
|
|
><TD
|
282 |
|
|
WIDTH="33%"
|
283 |
|
|
ALIGN="left"
|
284 |
|
|
VALIGN="top"
|
285 |
|
|
>Approaches to Configurability</TD
|
286 |
|
|
><TD
|
287 |
|
|
WIDTH="34%"
|
288 |
|
|
ALIGN="center"
|
289 |
|
|
VALIGN="top"
|
290 |
|
|
><A
|
291 |
|
|
HREF="overview.html"
|
292 |
|
|
ACCESSKEY="U"
|
293 |
|
|
>Up</A
|
294 |
|
|
></TD
|
295 |
|
|
><TD
|
296 |
|
|
WIDTH="33%"
|
297 |
|
|
ALIGN="right"
|
298 |
|
|
VALIGN="top"
|
299 |
|
|
>Warnings</TD
|
300 |
|
|
></TR
|
301 |
|
|
></TABLE
|
302 |
|
|
></DIV
|
303 |
|
|
></BODY
|
304 |
|
|
></HTML
|
305 |
|
|
>
|