Initial kmemtrace userspace tools implementation.
[kmemtrace-user.git] / hashtable.c
blob5e987960b46a1fe255a5d390c8afa366f4d9f339
1 /*
2 * Copyright (C) 2008 Eduard-Gabriel Munteanu
4 * This file is released under GPL version 2.
5 */
7 /*
8 * Simple hashtable for storing pointer-sized keyed data.
9 */
11 #include <stdlib.h>
12 #include <stdint.h>
14 #include "hashtable.h"
16 struct ht_table *__ht_create(size_t bits, size_t entry_size, size_t key_offset)
18 struct ht_table *ret;
19 size_t n_entries = 1 << bits;
21 ret = malloc(sizeof(struct ht_table));
22 if (!ret)
23 return NULL;
24 ret->entry = calloc(n_entries, sizeof(struct ht_entry));
25 ret->bits = bits;
26 ret->entry_size = entry_size;
27 ret->key_offset = key_offset;
29 return ret;
32 void ht_destroy(struct ht_table *table)
34 free(table->entry);
35 free(table);
38 static inline unsigned long ht_hash(uint64_t key, size_t bits)
40 unsigned long ret = (unsigned long) key;
41 unsigned long mask = (1 << bits) - 1;
43 return (ret ^ (ret >> 16)) & mask;
46 static inline uint64_t *ht_get_key_ptr(struct ht_entry *entry,
47 struct ht_table *table)
49 return (uint64_t *) (entry->data + table->key_offset);
52 static inline void ht_set_key(struct ht_entry *entry,
53 struct ht_table *table,
54 uint64_t key)
56 *ht_get_key_ptr(entry, table) = key;
59 static inline uint64_t ht_get_key(struct ht_entry *entry,
60 struct ht_table *table)
62 return *ht_get_key_ptr(entry, table);
65 struct ht_entry *ht_update_entry(struct ht_table *table, uint64_t key)
67 struct ht_entry *entry;
68 unsigned long bucket = ht_hash(key, table->bits);
70 entry = &table->entry[bucket];
71 if (!entry->data) {
72 entry->data = calloc(1, table->entry_size);
73 ht_set_key(entry, table, key);
74 return entry;
75 } else {
76 while (entry) {
77 if (ht_get_key(entry, table) == key)
78 return entry;
79 if (!entry->next) {
80 entry->next =
81 calloc(1, sizeof(struct ht_entry));
82 entry->next->data =
83 calloc(1, table->entry_size);
84 ht_set_key(entry->next, table, key);
86 return entry->next;
89 entry = entry->next;
93 return NULL;
96 void ht_action(struct ht_table *table, void (*action)(struct ht_entry *, int))
98 unsigned long i;
99 struct ht_entry *entry, *next_entry;
101 for (i = 0; i < (1 << table->bits); i++) {
102 entry = &table->entry[i];
103 if (entry->data) {
104 next_entry = entry->next;
105 action(entry, 0);
106 entry = next_entry;
107 } else
108 continue;
109 while (entry) {
110 next_entry = entry->next;
111 action(entry, 1);
112 entry = next_entry;
117 void ht_free_entry(struct ht_entry *entry, int freeable)
119 free(entry->data);
120 if (freeable)
121 free(entry);