- 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
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=159804
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);
if (symptr == NULL) {
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);
}
@ -803,7 +803,7 @@ digi_loadmoduledata(struct digi_softc *sc)
if (digi_mod->dm_version != DIGI_MOD_VERSION) {
printf("digi_%s.ko: Invalid version %d (need %d)\n",
sc->module, digi_mod->dm_version, DIGI_MOD_VERSION);
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
linker_release_module(NULL, NULL, lf);
return (EINVAL);
}
@ -825,7 +825,7 @@ digi_loadmoduledata(struct digi_softc *sc)
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);
}

View File

@ -415,14 +415,44 @@ linker_reference_module(const char *modname, struct mod_depend *verinfo,
linker_file_t *result)
{
modlist_t mod;
int error;
mtx_lock(&Giant);
if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
*result = mod->container;
(*result)->refs++;
mtx_unlock(&Giant);
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

View File

@ -195,9 +195,7 @@ firmware_get(const char *imagename)
"load firmware image %s\n", __func__, imagename);
return NULL;
}
mtx_lock(&Giant); /* XXX */
(void) linker_reference_module(imagename, NULL, &result);
mtx_unlock(&Giant); /* XXX */
requested_load = 1;
goto again; /* sort of an Algol-style for loop */
}
@ -227,7 +225,7 @@ unloadentry(void *unused1, int unused2)
fp->file = NULL;
mtx_unlock(&firmware_mtx);
linker_file_unload(file, LINKER_UNLOAD_NORMAL);
linker_release_module(NULL, NULL, file);
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,
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
* predicate function while the function returns 0. Returns the value