- Push Giant down into linker_reference_module().

- Add a new function linker_release_module() as a more intuitive complement
  to linker_reference_module() that wraps linker_file_unload().
  linker_release_module() can either take the module name and version info
  passed to linker_reference_module() or it can accept the linker file
  object returned by linker_reference_module().
This commit is contained in:
John Baldwin 2006-06-20 20:54:13 +00:00
parent f05446648b
commit aeeb017bd6
4 changed files with 43 additions and 7 deletions

View File

@ -795,7 +795,7 @@ digi_loadmoduledata(struct digi_softc *sc)
free(sym, M_TEMP); free(sym, M_TEMP);
if (symptr == NULL) { if (symptr == NULL) {
printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym); printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym);
linker_file_unload(lf, LINKER_UNLOAD_FORCE); linker_release_module(NULL, NULL, lf);
return (EINVAL); return (EINVAL);
} }
@ -803,7 +803,7 @@ digi_loadmoduledata(struct digi_softc *sc)
if (digi_mod->dm_version != DIGI_MOD_VERSION) { if (digi_mod->dm_version != DIGI_MOD_VERSION) {
printf("digi_%s.ko: Invalid version %d (need %d)\n", printf("digi_%s.ko: Invalid version %d (need %d)\n",
sc->module, digi_mod->dm_version, DIGI_MOD_VERSION); sc->module, digi_mod->dm_version, DIGI_MOD_VERSION);
linker_file_unload(lf, LINKER_UNLOAD_FORCE); linker_release_module(NULL, NULL, lf);
return (EINVAL); return (EINVAL);
} }
@ -825,7 +825,7 @@ digi_loadmoduledata(struct digi_softc *sc)
bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size); bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size);
} }
linker_file_unload(lf, LINKER_UNLOAD_FORCE); linker_release_module(NULL, NULL, lf);
return (0); return (0);
} }

View File

@ -415,14 +415,44 @@ linker_reference_module(const char *modname, struct mod_depend *verinfo,
linker_file_t *result) linker_file_t *result)
{ {
modlist_t mod; modlist_t mod;
int error;
mtx_lock(&Giant);
if ((mod = modlist_lookup2(modname, verinfo)) != NULL) { if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
*result = mod->container; *result = mod->container;
(*result)->refs++; (*result)->refs++;
mtx_unlock(&Giant);
return (0); return (0);
} }
return (linker_load_module(NULL, modname, NULL, verinfo, result)); error = linker_load_module(NULL, modname, NULL, verinfo, result);
mtx_unlock(&Giant);
return (error);
}
int
linker_release_module(const char *modname, struct mod_depend *verinfo,
linker_file_t lf)
{
modlist_t mod;
int error;
mtx_lock(&Giant);
if (lf == NULL) {
KASSERT(modname != NULL,
("linker_release_module: no file or name"));
mod = modlist_lookup2(modname, verinfo);
if (mod == NULL) {
mtx_unlock(&Giant);
return (ESRCH);
}
lf = mod->container;
} else
KASSERT(modname == NULL && verinfo == NULL,
("linker_release_module: both file and name"));
error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
mtx_unlock(&Giant);
return (error);
} }
static linker_file_t static linker_file_t

View File

@ -195,9 +195,7 @@ again:
"load firmware image %s\n", __func__, imagename); "load firmware image %s\n", __func__, imagename);
return NULL; return NULL;
} }
mtx_lock(&Giant); /* XXX */
(void) linker_reference_module(imagename, NULL, &result); (void) linker_reference_module(imagename, NULL, &result);
mtx_unlock(&Giant); /* XXX */
requested_load = 1; requested_load = 1;
goto again; /* sort of an Algol-style for loop */ goto again; /* sort of an Algol-style for loop */
} }
@ -227,7 +225,7 @@ unloadentry(void *unused1, int unused2)
fp->file = NULL; fp->file = NULL;
mtx_unlock(&firmware_mtx); mtx_unlock(&firmware_mtx);
linker_file_unload(file, LINKER_UNLOAD_NORMAL); linker_release_module(NULL, NULL, file);
mtx_lock(&firmware_mtx); mtx_lock(&firmware_mtx);
} }

View File

@ -115,6 +115,14 @@ int linker_add_class(linker_class_t _cls);
int linker_reference_module(const char* _modname, struct mod_depend *_verinfo, int linker_reference_module(const char* _modname, struct mod_depend *_verinfo,
linker_file_t* _result); linker_file_t* _result);
/*
* Release a reference to a module, unloading it if there are no more
* references. Note that one should either provide a module name and
* optional version info or a linker file, but not both.
*/
int linker_release_module(const char *_modname, struct mod_depend *_verinfo,
linker_file_t _file);
/* /*
* Iterate over all of the currently loaded linker files calling the * Iterate over all of the currently loaded linker files calling the
* predicate function while the function returns 0. Returns the value * predicate function while the function returns 0. Returns the value