The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_module.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * $FreeBSD: releng/5.1/sys/kern/kern_module.c 111119 2003-02-19 05:47:46Z imp $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/kernel.h>
   31 #include <sys/systm.h>
   32 #include <sys/eventhandler.h>
   33 #include <sys/malloc.h>
   34 #include <sys/sysproto.h>
   35 #include <sys/sysent.h>
   36 #include <sys/proc.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <sys/sx.h>
   40 #include <sys/module.h>
   41 #include <sys/linker.h>
   42 
   43 static MALLOC_DEFINE(M_MODULE, "module", "module data structures");
   44 
   45 typedef TAILQ_HEAD(, module) modulelist_t;
   46 struct module {
   47         TAILQ_ENTRY(module)     link;   /* chain together all modules */
   48         TAILQ_ENTRY(module)     flink;  /* all modules in a file */
   49         struct linker_file      *file;  /* file which contains this module */
   50         int                     refs;   /* reference count */
   51         int                     id;     /* unique id number */
   52         char                    *name;  /* module name */
   53         modeventhand_t          handler;        /* event handler */
   54         void                    *arg;   /* argument for handler */
   55         modspecific_t           data;   /* module specific data */
   56 };
   57 
   58 #define MOD_EVENT(mod, type)    (mod)->handler((mod), (type), (mod)->arg)
   59 
   60 static modulelist_t modules;
   61 struct sx modules_sx;
   62 static int nextid = 1;
   63 static void module_shutdown(void *, int);
   64 
   65 static int
   66 modevent_nop(module_t mod, int what, void *arg)
   67 {
   68         return (0);
   69 }
   70 
   71 static void
   72 module_init(void *arg)
   73 {
   74 
   75         sx_init(&modules_sx, "module subsystem sx lock");
   76         TAILQ_INIT(&modules);
   77         EVENTHANDLER_REGISTER(shutdown_final, module_shutdown, NULL,
   78             SHUTDOWN_PRI_DEFAULT);
   79 }
   80 
   81 SYSINIT(module, SI_SUB_KLD, SI_ORDER_FIRST, module_init, 0)
   82 
   83 static void
   84 module_shutdown(void *arg1, int arg2)
   85 {
   86         module_t mod;
   87 
   88         MOD_SLOCK;
   89         TAILQ_FOREACH(mod, &modules, link)
   90                 MOD_EVENT(mod, MOD_SHUTDOWN);
   91         MOD_SUNLOCK;
   92 }
   93 
   94 void
   95 module_register_init(const void *arg)
   96 {
   97         const moduledata_t *data = (const moduledata_t *)arg;
   98         int error;
   99         module_t mod;
  100 
  101         MOD_SLOCK;
  102         mod = module_lookupbyname(data->name);
  103         if (mod == NULL)
  104                 panic("module_register_init: module named %s not found\n",
  105                     data->name);
  106         MOD_SUNLOCK;
  107         error = MOD_EVENT(mod, MOD_LOAD);
  108         if (error) {
  109                 MOD_EVENT(mod, MOD_UNLOAD);
  110                 MOD_XLOCK;
  111                 module_release(mod);
  112                 MOD_XUNLOCK;
  113                 printf("module_register_init: MOD_LOAD (%s, %p, %p) error"
  114                     " %d\n", data->name, (void *)data->evhand, data->priv,
  115                     error); 
  116         }
  117 }
  118 
  119 int
  120 module_register(const moduledata_t *data, linker_file_t container)
  121 {
  122         size_t namelen;
  123         module_t newmod;
  124 
  125         MOD_SLOCK;
  126         newmod = module_lookupbyname(data->name);
  127         if (newmod != NULL) {
  128                 MOD_SUNLOCK;
  129                 printf("module_register: module %s already exists!\n",
  130                     data->name);
  131                 return (EEXIST);
  132         }
  133         MOD_SUNLOCK;
  134         namelen = strlen(data->name) + 1;
  135         newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK);
  136         if (newmod == NULL)
  137                 return (ENOMEM);
  138         MOD_XLOCK;
  139         newmod->refs = 1;
  140         newmod->id = nextid++;
  141         newmod->name = (char *)(newmod + 1);
  142         strcpy(newmod->name, data->name);
  143         newmod->handler = data->evhand ? data->evhand : modevent_nop;
  144         newmod->arg = data->priv;
  145         bzero(&newmod->data, sizeof(newmod->data));
  146         TAILQ_INSERT_TAIL(&modules, newmod, link);
  147 
  148         if (container)
  149                 TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
  150         newmod->file = container;
  151         MOD_XUNLOCK;
  152         return (0);
  153 }
  154 
  155 void
  156 module_reference(module_t mod)
  157 {
  158 
  159         MOD_XLOCK_ASSERT;
  160 
  161         MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
  162         mod->refs++;
  163 }
  164 
  165 void
  166 module_release(module_t mod)
  167 {
  168 
  169         MOD_XLOCK_ASSERT;
  170 
  171         if (mod->refs <= 0)
  172                 panic("module_release: bad reference count");
  173 
  174         MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
  175         
  176         mod->refs--;
  177         if (mod->refs == 0) {
  178                 TAILQ_REMOVE(&modules, mod, link);
  179                 if (mod->file)
  180                         TAILQ_REMOVE(&mod->file->modules, mod, flink);
  181                 MOD_XUNLOCK;
  182                 free(mod, M_MODULE);
  183                 MOD_XLOCK;
  184         }
  185 }
  186 
  187 module_t
  188 module_lookupbyname(const char *name)
  189 {
  190         module_t mod;
  191         int err;
  192 
  193         MOD_LOCK_ASSERT;
  194 
  195         TAILQ_FOREACH(mod, &modules, link) {
  196                 err = strcmp(mod->name, name);
  197                 if (err == 0)
  198                         return (mod);
  199         }
  200         return (NULL);
  201 }
  202 
  203 module_t
  204 module_lookupbyid(int modid)
  205 {
  206         module_t mod;
  207 
  208         MOD_LOCK_ASSERT;
  209 
  210         TAILQ_FOREACH(mod, &modules, link)
  211                 if (mod->id == modid)
  212                         return(mod);
  213         return (NULL);
  214 }
  215 
  216 int
  217 module_unload(module_t mod)
  218 {
  219 
  220         return (MOD_EVENT(mod, MOD_UNLOAD));
  221 }
  222 
  223 int
  224 module_getid(module_t mod)
  225 {
  226 
  227         MOD_LOCK_ASSERT;
  228         return (mod->id);
  229 }
  230 
  231 module_t
  232 module_getfnext(module_t mod)
  233 {
  234 
  235         MOD_LOCK_ASSERT;
  236         return (TAILQ_NEXT(mod, flink));
  237 }
  238 
  239 void
  240 module_setspecific(module_t mod, modspecific_t *datap)
  241 {
  242 
  243         MOD_XLOCK_ASSERT;
  244         mod->data = *datap;
  245 }
  246 
  247 /*
  248  * Syscalls.
  249  */
  250 /*
  251  * MPSAFE
  252  */
  253 int
  254 modnext(struct thread *td, struct modnext_args *uap)
  255 {
  256         module_t mod;
  257         int error = 0;
  258 
  259         td->td_retval[0] = -1;
  260 
  261         MOD_SLOCK;
  262         if (uap->modid == 0) {
  263                 mod = TAILQ_FIRST(&modules);
  264                 if (mod)
  265                         td->td_retval[0] = mod->id;
  266                 else
  267                         error = ENOENT;
  268                 goto done2;
  269         }
  270         mod = module_lookupbyid(uap->modid);
  271         if (mod == NULL) {
  272                 error = ENOENT;
  273                 goto done2;
  274         }
  275         if (TAILQ_NEXT(mod, link))
  276                 td->td_retval[0] = TAILQ_NEXT(mod, link)->id;
  277         else
  278                 td->td_retval[0] = 0;
  279 done2:
  280         MOD_SUNLOCK;
  281         return (error);
  282 }
  283 
  284 /*
  285  * MPSAFE
  286  */
  287 int
  288 modfnext(struct thread *td, struct modfnext_args *uap)
  289 {
  290         module_t mod;
  291         int error;
  292 
  293         td->td_retval[0] = -1;
  294 
  295         MOD_SLOCK;
  296         mod = module_lookupbyid(uap->modid);
  297         if (mod == NULL) {
  298                 error = ENOENT;
  299         } else {
  300                 error = 0;
  301                 if (TAILQ_NEXT(mod, flink))
  302                         td->td_retval[0] = TAILQ_NEXT(mod, flink)->id;
  303                 else
  304                         td->td_retval[0] = 0;
  305         }
  306         MOD_SUNLOCK;
  307         return (error);
  308 }
  309 
  310 struct module_stat_v1 {
  311         int     version;                /* set to sizeof(struct module_stat) */
  312         char    name[MAXMODNAME];
  313         int     refs;
  314         int     id;
  315 };
  316 
  317 /*
  318  * MPSAFE
  319  */
  320 int
  321 modstat(struct thread *td, struct modstat_args *uap)
  322 {
  323         module_t mod;
  324         modspecific_t data;
  325         int error = 0;
  326         int id, namelen, refs, version;
  327         struct module_stat *stat;
  328         char *name;
  329 
  330         MOD_SLOCK;
  331         mod = module_lookupbyid(uap->modid);
  332         if (mod == NULL) {
  333                 MOD_SUNLOCK;
  334                 return (ENOENT);
  335         }
  336         id = mod->id;
  337         refs = mod->refs;
  338         name = mod->name;
  339         data = mod->data;
  340         MOD_SUNLOCK;
  341         stat = uap->stat;
  342 
  343         /*
  344          * Check the version of the user's structure.
  345          */
  346         if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
  347                 return (error);
  348         if (version != sizeof(struct module_stat_v1)
  349             && version != sizeof(struct module_stat))
  350                 return (EINVAL);
  351         namelen = strlen(mod->name) + 1;
  352         if (namelen > MAXMODNAME)
  353                 namelen = MAXMODNAME;
  354         if ((error = copyout(name, &stat->name[0], namelen)) != 0)
  355                 return (error);
  356 
  357         if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0)
  358                 return (error);
  359         if ((error = copyout(&id, &stat->id, sizeof(int))) != 0)
  360                 return (error);
  361 
  362         /*
  363          * >v1 stat includes module data.
  364          */
  365         if (version == sizeof(struct module_stat))
  366                 if ((error = copyout(&data, &stat->data, 
  367                     sizeof(data))) != 0)
  368                         return (error);
  369         td->td_retval[0] = 0;
  370         return (error);
  371 }
  372 
  373 /*
  374  * MPSAFE
  375  */
  376 int
  377 modfind(struct thread *td, struct modfind_args *uap)
  378 {
  379         int error = 0;
  380         char name[MAXMODNAME];
  381         module_t mod;
  382 
  383         if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0)
  384                 return (error);
  385 
  386         MOD_SLOCK;
  387         mod = module_lookupbyname(name);
  388         if (mod == NULL)
  389                 error = ENOENT;
  390         else
  391                 td->td_retval[0] = module_getid(mod);
  392         MOD_SUNLOCK;
  393         return (error);
  394 }

Cache object: 307244a027a16b087c83b369fa602ff3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.