Migrate image hash table to BOpenHashTable.

For #9552.
This commit is contained in:
Adrien Destugues
2015-01-09 18:09:09 +01:00
parent ce39d3a366
commit 69ff01cb9e
+55 -69
View File
@@ -34,7 +34,6 @@
#include <thread.h> #include <thread.h>
#include <runtime_loader.h> #include <runtime_loader.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/khash.h>
#include <vfs.h> #include <vfs.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/vm_types.h> #include <vm/vm_types.h>
@@ -56,7 +55,29 @@
#define IMAGE_HASH_SIZE 16 #define IMAGE_HASH_SIZE 16
static hash_table *sImagesHash; struct ImageHashDefinition {
typedef struct elf_image_info ValueType;
typedef image_id KeyType;
size_t Hash(ValueType* entry) const
{ return HashKey(entry->id); }
ValueType*& GetLink(ValueType* entry) const
{ return entry->next; }
size_t HashKey(KeyType key) const
{
return (size_t)key;
}
bool Compare(KeyType key, ValueType* entry) const
{
return key - entry->id;
}
};
typedef BOpenHashTable<ImageHashDefinition> ImageHash;
static ImageHash *sImagesHash;
static struct elf_image_info *sKernelImage = NULL; static struct elf_image_info *sKernelImage = NULL;
static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock"); static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
@@ -71,36 +92,11 @@ static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
const elf_version_info *version, bool lookupDefault); const elf_version_info *version, bool lookupDefault);
/*! Calculates hash for an image using its ID */
static uint32
image_hash(void *_image, const void *_key, uint32 range)
{
struct elf_image_info *image = (struct elf_image_info *)_image;
image_id id = (image_id)(addr_t)_key;
if (image != NULL)
return image->id % range;
return (uint32)id % range;
}
/*! Compares an image to a given ID */
static int
image_compare(void *_image, const void *_key)
{
struct elf_image_info *image = (struct elf_image_info *)_image;
image_id id = (image_id)(addr_t)_key;
return id - image->id;
}
static void static void
unregister_elf_image(struct elf_image_info *image) unregister_elf_image(struct elf_image_info *image)
{ {
unregister_image(team_get_kernel_team(), image->id); unregister_image(team_get_kernel_team(), image->id);
hash_remove(sImagesHash, image); sImagesHash->Remove(image);
} }
@@ -161,7 +157,7 @@ register_elf_image(struct elf_image_info *image)
image->id = register_image(team_get_kernel_team(), &imageInfo, image->id = register_image(team_get_kernel_team(), &imageInfo,
sizeof(image_info)); sizeof(image_info));
hash_insert(sImagesHash, image); sImagesHash->Insert(image);
} }
@@ -169,20 +165,19 @@ register_elf_image(struct elf_image_info *image)
static struct elf_image_info * static struct elf_image_info *
find_image_at_address(addr_t address) find_image_at_address(addr_t address)
{ {
struct hash_iterator iterator; struct elf_image_info *image = NULL;
struct elf_image_info *image;
#if KDEBUG #if KDEBUG
if (!debug_debugger_running()) if (!debug_debugger_running())
ASSERT_LOCKED_MUTEX(&sImageMutex); ASSERT_LOCKED_MUTEX(&sImageMutex);
#endif #endif
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
// get image that may contain the address // get image that may contain the address
while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) while (iterator.HasNext()) {
!= NULL) { image = iterator.Next();
if ((address >= image->text_region.start && address if ((address >= image->text_region.start && address
<= (image->text_region.start + image->text_region.size)) <= (image->text_region.start + image->text_region.size))
|| (address >= image->data_region.start || (address >= image->data_region.start
@@ -191,7 +186,6 @@ find_image_at_address(addr_t address)
break; break;
} }
hash_close(sImagesHash, &iterator, false);
return image; return image;
} }
@@ -234,26 +228,24 @@ dump_address_info(int argc, char **argv)
static struct elf_image_info * static struct elf_image_info *
find_image(image_id id) find_image(image_id id)
{ {
return (elf_image_info *)hash_lookup(sImagesHash, (void *)(addr_t)id); return sImagesHash->Lookup(id);
} }
static struct elf_image_info * static struct elf_image_info *
find_image_by_vnode(void *vnode) find_image_by_vnode(void *vnode)
{ {
struct hash_iterator iterator; struct elf_image_info *image = NULL;
struct elf_image_info *image;
mutex_lock(&sImageMutex); mutex_lock(&sImageMutex);
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) while (iterator.HasNext()) {
!= NULL) { image = iterator.Next();
if (image->vnode == vnode) if (image->vnode == vnode)
break; break;
} }
hash_close(sImagesHash, &iterator, false);
mutex_unlock(&sImageMutex); mutex_unlock(&sImageMutex);
return image; return image;
@@ -357,14 +349,13 @@ dump_symbol(int argc, char **argv)
} }
struct elf_image_info *image = NULL; struct elf_image_info *image = NULL;
struct hash_iterator iterator;
const char *pattern = argv[1]; const char *pattern = argv[1];
void* symbolAddress = NULL; void* symbolAddress = NULL;
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) while (iterator.HasNext()) {
!= NULL) { image = iterator.Next();
if (image->num_debug_symbols > 0) { if (image->num_debug_symbols > 0) {
// search extended debug symbol table (contains static symbols) // search extended debug symbol table (contains static symbols)
for (uint32 i = 0; i < image->num_debug_symbols; i++) { for (uint32 i = 0; i < image->num_debug_symbols; i++) {
@@ -396,7 +387,6 @@ dump_symbol(int argc, char **argv)
} }
} }
} }
hash_close(sImagesHash, &iterator, false);
if (symbolAddress != NULL) if (symbolAddress != NULL)
set_debug_variable("_", (addr_t)symbolAddress); set_debug_variable("_", (addr_t)symbolAddress);
@@ -409,7 +399,6 @@ static int
dump_symbols(int argc, char **argv) dump_symbols(int argc, char **argv)
{ {
struct elf_image_info *image = NULL; struct elf_image_info *image = NULL;
struct hash_iterator iterator;
uint32 i; uint32 i;
// if the argument looks like a hex number, treat it as such // if the argument looks like a hex number, treat it as such
@@ -420,22 +409,21 @@ dump_symbols(int argc, char **argv)
if (IS_KERNEL_ADDRESS(num)) { if (IS_KERNEL_ADDRESS(num)) {
// find image at address // find image at address
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, while (iterator.HasNext()) {
&iterator)) != NULL) { image = iterator.Next();
if (image->text_region.start <= num if (image->text_region.start <= num
&& image->text_region.start + image->text_region.size && image->text_region.start + image->text_region.size
>= num) >= num)
break; break;
} }
hash_close(sImagesHash, &iterator, false);
if (image == NULL) { if (image == NULL) {
kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n", kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
num); num);
} }
} else { } else {
image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); image = sImagesHash->Lookup(num);
if (image == NULL) { if (image == NULL) {
kprintf("image %#" B_PRIxADDR " doesn't exist in the " kprintf("image %#" B_PRIxADDR " doesn't exist in the "
"kernel!\n", num); "kernel!\n", num);
@@ -443,13 +431,12 @@ dump_symbols(int argc, char **argv)
} }
} else { } else {
// look for image by name // look for image by name
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, while (iterator.HasNext()) {
&iterator)) != NULL) { image = iterator.Next();
if (!strcmp(image->name, argv[1])) if (!strcmp(image->name, argv[1]))
break; break;
} }
hash_close(sImagesHash, &iterator, false);
if (image == NULL) if (image == NULL)
kprintf("No image \"%s\" found in kernel!\n", argv[1]); kprintf("No image \"%s\" found in kernel!\n", argv[1]);
@@ -545,7 +532,6 @@ dump_image_info(struct elf_image_info *image)
static int static int
dump_image(int argc, char **argv) dump_image(int argc, char **argv)
{ {
struct hash_iterator iterator;
struct elf_image_info *image; struct elf_image_info *image;
// if the argument looks like a hex number, treat it as such // if the argument looks like a hex number, treat it as such
@@ -556,7 +542,7 @@ dump_image(int argc, char **argv)
// semi-hack // semi-hack
dump_image_info((struct elf_image_info *)num); dump_image_info((struct elf_image_info *)num);
} else { } else {
image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); image = sImagesHash->Lookup(num);
if (image == NULL) { if (image == NULL) {
kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n", kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
num); num);
@@ -568,14 +554,13 @@ dump_image(int argc, char **argv)
kprintf("loaded kernel images:\n"); kprintf("loaded kernel images:\n");
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) while (iterator.HasNext()) {
!= NULL) { image = iterator.Next();
kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name); kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
} }
hash_close(sImagesHash, &iterator, false);
return 0; return 0;
} }
@@ -1767,11 +1752,10 @@ addr_t
elf_debug_lookup_symbol(const char* searchName) elf_debug_lookup_symbol(const char* searchName)
{ {
struct elf_image_info *image = NULL; struct elf_image_info *image = NULL;
struct hash_iterator iterator;
hash_open(sImagesHash, &iterator); ImageHash::Iterator iterator(sImagesHash);
while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) while (iterator.HasNext()) {
!= NULL) { image = iterator.Next();
if (image->num_debug_symbols > 0) { if (image->num_debug_symbols > 0) {
// search extended debug symbol table (contains static symbols) // search extended debug symbol table (contains static symbols)
for (uint32 i = 0; i < image->num_debug_symbols; i++) { for (uint32 i = 0; i < image->num_debug_symbols; i++) {
@@ -1795,7 +1779,6 @@ elf_debug_lookup_symbol(const char* searchName)
} }
} }
} }
hash_close(sImagesHash, &iterator, false);
return 0; return 0;
} }
@@ -2572,9 +2555,12 @@ elf_init(kernel_args *args)
image_init(); image_init();
sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash); sImagesHash = new ImageHash();
if (sImagesHash == NULL) if (sImagesHash == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
if (init != B_OK)
return init;
// Build a image structure for the kernel, which has already been loaded. // Build a image structure for the kernel, which has already been loaded.
// The preloaded_images were already prepared by the VM. // The preloaded_images were already prepared by the VM.