A hash_lookup() to the module images was made without having the proper lock held.
Added kernel private calls load_module() and unload_module() that can be used to load/unload modules by path. load_module_image() now only mentions when it couldn't load a module when tracing is enabled (because the device manager uses it to determine if an add-on is a module or an old-style driver). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10821 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+59
-11
@@ -1,12 +1,14 @@
|
|||||||
/* Module manager */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Copyright 2002-2004, Haiku Inc.. All rights reserved.
|
* Copyright 2002-2005, Haiku Inc. All rights reserved.
|
||||||
** Distributed under the terms of the Haiku License.
|
* Distributed under the terms of the MIT License.
|
||||||
**
|
*
|
||||||
** Copyright 2001, Thomas Kurschel. All rights reserved.
|
* Copyright 2001, Thomas Kurschel. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* The Module manager
|
||||||
|
* Manages kernel add-ons and their exported modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <kmodule.h>
|
#include <kmodule.h>
|
||||||
@@ -273,7 +275,7 @@ load_module_image(const char *path, module_image **_moduleImage)
|
|||||||
|
|
||||||
if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
|
if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
|
||||||
(void **)&moduleImage->info) != B_OK) {
|
(void **)&moduleImage->info) != B_OK) {
|
||||||
FATAL(("load_module_image: Failed to load %s due to lack of 'modules' symbol\n", path));
|
TRACE(("load_module_image: Failed to load \"%s\" due to lack of 'modules' symbol\n", path));
|
||||||
status = B_BAD_TYPE;
|
status = B_BAD_TYPE;
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
@@ -314,11 +316,15 @@ unload_module_image(module_image *moduleImage, const char *path)
|
|||||||
{
|
{
|
||||||
TRACE(("unload_module_image(image = %p, path = %s)\n", moduleImage, path));
|
TRACE(("unload_module_image(image = %p, path = %s)\n", moduleImage, path));
|
||||||
|
|
||||||
|
recursive_lock_lock(&sModulesLock);
|
||||||
|
|
||||||
if (moduleImage == NULL) {
|
if (moduleImage == NULL) {
|
||||||
// if no image was specified, lookup it up in the hash table
|
// if no image was specified, lookup it up in the hash table
|
||||||
moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
|
moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
|
||||||
if (moduleImage == NULL)
|
if (moduleImage == NULL) {
|
||||||
|
recursive_lock_unlock(&sModulesLock);
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleImage->ref_count != 0) {
|
if (moduleImage->ref_count != 0) {
|
||||||
@@ -326,7 +332,6 @@ unload_module_image(module_image *moduleImage, const char *path)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
recursive_lock_lock(&sModulesLock);
|
|
||||||
hash_remove(sModuleImagesHash, moduleImage);
|
hash_remove(sModuleImagesHash, moduleImage);
|
||||||
recursive_lock_unlock(&sModulesLock);
|
recursive_lock_unlock(&sModulesLock);
|
||||||
|
|
||||||
@@ -1055,6 +1060,49 @@ dump_modules(int argc, char **argv)
|
|||||||
// Exported Kernel API (private part)
|
// Exported Kernel API (private part)
|
||||||
|
|
||||||
|
|
||||||
|
/** Unloads a module in case it's not in use. This is the counterpart
|
||||||
|
* to load_module().
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
unload_module(const char *path)
|
||||||
|
{
|
||||||
|
struct module_image *moduleImage;
|
||||||
|
|
||||||
|
recursive_lock_lock(&sModulesLock);
|
||||||
|
moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
|
||||||
|
recursive_lock_unlock(&sModulesLock);
|
||||||
|
|
||||||
|
if (moduleImage == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
put_module_image(moduleImage);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Unlike get_module(), this function lets you specify the add-on to
|
||||||
|
* be loaded by path.
|
||||||
|
* However, you must not use the exported modules without having called
|
||||||
|
* get_module() on them. When you're done with the NULL terminated
|
||||||
|
* \a modules array, you have to call unload_module(), no matter if
|
||||||
|
* you're actually using any of the modules or not - of course, the
|
||||||
|
* add-on won't be unloaded until the last put_module().
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
load_module(const char *path, module_info ***_modules)
|
||||||
|
{
|
||||||
|
module_image *moduleImage;
|
||||||
|
status_t status = get_module_image(path, &moduleImage);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
*_modules = moduleImage->info;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Setup the module structures and data for use - must be called
|
/** Setup the module structures and data for use - must be called
|
||||||
* before any other module call.
|
* before any other module call.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user