Deleted Added
full compact
kern_module.c (37555) kern_module.c (37629)
1/*-
2 * Copyright (c) 1997 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1997 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: kern_module.c,v 1.6 1997/11/07 08:52:56 phk Exp $
26 * $Id: kern_module.c,v 1.7 1998/07/11 07:45:40 bde Exp $
27 */
28
29#include <sys/param.h>
30#include <sys/kernel.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/sysproto.h>
34#include <sys/sysent.h>
35#include <sys/module.h>
36#include <sys/linker.h>
37#include <sys/proc.h>
38
39#define M_MODULE M_TEMP /* XXX */
40
41typedef TAILQ_HEAD(, module) modulelist_t;
42struct module {
43 TAILQ_ENTRY(module) link; /* chain together all modules */
44 TAILQ_ENTRY(module) flink; /* all modules in a file */
45 struct linker_file* file; /* file which contains this module */
46 int refs; /* reference count */
47 int id; /* unique id number */
48 char *name; /* module name */
49 modeventhand_t handler; /* event handler */
50 void *arg; /* argument for handler */
51};
52
53#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg)
54
55static modulelist_t modules;
56static int nextid = 1;
57
58static void module_shutdown(int, void*);
59
60static void
61module_init(void* arg)
62{
63 TAILQ_INIT(&modules);
64 at_shutdown(module_shutdown, 0, SHUTDOWN_POST_SYNC);
65}
66
67SYSINIT(module, SI_SUB_KMEM, SI_ORDER_ANY, module_init, 0);
68
69static void
70module_shutdown(int arg1, void* arg2)
71{
72 module_t mod;
73
74 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link))
75 MOD_EVENT(mod, MOD_SHUTDOWN);
76}
77
78void
79module_register_init(void *arg)
80{
81 moduledata_t* data = (moduledata_t*) arg;
82 int error;
83
27 */
28
29#include <sys/param.h>
30#include <sys/kernel.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/sysproto.h>
34#include <sys/sysent.h>
35#include <sys/module.h>
36#include <sys/linker.h>
37#include <sys/proc.h>
38
39#define M_MODULE M_TEMP /* XXX */
40
41typedef TAILQ_HEAD(, module) modulelist_t;
42struct module {
43 TAILQ_ENTRY(module) link; /* chain together all modules */
44 TAILQ_ENTRY(module) flink; /* all modules in a file */
45 struct linker_file* file; /* file which contains this module */
46 int refs; /* reference count */
47 int id; /* unique id number */
48 char *name; /* module name */
49 modeventhand_t handler; /* event handler */
50 void *arg; /* argument for handler */
51};
52
53#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg)
54
55static modulelist_t modules;
56static int nextid = 1;
57
58static void module_shutdown(int, void*);
59
60static void
61module_init(void* arg)
62{
63 TAILQ_INIT(&modules);
64 at_shutdown(module_shutdown, 0, SHUTDOWN_POST_SYNC);
65}
66
67SYSINIT(module, SI_SUB_KMEM, SI_ORDER_ANY, module_init, 0);
68
69static void
70module_shutdown(int arg1, void* arg2)
71{
72 module_t mod;
73
74 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link))
75 MOD_EVENT(mod, MOD_SHUTDOWN);
76}
77
78void
79module_register_init(void *arg)
80{
81 moduledata_t* data = (moduledata_t*) arg;
82 int error;
83
84#define fptrint_t unsigned /* XXX */
85 if (error = module_register(data->name, data->evhand, data->priv))
86 printf("module_register_init: module_register(%s, %lx, %p) returned %d",
84 if (error = module_register(data->name, data->evhand, data->priv))
85 printf("module_register_init: module_register(%s, %lx, %p) returned %d",
87 data->name, (u_long)(fptrint_t)data->evhand, data->priv, error);
86 data->name, (u_long)(uintfptr_t)data->evhand, data->priv, error);
88}
89
90int
91module_register(const char* name, modeventhand_t handler, void* arg)
92{
93 size_t namelen;
94 module_t newmod;
95 int error;
96
97 namelen = strlen(name) + 1;
98 newmod = (module_t) malloc(sizeof(struct module) + namelen,
99 M_MODULE, M_WAITOK);
100 if (newmod == 0)
101 return ENOMEM;
102
103 newmod->refs = 1;
104 newmod->id = nextid++;
105 newmod->name = (char *) (newmod + 1);
106 strcpy(newmod->name, name);
107 newmod->handler = handler;
108 newmod->arg = arg;
109 TAILQ_INSERT_TAIL(&modules, newmod, link);
110
111 if (linker_current_file) {
112 TAILQ_INSERT_TAIL(&linker_current_file->modules, newmod, flink);
113 newmod->file = linker_current_file;
114 } else
115 newmod->file = 0;
116
117 if (error = MOD_EVENT(newmod, MOD_LOAD)) {
118 module_release(newmod);
119 return error;
120 }
121
122 return 0;
123}
124
125void
126module_reference(module_t mod)
127{
128 MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
129
130 mod->refs++;
131}
132
133void
134module_release(module_t mod)
135{
136 if (mod->refs <= 0)
137 panic("module_release: bad reference count");
138
139 MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
140
141 mod->refs--;
142 if (mod->refs == 0) {
143 TAILQ_REMOVE(&modules, mod, link);
144 if (mod->file) {
145 TAILQ_REMOVE(&mod->file->modules, mod, flink);
146 }
147 free(mod, M_MODULE);
148 }
149}
150
151module_t
152module_lookupbyname(const char* name)
153{
154 module_t mod;
155
156 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
157 if (!strcmp(mod->name, name))
158 return mod;
159 }
160
161 return 0;
162}
163
164module_t
165module_lookupbyid(int modid)
166{
167 module_t mod;
168
169 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
170 if (mod->id == modid)
171 return mod;
172 }
173
174 return 0;
175}
176
177int
178module_unload(module_t mod)
179{
180 return MOD_EVENT(mod, MOD_UNLOAD);
181}
182
183int
184module_getid(module_t mod)
185{
186 return mod->id;
187}
188
189module_t
190module_getfnext(module_t mod)
191{
192 return TAILQ_NEXT(mod, flink);
193}
194
195/*
196 * Syscalls.
197 */
198int
199modnext(struct proc* p, struct modnext_args* uap)
200{
201 module_t mod;
202
203 p->p_retval[0] = -1;
204 if (SCARG(uap, modid) == 0) {
205 mod = TAILQ_FIRST(&modules);
206 if (mod) {
207 p->p_retval[0] = mod->id;
208 return 0;
209 } else
210 return ENOENT;
211 }
212
213 mod = module_lookupbyid(SCARG(uap, modid));
214 if (!mod)
215 return ENOENT;
216
217 if (TAILQ_NEXT(mod, link))
218 p->p_retval[0] = TAILQ_NEXT(mod, link)->id;
219 else
220 p->p_retval[0] = 0;
221 return 0;
222}
223
224int
225modfnext(struct proc* p, struct modfnext_args* uap)
226{
227 module_t mod;
228
229 p->p_retval[0] = -1;
230
231 mod = module_lookupbyid(SCARG(uap, modid));
232 if (!mod)
233 return ENOENT;
234
235 if (TAILQ_NEXT(mod, flink))
236 p->p_retval[0] = TAILQ_NEXT(mod, flink)->id;
237 else
238 p->p_retval[0] = 0;
239 return 0;
240}
241
242int
243modstat(struct proc* p, struct modstat_args* uap)
244{
245 module_t mod;
246 int error = 0;
247 int namelen;
248 int version;
249 struct module_stat* stat;
250
251 mod = module_lookupbyid(SCARG(uap, modid));
252 if (!mod)
253 return ENOENT;
254
255 stat = SCARG(uap, stat);
256
257 /*
258 * Check the version of the user's structure.
259 */
260 if (error = copyin(&stat->version, &version, sizeof(version)))
261 goto out;
262 if (version != sizeof(struct module_stat)) {
263 error = EINVAL;
264 goto out;
265 }
266
267 namelen = strlen(mod->name) + 1;
268 if (namelen > MAXMODNAME)
269 namelen = MAXMODNAME;
270 if (error = copyout(mod->name, &stat->name[0], namelen))
271 goto out;
272
273 if (error = copyout(&mod->refs, &stat->refs, sizeof(int)))
274 goto out;
275 if (error = copyout(&mod->id, &stat->id, sizeof(int)))
276 goto out;
277
278 p->p_retval[0] = 0;
279
280out:
281 return error;
282}
283
284int
285modfind(struct proc* p, struct modfind_args* uap)
286{
287 int error = 0;
288 char name[MAXMODNAME];
289 module_t mod;
290
291 if (error = copyinstr(SCARG(uap, name), name, sizeof name, 0))
292 goto out;
293
294 mod = module_lookupbyname(name);
295 if (!mod)
296 error = ENOENT;
297 else
298 p->p_retval[0] = mod->id;
299
300out:
301 return error;
302}
87}
88
89int
90module_register(const char* name, modeventhand_t handler, void* arg)
91{
92 size_t namelen;
93 module_t newmod;
94 int error;
95
96 namelen = strlen(name) + 1;
97 newmod = (module_t) malloc(sizeof(struct module) + namelen,
98 M_MODULE, M_WAITOK);
99 if (newmod == 0)
100 return ENOMEM;
101
102 newmod->refs = 1;
103 newmod->id = nextid++;
104 newmod->name = (char *) (newmod + 1);
105 strcpy(newmod->name, name);
106 newmod->handler = handler;
107 newmod->arg = arg;
108 TAILQ_INSERT_TAIL(&modules, newmod, link);
109
110 if (linker_current_file) {
111 TAILQ_INSERT_TAIL(&linker_current_file->modules, newmod, flink);
112 newmod->file = linker_current_file;
113 } else
114 newmod->file = 0;
115
116 if (error = MOD_EVENT(newmod, MOD_LOAD)) {
117 module_release(newmod);
118 return error;
119 }
120
121 return 0;
122}
123
124void
125module_reference(module_t mod)
126{
127 MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
128
129 mod->refs++;
130}
131
132void
133module_release(module_t mod)
134{
135 if (mod->refs <= 0)
136 panic("module_release: bad reference count");
137
138 MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
139
140 mod->refs--;
141 if (mod->refs == 0) {
142 TAILQ_REMOVE(&modules, mod, link);
143 if (mod->file) {
144 TAILQ_REMOVE(&mod->file->modules, mod, flink);
145 }
146 free(mod, M_MODULE);
147 }
148}
149
150module_t
151module_lookupbyname(const char* name)
152{
153 module_t mod;
154
155 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
156 if (!strcmp(mod->name, name))
157 return mod;
158 }
159
160 return 0;
161}
162
163module_t
164module_lookupbyid(int modid)
165{
166 module_t mod;
167
168 for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
169 if (mod->id == modid)
170 return mod;
171 }
172
173 return 0;
174}
175
176int
177module_unload(module_t mod)
178{
179 return MOD_EVENT(mod, MOD_UNLOAD);
180}
181
182int
183module_getid(module_t mod)
184{
185 return mod->id;
186}
187
188module_t
189module_getfnext(module_t mod)
190{
191 return TAILQ_NEXT(mod, flink);
192}
193
194/*
195 * Syscalls.
196 */
197int
198modnext(struct proc* p, struct modnext_args* uap)
199{
200 module_t mod;
201
202 p->p_retval[0] = -1;
203 if (SCARG(uap, modid) == 0) {
204 mod = TAILQ_FIRST(&modules);
205 if (mod) {
206 p->p_retval[0] = mod->id;
207 return 0;
208 } else
209 return ENOENT;
210 }
211
212 mod = module_lookupbyid(SCARG(uap, modid));
213 if (!mod)
214 return ENOENT;
215
216 if (TAILQ_NEXT(mod, link))
217 p->p_retval[0] = TAILQ_NEXT(mod, link)->id;
218 else
219 p->p_retval[0] = 0;
220 return 0;
221}
222
223int
224modfnext(struct proc* p, struct modfnext_args* uap)
225{
226 module_t mod;
227
228 p->p_retval[0] = -1;
229
230 mod = module_lookupbyid(SCARG(uap, modid));
231 if (!mod)
232 return ENOENT;
233
234 if (TAILQ_NEXT(mod, flink))
235 p->p_retval[0] = TAILQ_NEXT(mod, flink)->id;
236 else
237 p->p_retval[0] = 0;
238 return 0;
239}
240
241int
242modstat(struct proc* p, struct modstat_args* uap)
243{
244 module_t mod;
245 int error = 0;
246 int namelen;
247 int version;
248 struct module_stat* stat;
249
250 mod = module_lookupbyid(SCARG(uap, modid));
251 if (!mod)
252 return ENOENT;
253
254 stat = SCARG(uap, stat);
255
256 /*
257 * Check the version of the user's structure.
258 */
259 if (error = copyin(&stat->version, &version, sizeof(version)))
260 goto out;
261 if (version != sizeof(struct module_stat)) {
262 error = EINVAL;
263 goto out;
264 }
265
266 namelen = strlen(mod->name) + 1;
267 if (namelen > MAXMODNAME)
268 namelen = MAXMODNAME;
269 if (error = copyout(mod->name, &stat->name[0], namelen))
270 goto out;
271
272 if (error = copyout(&mod->refs, &stat->refs, sizeof(int)))
273 goto out;
274 if (error = copyout(&mod->id, &stat->id, sizeof(int)))
275 goto out;
276
277 p->p_retval[0] = 0;
278
279out:
280 return error;
281}
282
283int
284modfind(struct proc* p, struct modfind_args* uap)
285{
286 int error = 0;
287 char name[MAXMODNAME];
288 module_t mod;
289
290 if (error = copyinstr(SCARG(uap, name), name, sizeof name, 0))
291 goto out;
292
293 mod = module_lookupbyname(name);
294 if (!mod)
295 error = ENOENT;
296 else
297 p->p_retval[0] = mod->id;
298
299out:
300 return error;
301}