voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

commit a4278f3bfd32165c8bbd453a6a3930f92165bbfa
parent d573437808d978dea443e72ec1b3ddc62475910d
Author: sin <sin@2f30.org>
Date:   Fri, 26 Jul 2013 15:32:59 +0100

Simplify hash table implementation

Forget about the open-addressing based implementation.
Now we've got a hash table with a fixed number of buckets.

In this implementation we allow duplicates.

We still need to constify some of the parameters.

Diffstat:
Minclude/hash.h | 16++++++++--------
Mkernel/hash.c | 205++++++++++++++++++++++++++++++++++++++-----------------------------------------
2 files changed, 106 insertions(+), 115 deletions(-)

diff --git a/include/hash.h b/include/hash.h @@ -3,15 +3,15 @@ #include <inttypes.h> -struct hent_ops { - unsigned long (*hash)(void *data, size_t siz); - int (*cmp)(void *src, void *dst, size_t siz); +struct hops { + long (*hash)(void *data, size_t siz); + int (*cmp)(void *src, void *dst, size_t siz); }; -struct htable *init_htable(struct hent_ops *hent_ops, size_t n); -void free_htable(struct htable *htable); -int search_htable(struct htable *htable, void *data, size_t siz); -int insert_htable(struct htable *htable, void *data, size_t siz); -int remove_htable(struct htable *htable, void *data, size_t siz); +struct htable *init_htable(struct hops *ops, size_t siz); +void free_htable(struct htable *ht); +long search_htable(struct htable *ht, void *data, size_t siz); +long insert_htable(struct htable *ht, void *data, size_t siz); +long remove_htable(struct htable *ht, void *data, size_t siz); #endif /* __HASH_H */ diff --git a/kernel/hash.c b/kernel/hash.c @@ -1,148 +1,139 @@ -/* Simple hash table implementation using open-addressing */ #include <kernel.h> -#include <mmu.h> #include <alloc.h> #include <spinlock.h> #include <hash.h> -enum hent_state { - UNUSED, - USED, - REMOVED, -}; +enum { CHAIN_SIZ = 32 }; -struct hent { - void *data; - size_t siz; - enum hent_state state; +struct hentry { + struct { + void *data; + size_t siz; + } c[CHAIN_SIZ]; }; struct htable { - struct hent *hent; - struct hent_ops *hent_ops; + struct hentry *e; + struct hops *ops; size_t siz; spinlock_t lock; }; struct htable * -init_htable(struct hent_ops *hent_ops, size_t n) +init_htable(struct hops *ops, size_t siz) { - struct htable *htable; - size_t i; + struct htable *ht; + size_t i, j; + + if (!ops || !ops->hash || !ops->cmp || !siz) + return NULL; - htable = kmalloc(sizeof(*htable)); - if (!htable) + ht = kmalloc(sizeof(*ht)); + if (!ht) return NULL; - htable->hent = kcalloc(n, sizeof(struct hent)); - if (!htable->hent) { - kfree(htable); + ht->e = kmalloc(siz * sizeof(*ht->e)); + if (!ht->e) { + kfree(ht); return NULL; } - for (i = 0; i < n; i++) - htable->hent[i].state = UNUSED; - htable->siz = n; - htable->hent_ops = hent_ops; - spinlock_init(&htable->lock); - return htable; + for (i = 0; i < siz; i++) { + for (j = 0; j < CHAIN_SIZ; j++) { + ht->e[i].c[j].data = NULL; + ht->e[i].c[j].siz = 0; + } + } + ht->siz = siz; + ht->ops = ops; + spinlock_init(&ht->lock); + return ht; } void -free_htable(struct htable *htable) +kfree_htable(struct htable *ht) { - kfree(htable->hent); - kfree(htable); + kfree(ht->e); + kfree(ht); } -/* Search the hash table for the given entry. Returns -1 - * on failure and the index of the entry on success. */ -int -search_htable(struct htable *htable, void *data, size_t siz) +long +search_htable(struct htable *ht, void *data, size_t siz) { - struct hent *hent; - struct hent_ops *ops; - size_t idx, i, j; - - spinlock_lock(&htable->lock); - ops = htable->hent_ops; - idx = ops->hash(data, siz) % htable->siz; - j = idx; - for (i = 0; i < htable->siz; i++) { - hent = &htable->hent[j]; - if (hent->state == UNUSED) { - spinlock_unlock(&htable->lock); - return -1; - } - if (hent->state == USED && !ops->cmp(hent->data, data, siz)) { - spinlock_unlock(&htable->lock); - return j; + struct hentry *e; + struct hops *ops; + long i; + size_t j; + + if (!ht || !data || !siz) + return -1; + + spinlock_lock(&ht->lock); + ops = ht->ops; + i = ops->hash(data, siz) % ht->siz; + e = &ht->e[i]; + for (j = 0; j < CHAIN_SIZ; j++) { + if (!e->c[j].data || e->c[j].siz != siz) + continue; + if (!ops->cmp(e->c[j].data, data, siz)) { + spinlock_unlock(&ht->lock); + return i; } - j++; - j %= htable->siz; } - spinlock_unlock(&htable->lock); + spinlock_unlock(&ht->lock); return -1; } -/* Insert the given entry in the hash table. Ignore duplicates. - * Return the index on a successful insertion, -1 if the table is full. */ -int -insert_htable(struct htable *htable, void *data, size_t siz) +long +insert_htable(struct htable *ht, void *data, size_t siz) { - struct hent *hent; - struct hent_ops *ops; - size_t idx, i, j; - - spinlock_lock(&htable->lock); - ops = htable->hent_ops; - idx = ops->hash(data, siz) % htable->siz; - j = idx; - for (i = 0; i < htable->siz; i++) { - hent = &htable->hent[j]; - if (hent->state == USED && !ops->cmp(hent->data, data, siz)) { - spinlock_unlock(&htable->lock); - return j; - } - if (hent->state == UNUSED || hent->state == REMOVED) { - hent->data = data; - hent->siz = siz; - hent->state = USED; - spinlock_unlock(&htable->lock); - return j; - } - j++; - j %= htable->siz; + struct hentry *e; + struct hops *ops; + long i; + size_t j; + + if (!ht || !data || !siz) + return -1; + + spinlock_lock(&ht->lock); + ops = ht->ops; + i = ops->hash(data, siz) % ht->siz; + e = &ht->e[i]; + for (j = 0; j < CHAIN_SIZ; j++) { + if (e->c[j].data) + continue; + e->c[j].data = data; + e->c[j].siz = siz; + spinlock_unlock(&ht->lock); + return i; } - spinlock_unlock(&htable->lock); + spinlock_unlock(&ht->lock); return -1; } -/* Remove an entry from the hash table. Return -1 on failure, - * and the index of the entry on success. */ -int -remove_htable(struct htable *htable, void *data, size_t siz) +long +remove_htable(struct htable *ht, void *data, size_t siz) { - struct hent *hent; - struct hent_ops *ops; - size_t idx, i, j; - - spinlock_lock(&htable->lock); - ops = htable->hent_ops; - idx = ops->hash(data, siz) % htable->siz; - j = idx; - for (i = 0; i < htable->siz; i++) { - hent = &htable->hent[j]; - if (hent->state == UNUSED) { - spinlock_unlock(&htable->lock); - return -1; - } - if (hent->state == USED && !ops->cmp(hent->data, data, siz)) { - hent->state = REMOVED; - spinlock_unlock(&htable->lock); - return j; + struct hentry *e; + struct hops *ops; + long i; + size_t j; + + if (!ht || !data || !siz) + return -1; + + spinlock_lock(&ht->lock); + ops = ht->ops; + i = ops->hash(data, siz) % ht->siz; + e = &ht->e[i]; + for (j = 0; j < CHAIN_SIZ; j++) { + if (!e->c[j].data || e->c[j].siz != siz) + continue; + if (!ops->cmp(e->c[j].data, data, siz)) { + e->c[j].data = NULL; + e->c[j].siz = 0; + spinlock_unlock(&ht->lock); + return i; } - j++; - j %= htable->siz; } - spinlock_unlock(&htable->lock); + spinlock_unlock(&ht->lock); return -1; }