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$
   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 
   41 typedef TAILQ_HEAD(, module) modulelist_t;
   42 struct 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     modspecific_t       data;           /* module specific data */
   52 };
   53 
   54 #define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg)
   55 
   56 static modulelist_t modules;
   57 static int nextid = 1;
   58 
   59 static void module_shutdown(int, void*);
   60 
   61 static void
   62 module_init(void* arg)
   63 {
   64     TAILQ_INIT(&modules);
   65     at_shutdown(module_shutdown, 0, SHUTDOWN_POST_SYNC);
   66 }
   67 
   68 SYSINIT(module, SI_SUB_KLD, SI_ORDER_FIRST, module_init, 0);
   69 
   70 static void
   71 module_shutdown(int arg1, void* arg2)
   72 {
   73     module_t mod;
   74 
   75     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link))
   76         MOD_EVENT(mod, MOD_SHUTDOWN);
   77 }
   78 
   79 void
   80 module_register_init(void *arg)
   81 {
   82     moduledata_t* data = (moduledata_t*) arg;
   83     int error;
   84 
   85     error = module_register(data->name, data->evhand, data->priv, data->_file);
   86     if (error)
   87         printf("module_register_init: module_register(%s, %lx, %p) error %d\n",
   88                data->name, (u_long)(uintfptr_t)data->evhand, data->priv, error);
   89 }
   90 
   91 int
   92 module_register(const char* name, modeventhand_t handler, void* arg, void *file)
   93 {
   94     size_t namelen;
   95     module_t newmod;
   96     int error;
   97     linker_file_t container = file;
   98 
   99     namelen = strlen(name) + 1;
  100     newmod = (module_t) malloc(sizeof(struct module) + namelen,
  101                                M_MODULE, M_WAITOK);
  102     if (newmod == 0)
  103         return ENOMEM;
  104 
  105     newmod->refs = 1;
  106     newmod->id = nextid++;
  107     newmod->name = (char *) (newmod + 1);
  108     strcpy(newmod->name, name);
  109     newmod->handler = handler;
  110     newmod->arg = arg;
  111     bzero(&newmod->data, sizeof(newmod->data));
  112     TAILQ_INSERT_TAIL(&modules, newmod, link);
  113 
  114     if (container == NULL)
  115         container = linker_current_file;
  116     if (container) {
  117         TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
  118         newmod->file = container;
  119     } else
  120         newmod->file = 0;
  121 
  122     if (error = MOD_EVENT(newmod, MOD_LOAD)) {
  123         MOD_EVENT(newmod, MOD_UNLOAD);
  124         module_release(newmod);
  125         return error;
  126     }
  127 
  128     return 0;
  129 }
  130 
  131 void
  132 module_reference(module_t mod)
  133 {
  134     MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
  135 
  136     mod->refs++;
  137 }
  138 
  139 void
  140 module_release(module_t mod)
  141 {
  142     if (mod->refs <= 0)
  143         panic("module_release: bad reference count");
  144 
  145     MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
  146 
  147     mod->refs--;
  148     if (mod->refs == 0) {
  149         TAILQ_REMOVE(&modules, mod, link);
  150         if (mod->file) {
  151             TAILQ_REMOVE(&mod->file->modules, mod, flink);
  152         }
  153         free(mod, M_MODULE);
  154     }
  155 }
  156 
  157 module_t
  158 module_lookupbyname(const char* name)
  159 {
  160     module_t mod;
  161 
  162     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
  163         if (!strcmp(mod->name, name))
  164             return mod;
  165     }
  166 
  167     return 0;
  168 }
  169 
  170 module_t
  171 module_lookupbyid(int modid)
  172 {
  173     module_t mod;
  174 
  175     for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
  176         if (mod->id == modid)
  177             return mod;
  178     }
  179 
  180     return 0;
  181 }
  182 
  183 int
  184 module_unload(module_t mod)
  185 {
  186     return MOD_EVENT(mod, MOD_UNLOAD);
  187 }
  188 
  189 int
  190 module_getid(module_t mod)
  191 {
  192     return mod->id;
  193 }
  194 
  195 module_t
  196 module_getfnext(module_t mod)
  197 {
  198     return TAILQ_NEXT(mod, flink);
  199 }
  200 
  201 void
  202 module_setspecific(module_t mod, modspecific_t *datap)
  203 {
  204     mod->data = *datap;
  205 }
  206 
  207 /*
  208  * Syscalls.
  209  */
  210 int
  211 modnext(struct proc* p, struct modnext_args* uap)
  212 {
  213     module_t mod;
  214 
  215     p->p_retval[0] = -1;
  216     if (SCARG(uap, modid) == 0) {
  217         mod = TAILQ_FIRST(&modules);
  218         if (mod) {
  219             p->p_retval[0] = mod->id;
  220             return 0;
  221         } else
  222             return ENOENT;
  223     }
  224 
  225     mod = module_lookupbyid(SCARG(uap, modid));
  226     if (!mod)
  227         return ENOENT;
  228 
  229     if (TAILQ_NEXT(mod, link))
  230         p->p_retval[0] = TAILQ_NEXT(mod, link)->id;
  231     else
  232         p->p_retval[0] = 0;
  233     return 0;
  234 }
  235 
  236 int
  237 modfnext(struct proc* p, struct modfnext_args* uap)
  238 {
  239     module_t mod;
  240 
  241     p->p_retval[0] = -1;
  242 
  243     mod = module_lookupbyid(SCARG(uap, modid));
  244     if (!mod)
  245         return ENOENT;
  246 
  247     if (TAILQ_NEXT(mod, flink))
  248         p->p_retval[0] = TAILQ_NEXT(mod, flink)->id;
  249     else
  250         p->p_retval[0] = 0;
  251     return 0;
  252 }
  253 
  254 struct module_stat_v1 {
  255     int         version;        /* set to sizeof(struct module_stat) */
  256     char        name[MAXMODNAME];
  257     int         refs;
  258     int         id;
  259 };
  260 
  261 int
  262 modstat(struct proc* p, struct modstat_args* uap)
  263 {
  264     module_t mod;
  265     int error = 0;
  266     int namelen;
  267     int version;
  268     struct module_stat* stat;
  269 
  270     mod = module_lookupbyid(SCARG(uap, modid));
  271     if (!mod)
  272         return ENOENT;
  273 
  274     stat = SCARG(uap, stat);
  275 
  276     /*
  277      * Check the version of the user's structure.
  278      */
  279     if (error = copyin(&stat->version, &version, sizeof(version)))
  280         goto out;
  281     if (version != sizeof(struct module_stat_v1)
  282         && version != sizeof(struct module_stat)) {
  283         error = EINVAL;
  284         goto out;
  285     }
  286 
  287     namelen = strlen(mod->name) + 1;
  288     if (namelen > MAXMODNAME)
  289         namelen = MAXMODNAME;
  290     if (error = copyout(mod->name, &stat->name[0], namelen))
  291         goto out;
  292 
  293     if (error = copyout(&mod->refs, &stat->refs, sizeof(int)))
  294         goto out;
  295     if (error = copyout(&mod->id, &stat->id, sizeof(int)))
  296         goto out;
  297 
  298     /*
  299      * >v1 stat includes module data.
  300      */
  301     if (version == sizeof(struct module_stat)) {
  302         if (error = copyout(&mod->data, &stat->data, sizeof(mod->data)))
  303             goto out;
  304     }
  305 
  306     p->p_retval[0] = 0;
  307 
  308 out:
  309     return error;
  310 }
  311 
  312 int
  313 modfind(struct proc* p, struct modfind_args* uap)
  314 {
  315     int error = 0;
  316     char name[MAXMODNAME];
  317     module_t mod;
  318 
  319     if (error = copyinstr(SCARG(uap, name), name, sizeof name, 0))
  320         goto out;
  321 
  322     mod = module_lookupbyname(name);
  323     if (!mod)
  324         error = ENOENT;
  325     else
  326         p->p_retval[0] = mod->id;
  327 
  328 out:
  329     return error;
  330 }

Cache object: 897af403111c4621ee4201754a3115f6


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