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: src/sys/kern/kern_module.c,v 1.21 1999/11/08 06:53:30 peter Exp $
   27  * $DragonFly: src/sys/kern/kern_module.c,v 1.16 2008/06/07 11:44:04 mneumann Exp $
   28  */
   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/module.h>
   38 #include <sys/linker.h>
   39 #include <sys/proc.h>
   40 
   41 #include <sys/mplock2.h>
   42 
   43 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 = TAILQ_HEAD_INITIALIZER(modules);
   61 static int nextid = 1;
   62 
   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 
   72 static void
   73 module_init(void* arg)
   74 {
   75     TAILQ_INIT(&modules);
   76     EVENTHANDLER_REGISTER(shutdown_post_sync, module_shutdown, NULL,
   77                           SHUTDOWN_PRI_DEFAULT);
   78 }
   79 
   80 SYSINIT(module, SI_BOOT2_KLD, SI_ORDER_FIRST, module_init, 0);
   81 
   82 static void
   83 module_shutdown(void* arg1, int arg2)
   84 {
   85     module_t mod;
   86 
   87     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link))
   88         MOD_EVENT(mod, MOD_SHUTDOWN);
   89 }
   90 
   91 void
   92 module_register_init(const void *arg)
   93 {
   94     const moduledata_t* data = (const moduledata_t*) arg;
   95     int error;
   96     module_t mod;
   97 
   98     mod = module_lookupbyname(data->name);
   99     if (mod == NULL) {
  100 #if 0
  101         panic("module_register_init: module named %s not found", data->name);
  102 #else
  103         /* temporary kludge until kernel `file' attachment registers modules */
  104         error = module_register(data, linker_kernel_file);
  105         if (error)
  106             panic("module_register_init: register of module failed! %d", error);
  107         mod = module_lookupbyname(data->name);
  108         if (mod == NULL)
  109             panic("module_register_init: module STILL not found!");
  110 #endif
  111     }
  112     error = MOD_EVENT(mod, MOD_LOAD);
  113     if (error) {
  114         module_unload(mod);     /* ignore error */
  115         module_release(mod);
  116         kprintf("module_register_init: MOD_LOAD (%s, %lx, %p) error %d\n",
  117                data->name, (u_long)(uintfptr_t)data->evhand, data->priv, error);
  118     }
  119 }
  120 
  121 int
  122 module_register(const moduledata_t *data, linker_file_t container)
  123 {
  124     size_t namelen;
  125     module_t newmod;
  126 
  127     newmod = module_lookupbyname(data->name);
  128     if (newmod != NULL) {
  129         kprintf("module_register: module %s already exists!\n", data->name);
  130         return EEXIST;
  131     }
  132     namelen = strlen(data->name) + 1;
  133     newmod = (module_t) kmalloc(sizeof(struct module) + namelen,
  134                                M_MODULE, M_WAITOK);
  135 
  136     newmod->refs = 1;
  137     newmod->id = nextid++;
  138     newmod->name = (char *) (newmod + 1);
  139     strcpy(newmod->name, data->name);
  140     newmod->handler = data->evhand ? data->evhand : modevent_nop;
  141     newmod->arg = data->priv;
  142     bzero(&newmod->data, sizeof(newmod->data));
  143     TAILQ_INSERT_TAIL(&modules, newmod, link);
  144 
  145     if (container == NULL)
  146         container = linker_current_file;
  147     if (container)
  148         TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
  149     newmod->file = container;
  150 
  151     return 0;
  152 }
  153 
  154 void
  155 module_reference(module_t mod)
  156 {
  157     MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
  158 
  159     mod->refs++;
  160 }
  161 
  162 /*
  163  * module_release()
  164  *
  165  *      Release ref on the module and return the new reference count.  If 0
  166  *      is returned, the module has been removed from its list and freed.
  167  */
  168 int
  169 module_release(module_t mod)
  170 {
  171     int rc;
  172 
  173     if (mod->refs <= 0)
  174         panic("module_release: bad reference count");
  175 
  176     MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
  177 
  178     rc = --mod->refs;
  179     if (rc == 0) {
  180         TAILQ_REMOVE(&modules, mod, link);
  181         if (mod->file) {
  182             TAILQ_REMOVE(&mod->file->modules, mod, flink);
  183         }
  184         kfree(mod, M_MODULE);
  185     }
  186     return(rc);
  187 }
  188 
  189 module_t
  190 module_lookupbyname(const char* name)
  191 {
  192     module_t mod;
  193 
  194     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
  195         if (!strcmp(mod->name, name))
  196             return mod;
  197     }
  198 
  199     return NULL;
  200 }
  201 
  202 module_t
  203 module_lookupbyid(int modid)
  204 {
  205     module_t mod;
  206 
  207     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
  208         if (mod->id == modid)
  209             return mod;
  210     }
  211 
  212     return NULL;
  213 }
  214 
  215 int
  216 module_unload(module_t mod)
  217 {
  218     int error;
  219 
  220     error = MOD_EVENT(mod, MOD_UNLOAD);
  221     /*sync_devs();*/
  222     return (error);
  223 }
  224 
  225 int
  226 module_getid(module_t mod)
  227 {
  228     return mod->id;
  229 }
  230 
  231 module_t
  232 module_getfnext(module_t mod)
  233 {
  234     return TAILQ_NEXT(mod, flink);
  235 }
  236 
  237 void
  238 module_setspecific(module_t mod, modspecific_t *datap)
  239 {
  240     mod->data = *datap;
  241 }
  242 
  243 /*
  244  * Syscalls.
  245  *
  246  * MPALMOSTSAFE
  247  */
  248 int
  249 sys_modnext(struct modnext_args *uap)
  250 {
  251     module_t mod;
  252     int error;
  253 
  254     get_mplock();
  255     uap->sysmsg_result = -1;
  256     if (uap->modid == 0) {
  257         mod = TAILQ_FIRST(&modules);
  258         if (mod) {
  259             uap->sysmsg_result = mod->id;
  260             error = 0;
  261             goto done;
  262         } else {
  263             error = ENOENT;
  264             goto done;
  265         }
  266     }
  267 
  268     mod = module_lookupbyid(uap->modid);
  269     if (!mod) {
  270         error = ENOENT;
  271         goto done;
  272     }
  273 
  274     if (TAILQ_NEXT(mod, link))
  275         uap->sysmsg_result = TAILQ_NEXT(mod, link)->id;
  276     else
  277         uap->sysmsg_result = 0;
  278     error = 0;
  279 done:
  280     rel_mplock();
  281     return error;
  282 }
  283 
  284 /*
  285  * MPALMOSTSAFE
  286  */
  287 int
  288 sys_modfnext(struct modfnext_args *uap)
  289 {
  290     module_t mod;
  291     int error;
  292 
  293     get_mplock();
  294     uap->sysmsg_result = -1;
  295 
  296     mod = module_lookupbyid(uap->modid);
  297     if (!mod) {
  298         error = ENOENT;
  299         goto done;
  300     }
  301 
  302     if (TAILQ_NEXT(mod, flink))
  303         uap->sysmsg_result = TAILQ_NEXT(mod, flink)->id;
  304     else
  305         uap->sysmsg_result = 0;
  306     error = 0;
  307 done:
  308     rel_mplock();
  309     return error;
  310 }
  311 
  312 struct module_stat_v1 {
  313     int         version;        /* set to sizeof(struct module_stat) */
  314     char        name[MAXMODNAME];
  315     int         refs;
  316     int         id;
  317 };
  318 
  319 /*
  320  * MPALMOSTSAFE
  321  */
  322 int
  323 sys_modstat(struct modstat_args *uap)
  324 {
  325     module_t mod;
  326     int error;
  327     int namelen;
  328     int version;
  329     struct module_stat* stat;
  330 
  331     get_mplock();
  332     mod = module_lookupbyid(uap->modid);
  333     if (!mod) {
  334         error = ENOENT;
  335         goto out;
  336     }
  337 
  338     stat = uap->stat;
  339 
  340     /*
  341      * Check the version of the user's structure.
  342      */
  343     if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
  344         goto out;
  345     if (version != sizeof(struct module_stat_v1)
  346         && version != sizeof(struct module_stat)) {
  347         error = EINVAL;
  348         goto out;
  349     }
  350 
  351     namelen = strlen(mod->name) + 1;
  352     if (namelen > MAXMODNAME)
  353         namelen = MAXMODNAME;
  354     if ((error = copyout(mod->name, &stat->name[0], namelen)) != 0)
  355         goto out;
  356 
  357     if ((error = copyout(&mod->refs, &stat->refs, sizeof(int))) != 0)
  358         goto out;
  359     if ((error = copyout(&mod->id, &stat->id, sizeof(int))) != 0)
  360         goto out;
  361 
  362     /*
  363      * >v1 stat includes module data.
  364      */
  365     if (version == sizeof(struct module_stat)) {
  366         if ((error = copyout(&mod->data, &stat->data, sizeof(mod->data))) != 0)
  367             goto out;
  368     }
  369 
  370     uap->sysmsg_result = 0;
  371 
  372 out:
  373     rel_mplock();
  374     return error;
  375 }
  376 
  377 /*
  378  * MPALMOSTSAFE
  379  */
  380 int
  381 sys_modfind(struct modfind_args *uap)
  382 {
  383     int error;
  384     char name[MAXMODNAME];
  385     module_t mod;
  386 
  387     get_mplock();
  388     if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0)
  389         goto out;
  390 
  391     mod = module_lookupbyname(name);
  392     if (!mod)
  393         error = ENOENT;
  394     else
  395         uap->sysmsg_result = mod->id;
  396 
  397 out:
  398     rel_mplock();
  399     return error;
  400 }

Cache object: 684b11541bdb45c32dca797e9b88e562


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