Staging: tidspbridge: Use hashtable implementation

Use upstream hashtable implementation instead of generic code

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ivaylo Dimitrov 2014-01-06 01:17:27 +02:00 коммит произвёл Greg Kroah-Hartman
Родитель 3a21f00a50
Коммит d305558530
3 изменённых файлов: 97 добавлений и 138 удалений

Просмотреть файл

@ -14,56 +14,45 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/ */
#include <linux/types.h> #include <linux/err.h>
#include <linux/hashtable.h>
#include <linux/slab.h>
#include <dspbridge/host_os.h> struct gh_node {
#include <dspbridge/gh.h> struct hlist_node hl;
u8 data[0];
struct element {
struct element *next;
u8 data[1];
}; };
#define GH_HASH_ORDER 8
struct gh_t_hash_tab { struct gh_t_hash_tab {
u16 max_bucket; u32 val_size;
u16 val_size; DECLARE_HASHTABLE(hash_table, GH_HASH_ORDER);
struct element **buckets; u32 (*hash)(const void *key);
u16(*hash) (void *, u16); bool (*match)(const void *key, const void *value);
bool(*match) (void *, void *); void (*delete)(void *key);
void (*delete) (void *);
}; };
static void noop(void *p);
/* /*
* ======== gh_create ======== * ======== gh_create ========
*/ */
struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, struct gh_t_hash_tab *gh_create(u32 val_size, u32 (*hash)(const void *),
u16(*hash) (void *, u16), bool(*match) (void *, bool (*match)(const void *, const void *),
void *), void (*delete)(void *))
void (*delete) (void *))
{ {
struct gh_t_hash_tab *hash_tab; struct gh_t_hash_tab *hash_tab;
u16 i;
hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL); hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL);
if (hash_tab == NULL) if (!hash_tab)
return NULL; return ERR_PTR(-ENOMEM);
hash_tab->max_bucket = max_bucket;
hash_init(hash_tab->hash_table);
hash_tab->val_size = val_size; hash_tab->val_size = val_size;
hash_tab->hash = hash; hash_tab->hash = hash;
hash_tab->match = match; hash_tab->match = match;
hash_tab->delete = delete == NULL ? noop : delete; hash_tab->delete = delete;
hash_tab->buckets =
kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL);
if (hash_tab->buckets == NULL) {
gh_delete(hash_tab);
return NULL;
}
for (i = 0; i < max_bucket; i++)
hash_tab->buckets[i] = NULL;
return hash_tab; return hash_tab;
} }
@ -73,21 +62,16 @@ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size,
*/ */
void gh_delete(struct gh_t_hash_tab *hash_tab) void gh_delete(struct gh_t_hash_tab *hash_tab)
{ {
struct element *elem, *next; struct gh_node *n;
u16 i; struct hlist_node *tmp;
u32 i;
if (hash_tab != NULL) { if (hash_tab) {
if (hash_tab->buckets != NULL) { hash_for_each_safe(hash_tab->hash_table, i, tmp, n, hl) {
for (i = 0; i < hash_tab->max_bucket; i++) { hash_del(&n->hl);
for (elem = hash_tab->buckets[i]; elem != NULL; if (hash_tab->delete)
elem = next) { hash_tab->delete(n->data);
next = elem->next; kfree(n);
(*hash_tab->delete) (elem->data);
kfree(elem);
}
}
kfree(hash_tab->buckets);
} }
kfree(hash_tab); kfree(hash_tab);
@ -98,56 +82,39 @@ void gh_delete(struct gh_t_hash_tab *hash_tab)
* ======== gh_find ======== * ======== gh_find ========
*/ */
void *gh_find(struct gh_t_hash_tab *hash_tab, void *key) void *gh_find(struct gh_t_hash_tab *hash_tab, const void *key)
{ {
struct element *elem; struct gh_node *n;
u32 key_hash = hash_tab->hash(key);
elem = hash_tab->buckets[(*hash_tab->hash) (key, hash_tab->max_bucket)]; hash_for_each_possible(hash_tab->hash_table, n, hl, key_hash) {
if (hash_tab->match(key, n->data))
for (; elem; elem = elem->next) { return n->data;
if ((*hash_tab->match) (key, elem->data))
return elem->data;
} }
return NULL; return ERR_PTR(-ENODATA);
} }
/* /*
* ======== gh_insert ======== * ======== gh_insert ========
*/ */
void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value) void *gh_insert(struct gh_t_hash_tab *hash_tab, const void *key,
const void *value)
{ {
struct element *elem; struct gh_node *n;
u16 i;
char *src, *dst;
elem = kzalloc(sizeof(struct element) - 1 + hash_tab->val_size, n = kmalloc(sizeof(struct gh_node) + hash_tab->val_size,
GFP_KERNEL); GFP_KERNEL);
if (elem != NULL) {
dst = (char *)elem->data; if (!n)
src = (char *)value; return ERR_PTR(-ENOMEM);
for (i = 0; i < hash_tab->val_size; i++)
*dst++ = *src++;
i = (*hash_tab->hash) (key, hash_tab->max_bucket); INIT_HLIST_NODE(&n->hl);
elem->next = hash_tab->buckets[i]; hash_add(hash_tab->hash_table, &n->hl, hash_tab->hash(key));
hash_tab->buckets[i] = elem; memcpy(n->data, value, hash_tab->val_size);
return elem->data; return n->data;
}
return NULL;
}
/*
* ======== noop ========
*/
/* ARGSUSED */
static void noop(void *p)
{
p = p; /* stifle compiler warning */
} }
#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
@ -162,16 +129,13 @@ static void noop(void *p)
void gh_iterate(struct gh_t_hash_tab *hash_tab, void gh_iterate(struct gh_t_hash_tab *hash_tab,
void (*callback)(void *, void *), void *user_data) void (*callback)(void *, void *), void *user_data)
{ {
struct element *elem; struct gh_node *n;
u32 i; u32 i;
if (hash_tab && hash_tab->buckets) if (!hash_tab)
for (i = 0; i < hash_tab->max_bucket; i++) { return;
elem = hash_tab->buckets[i];
while (elem) { hash_for_each(hash_tab->hash_table, i, n, hl)
callback(&elem->data, user_data); callback(&n->data, user_data);
elem = elem->next;
}
}
} }
#endif #endif

Просмотреть файл

@ -18,13 +18,13 @@
#define GH_ #define GH_
#include <dspbridge/host_os.h> #include <dspbridge/host_os.h>
extern struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, extern struct gh_t_hash_tab *gh_create(u32 val_size,
u16(*hash) (void *, u16), u32 (*hash)(const void *), bool (*match)(const void *,
bool(*match) (void *, void *), const void *), void (*delete) (void *));
void (*delete) (void *));
extern void gh_delete(struct gh_t_hash_tab *hash_tab); extern void gh_delete(struct gh_t_hash_tab *hash_tab);
extern void *gh_find(struct gh_t_hash_tab *hash_tab, void *key); extern void *gh_find(struct gh_t_hash_tab *hash_tab, const void *key);
extern void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value); extern void *gh_insert(struct gh_t_hash_tab *hash_tab, const void *key,
const void *value);
#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
void gh_iterate(struct gh_t_hash_tab *hash_tab, void gh_iterate(struct gh_t_hash_tab *hash_tab,
void (*callback)(void *, void *), void *user_data); void (*callback)(void *, void *), void *user_data);

Просмотреть файл

@ -33,9 +33,6 @@
#include <dspbridge/dbll.h> #include <dspbridge/dbll.h>
#include <dspbridge/rmm.h> #include <dspbridge/rmm.h>
/* Number of buckets for symbol hash table */
#define MAXBUCKETS 211
/* Max buffer length */ /* Max buffer length */
#define MAXEXPR 128 #define MAXEXPR 128
@ -183,8 +180,8 @@ static int execute(struct dynamic_loader_initialize *this, ldr_addr start);
static void release(struct dynamic_loader_initialize *this); static void release(struct dynamic_loader_initialize *this);
/* symbol table hash functions */ /* symbol table hash functions */
static u16 name_hash(void *key, u16 max_bucket); static u32 name_hash(const void *key);
static bool name_match(void *key, void *sp); static bool name_match(const void *key, const void *sp);
static void sym_delete(void *value); static void sym_delete(void *value);
/* Symbol Redefinition */ /* Symbol Redefinition */
@ -277,17 +274,16 @@ bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name,
struct dbll_sym_val **sym_val) struct dbll_sym_val **sym_val)
{ {
struct dbll_symbol *sym; struct dbll_symbol *sym;
bool status = false;
sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name); sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name);
if (sym != NULL) { if (IS_ERR(sym))
*sym_val = &sym->value; return false;
status = true;
}
dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p, status 0x%x\n", *sym_val = &sym->value;
__func__, zl_lib, name, sym_val, status);
return status; dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p\n",
__func__, zl_lib, name, sym_val);
return true;
} }
/* /*
@ -312,7 +308,6 @@ bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name,
{ {
struct dbll_symbol *sym; struct dbll_symbol *sym;
char cname[MAXEXPR + 1]; char cname[MAXEXPR + 1];
bool status = false;
cname[0] = '_'; cname[0] = '_';
@ -321,13 +316,12 @@ bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name,
/* Check for C name, if not found */ /* Check for C name, if not found */
sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname); sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname);
if (IS_ERR(sym))
return false;
if (sym != NULL) { *sym_val = &sym->value;
*sym_val = &sym->value;
status = true;
}
return status; return true;
} }
/* /*
@ -416,12 +410,13 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
/* Create a hash table for symbols if not already created */ /* Create a hash table for symbols if not already created */
if (zl_lib->sym_tab == NULL) { if (zl_lib->sym_tab == NULL) {
got_symbols = false; got_symbols = false;
zl_lib->sym_tab = gh_create(MAXBUCKETS, zl_lib->sym_tab = gh_create(sizeof(struct dbll_symbol),
sizeof(struct dbll_symbol),
name_hash, name_hash,
name_match, sym_delete); name_match, sym_delete);
if (zl_lib->sym_tab == NULL) if (IS_ERR(zl_lib->sym_tab)) {
status = -ENOMEM; status = PTR_ERR(zl_lib->sym_tab);
zl_lib->sym_tab = NULL;
}
} }
/* /*
@ -593,10 +588,11 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
goto func_cont; goto func_cont;
zl_lib->sym_tab = zl_lib->sym_tab =
gh_create(MAXBUCKETS, sizeof(struct dbll_symbol), name_hash, gh_create(sizeof(struct dbll_symbol), name_hash, name_match,
name_match, sym_delete); sym_delete);
if (zl_lib->sym_tab == NULL) { if (IS_ERR(zl_lib->sym_tab)) {
status = -ENOMEM; status = PTR_ERR(zl_lib->sym_tab);
zl_lib->sym_tab = NULL;
} else { } else {
/* Do a fake load to get symbols - set write func to no_op */ /* Do a fake load to get symbols - set write func to no_op */
zl_lib->init.dl_init.writemem = no_op; zl_lib->init.dl_init.writemem = no_op;
@ -793,11 +789,10 @@ static int dof_open(struct dbll_library_obj *zl_lib)
/* /*
* ======== name_hash ======== * ======== name_hash ========
*/ */
static u16 name_hash(void *key, u16 max_bucket) static u32 name_hash(const void *key)
{ {
u16 ret; u32 hash;
u16 hash; const char *name = key;
char *name = (char *)key;
hash = 0; hash = 0;
@ -806,19 +801,16 @@ static u16 name_hash(void *key, u16 max_bucket)
hash ^= *name++; hash ^= *name++;
} }
ret = hash % max_bucket; return hash;
return ret;
} }
/* /*
* ======== name_match ======== * ======== name_match ========
*/ */
static bool name_match(void *key, void *sp) static bool name_match(const void *key, const void *sp)
{ {
if ((key != NULL) && (sp != NULL)) { if ((key != NULL) && (sp != NULL)) {
if (strcmp((char *)key, ((struct dbll_symbol *)sp)->name) == if (strcmp(key, ((struct dbll_symbol *)sp)->name) == 0)
0)
return true; return true;
} }
return false; return false;
@ -937,7 +929,6 @@ static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
*this, const char *name, *this, const char *name,
unsigned moduleid) unsigned moduleid)
{ {
struct dynload_symbol *ret_sym;
struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
struct dbll_library_obj *lib; struct dbll_library_obj *lib;
struct dbll_symbol *sym; struct dbll_symbol *sym;
@ -945,8 +936,10 @@ static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
lib = ldr_sym->lib; lib = ldr_sym->lib;
sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name); sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name);
ret_sym = (struct dynload_symbol *)&sym->value; if (IS_ERR(sym))
return ret_sym; return NULL;
return (struct dynload_symbol *)&sym->value;
} }
/* /*
@ -991,8 +984,10 @@ static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
sym_ptr = sym_ptr =
(struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name, (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name,
(void *)&symbol); (void *)&symbol);
if (sym_ptr == NULL) if (IS_ERR(sym_ptr)) {
kfree(symbol.name); kfree(symbol.name);
sym_ptr = NULL;
}
} }
if (sym_ptr != NULL) if (sym_ptr != NULL)