1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
<!--
The FreeBSD Documentation Project
$FreeBSD: $
-->
<chapter id="sysinit">
<title>The Sysinit Framework</title>
<para>Sysinit is the framework for a generic call sort and dispatch
mechanisim. FreeBSD currently uses it for the dynamic
initialization of the kernel. Sysinit allows FreeBSD's kernel
subsystems to be reordered, and added, removed, and replaced at
kernel link time when the kernel or one of its modules is loaded
without having to edit a staticly ordered initilization routing
and recompile the kernel. This system also allows kernel modules,
currently called <firstterm>KLD's</firstterm>, to be seperatly
compiled, linked, and initilized at boot time and loaded even
later while the system is already running. This is accomplished
using the <quote>kernel linker</quote> and <quote>linker
sets</quote>.</para>
<sect1>
<title>Terminology</title>
<variablelist>
<varlistentry>
<term>Linker Set</term>
<listitem>
<para>A linker technique in which the linker gathers
staticly declared data throughout a program's source files
into a single contagiously addressable unit of
data.</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1>
<title>Sysinit Operation</title>
<para>Sysinit relies on the ability of the linker to take static
data declared at multiple locations throughout a program's
source and group it together as a single contagious chunk of
data. This linker technique is called a <quote>linker
set</quote>. Sysinit uses two linker sets to maintain two data
sets containing each consumer's call order, function, and a
pointer to the data to pass to taht function.</para>
<para>Sysinit uses two priorites when ordering the functions for
execution. The first priority is a subsystem ID giving an
overall order Sysinit's dispatch of funtions. Current predeclard
ID's are in <filename><sys/kernel.h></filename> in the enum
list <literal>sysinit_sub_id</literal>. The second priority used
is an element order within the subsystem. Current predeclard
subsystem element orders are in
<filename><sys/kernel.h></filename> in the enum list
<literal>sysinit_elem_order</literal>.</para>
<para>There are currently two uses for Sysinit. Function dispatch
at system startup and kernel module loads, and function dispatch
at system shutdown and kernel module unload.</para>
</sect1>
<sect1>
<title>Using Sysinit</title>
<sect2>
<title>Interface</title>
<sect3>
<title>Headers</title>
<programlisting><sys/kernel.h></programlisting>
</sect3>
<sect3>
<title>Macros</title>
<programlisting>SYSINIT(uniquifier, subsystem, order, func, ident)
SYSUNINIT(uniquifier, subsystem, order, func, ident)</programlisting>
</sect3>
</sect2>
<sect2>
<title>Startup</title>
<para>The <literal>SYSINIT()</literal> macro creates the
necessary sysinit data in Sysinit's startup data set for
Sysinit to sort and dispatch a function at system startup and
module load. <literal>SYSINIT()</literal> takes a uniquifier
that Sysinit uses identify the particular function dispatch
data, the subsystem order, the subsystem element order, the
function to call, and the data to pass the fuction. All
functions must take a constant pointer argument.
</para>
<para>For example:</para>
<programlisting>#include <sys/kernel.h>
void foo_null(void *unused)
{
foo_doo();
}
SYSINIT(foo_null, SI_SUB_FOO, SI_ORDER_FOO, NULL);
struct foo foo_voodoo = {
FOO_VOODOO;
}
void foo_arg(void *vdata)
{
struct foo *foo = (struct foo *)vdata;
foo_data(foo);
}
SYSINIT(foo_arg, SI_SUB_FOO, SI_ORDER_FOO, foo_voodoo);
</programlisting>
</sect2>
<sect2>
<title>Shutdown</title>
<para>The <literal>SYSUNINIT()</literal> macro behaves similarly
to the <literal>SYSINIT()</literal> macro except that it adds
the Sysinit data to Sysinit's shutdown data set.</para>
<para>For example:</para>
<programlisting>#include <sys/kernel.h>
void foo_cleanup(void *unused)
{
foo_kill();
}
SYSUNINIT(foo_cleanup, SI_SUB_FOO, SI_ORDER_FOO, NULL);
struct foo_stack foo_stack = {
FOO_STACK_VOODOO;
}
void foo_flush(void *vdata)
{
}
SYSUNINIT(foo_flush, SI_SUB_FOO, SI_ORDER_FOO, foo_stack);
</programlisting>
</sect2>
</sect1>
</chapter>
<!--
Local Variables:
mode: sgml
sgml-declaration: "../chapter.decl"
sgml-indent-data: t
sgml-omittag: nil
sgml-always-quote-attributes: t
sgml-parent-document: ("../book.sgml" "part" "chapter")
End:
-->
|