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

Cache object: 149d38ceddd355e22528df0abd72d09f


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