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

Cache object: 58711d9d428bdde8ef0702dac2a8d192


[ 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.