- 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:
parent
f05446648b
commit
aeeb017bd6
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user