diff options
author | James Morris <james.l.morris@oracle.com> | 2014-04-14 11:23:14 +1000 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-04-14 11:23:14 +1000 |
commit | ecd740c6f2f092b90b95fa35f757973589eaaca2 (patch) | |
tree | ce02b1e18c4fc5729699251460cd8be7604d8401 /drivers/staging/tidspbridge/gen/gh.c | |
parent | selinux: correctly label /proc inodes in use before the policy is loaded (diff) | |
parent | Linux 3.14 (diff) | |
download | linux-dev-ecd740c6f2f092b90b95fa35f757973589eaaca2.tar.xz linux-dev-ecd740c6f2f092b90b95fa35f757973589eaaca2.zip |
Merge commit 'v3.14' into next
Diffstat (limited to 'drivers/staging/tidspbridge/gen/gh.c')
-rw-r--r-- | drivers/staging/tidspbridge/gen/gh.c | 148 |
1 files changed, 56 insertions, 92 deletions
diff --git a/drivers/staging/tidspbridge/gen/gh.c b/drivers/staging/tidspbridge/gen/gh.c index 25eaef782aaa..936470cb608e 100644 --- a/drivers/staging/tidspbridge/gen/gh.c +++ b/drivers/staging/tidspbridge/gen/gh.c @@ -14,56 +14,45 @@ * 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> -#include <dspbridge/gh.h> - -struct element { - struct element *next; - u8 data[1]; +struct gh_node { + struct hlist_node hl; + u8 data[0]; }; +#define GH_HASH_ORDER 8 + struct gh_t_hash_tab { - u16 max_bucket; - u16 val_size; - struct element **buckets; - u16(*hash) (void *, u16); - bool(*match) (void *, void *); - void (*delete) (void *); + u32 val_size; + DECLARE_HASHTABLE(hash_table, GH_HASH_ORDER); + u32 (*hash)(const void *key); + bool (*match)(const void *key, const void *value); + void (*delete)(void *key); }; -static void noop(void *p); - /* * ======== gh_create ======== */ -struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, - u16(*hash) (void *, u16), bool(*match) (void *, - void *), - void (*delete) (void *)) +struct gh_t_hash_tab *gh_create(u32 val_size, u32 (*hash)(const void *), + bool (*match)(const void *, const void *), + void (*delete)(void *)) { struct gh_t_hash_tab *hash_tab; - u16 i; + hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL); - if (hash_tab == NULL) - return NULL; - hash_tab->max_bucket = max_bucket; + if (!hash_tab) + return ERR_PTR(-ENOMEM); + + hash_init(hash_tab->hash_table); + hash_tab->val_size = val_size; hash_tab->hash = hash; hash_tab->match = match; - hash_tab->delete = delete == NULL ? noop : 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; + hash_tab->delete = delete; 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) { - struct element *elem, *next; - u16 i; - - if (hash_tab != NULL) { - if (hash_tab->buckets != NULL) { - for (i = 0; i < hash_tab->max_bucket; i++) { - for (elem = hash_tab->buckets[i]; elem != NULL; - elem = next) { - next = elem->next; - (*hash_tab->delete) (elem->data); - kfree(elem); - } - } - - kfree(hash_tab->buckets); + struct gh_node *n; + struct hlist_node *tmp; + u32 i; + + if (hash_tab) { + hash_for_each_safe(hash_tab->hash_table, i, tmp, n, hl) { + hash_del(&n->hl); + if (hash_tab->delete) + hash_tab->delete(n->data); + kfree(n); } kfree(hash_tab); @@ -98,56 +82,39 @@ void gh_delete(struct gh_t_hash_tab *hash_tab) * ======== 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)]; - - for (; elem; elem = elem->next) { - if ((*hash_tab->match) (key, elem->data)) - return elem->data; + hash_for_each_possible(hash_tab->hash_table, n, hl, key_hash) { + if (hash_tab->match(key, n->data)) + return n->data; } - return NULL; + return ERR_PTR(-ENODATA); } /* * ======== 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; - u16 i; - char *src, *dst; + struct gh_node *n; - elem = kzalloc(sizeof(struct element) - 1 + hash_tab->val_size, + n = kmalloc(sizeof(struct gh_node) + hash_tab->val_size, GFP_KERNEL); - if (elem != NULL) { - - dst = (char *)elem->data; - src = (char *)value; - for (i = 0; i < hash_tab->val_size; i++) - *dst++ = *src++; - i = (*hash_tab->hash) (key, hash_tab->max_bucket); - elem->next = hash_tab->buckets[i]; - hash_tab->buckets[i] = elem; + if (!n) + return ERR_PTR(-ENOMEM); - return elem->data; - } - - return NULL; -} + INIT_HLIST_NODE(&n->hl); + hash_add(hash_tab->hash_table, &n->hl, hash_tab->hash(key)); + memcpy(n->data, value, hash_tab->val_size); -/* - * ======== noop ======== - */ -/* ARGSUSED */ -static void noop(void *p) -{ - p = p; /* stifle compiler warning */ + return n->data; } #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE @@ -162,16 +129,13 @@ static void noop(void *p) void gh_iterate(struct gh_t_hash_tab *hash_tab, void (*callback)(void *, void *), void *user_data) { - struct element *elem; + struct gh_node *n; u32 i; - if (hash_tab && hash_tab->buckets) - for (i = 0; i < hash_tab->max_bucket; i++) { - elem = hash_tab->buckets[i]; - while (elem) { - callback(&elem->data, user_data); - elem = elem->next; - } - } + if (!hash_tab) + return; + + hash_for_each(hash_tab->hash_table, i, n, hl) + callback(&n->data, user_data); } #endif |