Fix extra decref of shared_page
[akaros.git] / kern / src / hashtable.c
1 /* Copyright (C) 2002, 2004 Christopher Clark  <firstname.lastname@cl.cam.ac.uk>
2  *
3  * Modified 2009 by Barret Rhoden <brho@cs.berkeley.edu>
4  * Changes include:
5  *   - No longer frees keys or values.  It's up to the client to do that.
6  *   - Uses the slab allocator for hash entry allocation.
7  *   - Merges the iterator code with the main hash table code, mostly to avoid
8  *   externing the hentry cache. */
9
10 #include <ros/common.h>
11 #include <hashtable.h>
12 #include <stdio.h>
13 #include <assert.h>
14 #include <string.h>
15 #include <slab.h>
16 #include <kmalloc.h>
17
18 /*
19 Credit for primes table: Aaron Krowne
20  http://br.endernet.org/~akrowne/
21  http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
22 */
23 static const unsigned int primes[] = {
24 53, 97, 193, 389,
25 769, 1543, 3079, 6151,
26 12289, 24593, 49157, 98317,
27 196613, 393241, 786433, 1572869,
28 3145739, 6291469, 12582917, 25165843,
29 50331653, 100663319, 201326611, 402653189,
30 805306457, 1610612741
31 };
32 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
33 #define APPLY_MAX_LOAD_FACTOR(size) \
34     ((size * 13)/20)
35 //const float max_load_factor = 0.65;
36
37 struct kmem_cache *hentry_cache;
38
39 /* Call this once on bootup, after initializing the slab allocator.  */
40 void hashtable_init(void)
41 {
42         hentry_cache = kmem_cache_create("hash_entry", sizeof(struct hash_entry),
43                                          __alignof__(struct hash_entry), 0, 0, 0);
44 }
45
46 /* Common hash/equals functions.  Don't call these directly. */
47 size_t __generic_hash(void *k)
48 {
49         /* 0x9e370001UL used by Linux (32 bit)
50          * (prime approx to the golden ratio to the max integer, IAW Knuth)
51          */
52         return (size_t)k * 0x9e370001UL;
53 }
54
55 ssize_t __generic_eq(void *k1, void *k2)
56 {
57         return k1 == k2;
58 }
59
60 /*****************************************************************************/
61 hashtable_t *
62 create_hashtable(size_t minsize,
63                  size_t (*hashf) (void*),
64                  ssize_t (*eqf) (void*,void*))
65 {
66     hashtable_t *h;
67     size_t pindex, size = primes[0];
68     /* Check requested hashtable isn't too large */
69     if (minsize > (1u << 30)) return NULL;
70     /* Enforce size as prime */
71     for (pindex=0; pindex < prime_table_length; pindex++) {
72         if (primes[pindex] > minsize) { size = primes[pindex]; break; }
73     }
74     h = (hashtable_t *)kmalloc(sizeof(hashtable_t), 0);
75     if (NULL == h) return NULL; /*oom*/
76     h->table = (hash_entry_t **)kmalloc(sizeof(hash_entry_t*) * size, 0);
77     if (NULL == h->table) { kfree(h); return NULL; } /*oom*/
78     memset(h->table, 0, size * sizeof(hash_entry_t *));
79     h->tablelength  = size;
80     h->primeindex   = pindex;
81     h->entrycount   = 0;
82     h->hashfn       = hashf;
83     h->eqfn         = eqf;
84     h->loadlimit    = APPLY_MAX_LOAD_FACTOR(size);
85     return h;
86 }
87
88 /*****************************************************************************/
89 static size_t
90 hash(hashtable_t *h, void *k)
91 {
92     /* Aim to protect against poor hash functions by adding logic here
93      * - logic taken from java 1.4 hashtable source */
94     size_t i = h->hashfn(k);
95     i += ~(i << 9);
96     i ^=  ((i >> 14) | (i << 18)); /* >>> */
97     i +=  (i << 4);
98     i ^=  ((i >> 10) | (i << 22)); /* >>> */
99     return i;
100 }
101
102 /*****************************************************************************/
103 static ssize_t
104 hashtable_expand(hashtable_t *h)
105 {
106     /* Double the size of the table to accomodate more entries */
107     hash_entry_t **newtable;
108     hash_entry_t *e;
109     hash_entry_t **pE;
110     size_t newsize, i, index;
111     /* Check we're not hitting max capacity */
112     if (h->primeindex == (prime_table_length - 1)) return 0;
113     newsize = primes[++(h->primeindex)];
114
115     newtable = (hash_entry_t **)kmalloc(sizeof(hash_entry_t*) * newsize, 0);
116     if (NULL != newtable)
117     {
118         memset(newtable, 0, newsize * sizeof(hash_entry_t*));
119         /* This algorithm is not 'stable'. ie. it reverses the list
120          * when it transfers entries between the tables */
121         for (i = 0; i < h->tablelength; i++) {
122             while (NULL != (e = h->table[i])) {
123                 h->table[i] = e->next;
124                 index = indexFor(newsize,e->h);
125                 e->next = newtable[index];
126                 newtable[index] = e;
127             }
128         }
129         kfree(h->table);
130         h->table = newtable;
131     }
132     /* Plan B: realloc instead */
133     else
134     {
135         newtable = (hash_entry_t**)
136                    krealloc(h->table, newsize*sizeof(hash_entry_t*), 0);
137         if (NULL == newtable) { (h->primeindex)--; return 0; }
138         h->table = newtable;
139         memset(newtable[h->tablelength], 0, newsize - h->tablelength);
140         for (i = 0; i < h->tablelength; i++) {
141             for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
142                 index = indexFor(newsize,e->h);
143                 if (index == i)
144                 {
145                     pE = &(e->next);
146                 }
147                 else
148                 {
149                     *pE = e->next;
150                     e->next = newtable[index];
151                     newtable[index] = e;
152                 }
153             }
154         }
155     }
156     h->tablelength = newsize;
157     h->loadlimit   = APPLY_MAX_LOAD_FACTOR(newsize);
158     return -1;
159 }
160
161 /*****************************************************************************/
162 size_t
163 hashtable_count(hashtable_t *h)
164 {
165     return h->entrycount;
166 }
167
168 /*****************************************************************************/
169 ssize_t
170 hashtable_insert(hashtable_t *h, void *k, void *v)
171 {
172     /* This method allows duplicate keys - but they shouldn't be used */
173     size_t index;
174     hash_entry_t *e;
175     if (++(h->entrycount) > h->loadlimit)
176     {
177         /* Ignore the return value. If expand fails, we should
178          * still try cramming just this value into the existing table
179          * -- we may not have memory for a larger table, but one more
180          * element may be ok. Next time we insert, we'll try expanding again.*/
181         hashtable_expand(h);
182     }
183     e = (hash_entry_t *)kmem_cache_alloc(hentry_cache, 0);
184     if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
185     e->h = hash(h,k);
186     index = indexFor(h->tablelength,e->h);
187     e->k = k;
188     e->v = v;
189     e->next = h->table[index];
190     h->table[index] = e;
191     return -1;
192 }
193
194 /*****************************************************************************/
195 void * /* returns value associated with key */
196 hashtable_search(hashtable_t *h, void *k)
197 {
198     hash_entry_t *e;
199     size_t hashvalue, index;
200     hashvalue = hash(h,k);
201     index = indexFor(h->tablelength,hashvalue);
202     e = h->table[index];
203     while (NULL != e)
204     {
205         /* Check hash value to short circuit heavier comparison */
206         if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
207         e = e->next;
208     }
209     return NULL;
210 }
211
212 /*****************************************************************************/
213 void * /* returns value associated with key */
214 hashtable_remove(hashtable_t *h, void *k)
215 {
216     /* TODO: consider compacting the table when the load factor drops enough,
217      *       or provide a 'compact' method. */
218
219     hash_entry_t *e;
220     hash_entry_t **pE;
221     void *v;
222     size_t hashvalue, index;
223
224     hashvalue = hash(h,k);
225     index = indexFor(h->tablelength,hash(h,k));
226     pE = &(h->table[index]);
227     e = *pE;
228     while (NULL != e)
229     {
230         /* Check hash value to short circuit heavier comparison */
231         if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
232         {
233             *pE = e->next;
234             h->entrycount--;
235             v = e->v;
236                         kmem_cache_free(hentry_cache, e);
237             return v;
238         }
239         pE = &(e->next);
240         e = e->next;
241     }
242     return NULL;
243 }
244
245 /*****************************************************************************/
246 /* destroy */
247 void
248 hashtable_destroy(hashtable_t *h)
249 {
250         if (hashtable_count(h))
251                 warn("Destroying a non-empty hashtable, clean up after yourself!\n");
252
253     size_t i;
254     hash_entry_t *e, *f;
255     hash_entry_t **table = h->table;
256         for (i = 0; i < h->tablelength; i++) {
257                 e = table[i];
258                 while (NULL != e) {
259                         f = e;
260                         e = e->next;
261                         kmem_cache_free(hentry_cache, f);
262                 }
263         }
264     kfree(h->table);
265     kfree(h);
266 }
267
268 /*****************************************************************************/
269 /* hashtable_iterator    - iterator constructor, be sure to kfree this when
270  * you're done.
271  *
272  * If the htable isn't empty, e and index will refer to the first entry. */
273
274 hashtable_itr_t *
275 hashtable_iterator(hashtable_t *h)
276 {
277     size_t i, tablelength;
278     hashtable_itr_t *itr = (hashtable_itr_t *)
279         kmalloc(sizeof(hashtable_itr_t), 0);
280     if (NULL == itr) return NULL;
281     itr->h = h;
282     itr->e = NULL;
283     itr->parent = NULL;
284     tablelength = h->tablelength;
285     itr->index = tablelength;
286     if (0 == h->entrycount) return itr;
287
288     for (i = 0; i < tablelength; i++)
289     {
290         if (NULL != h->table[i])
291         {
292             itr->e = h->table[i];
293             itr->index = i;
294             break;
295         }
296     }
297     return itr;
298 }
299
300 /*****************************************************************************/
301 /* key      - return the key of the (key,value) pair at the current position */
302 /* value    - return the value of the (key,value) pair at the current position */
303
304 void *
305 hashtable_iterator_key(hashtable_itr_t *i)
306 { return i->e->k; }
307
308 void *
309 hashtable_iterator_value(hashtable_itr_t *i)
310 { return i->e->v; }
311
312 /*****************************************************************************/
313 /* advance - advance the iterator to the next element
314  *           returns zero if advanced to end of table */
315
316 ssize_t
317 hashtable_iterator_advance(hashtable_itr_t *itr)
318 {
319     size_t j,tablelength;
320     hash_entry_t **table;
321     hash_entry_t *next;
322     if (NULL == itr->e) return 0; /* stupidity check */
323
324     next = itr->e->next;
325     if (NULL != next)
326     {
327         itr->parent = itr->e;
328         itr->e = next;
329         return -1;
330     }
331     tablelength = itr->h->tablelength;
332     itr->parent = NULL;
333     if (tablelength <= (j = ++(itr->index)))
334     {
335         itr->e = NULL;
336         return 0;
337     }
338     table = itr->h->table;
339     while (NULL == (next = table[j]))
340     {
341         if (++j >= tablelength)
342         {
343             itr->index = tablelength;
344             itr->e = NULL;
345             return 0;
346         }
347     }
348     itr->index = j;
349     itr->e = next;
350     return -1;
351 }
352
353 /*****************************************************************************/
354 /* remove - remove the entry at the current iterator position
355  *          and advance the iterator, if there is a successive
356  *          element.
357  *          If you want the value, read it before you remove:
358  *          beware memory leaks if you don't.
359  *          Returns zero if end of iteration. */
360
361 ssize_t
362 hashtable_iterator_remove(hashtable_itr_t *itr)
363 {
364     hash_entry_t *remember_e, *remember_parent;
365     ssize_t ret;
366
367     /* Do the removal */
368     if (NULL == (itr->parent))
369     {
370         /* element is head of a chain */
371         itr->h->table[itr->index] = itr->e->next;
372     } else {
373         /* element is mid-chain */
374         itr->parent->next = itr->e->next;
375     }
376     /* itr->e is now outside the hashtable */
377     remember_e = itr->e;
378     itr->h->entrycount--;
379
380     /* Advance the iterator, correcting the parent */
381     remember_parent = itr->parent;
382     ret = hashtable_iterator_advance(itr);
383     if (itr->parent == remember_e) { itr->parent = remember_parent; }
384         kmem_cache_free(hentry_cache, remember_e);
385     return ret;
386 }
387
388 /*****************************************************************************/
389 ssize_t /* returns zero if not found */
390 hashtable_iterator_search(hashtable_itr_t *itr,
391                           hashtable_t *h, void *k)
392 {
393     hash_entry_t *e, *parent;
394     size_t hashvalue, index;
395
396     hashvalue = hash(h,k);
397     index = indexFor(h->tablelength,hashvalue);
398
399     e = h->table[index];
400     parent = NULL;
401     while (NULL != e)
402     {
403         /* Check hash value to short circuit heavier comparison */
404         if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
405         {
406             itr->index = index;
407             itr->e = e;
408             itr->parent = parent;
409             itr->h = h;
410             return -1;
411         }
412         parent = e;
413         e = e->next;
414     }
415     return 0;
416 }
417
418 /* Runs func on each member of the hash table */
419 void hash_for_each(struct hashtable *hash, void func(void *, void *),
420                                    void *opaque)
421 {
422         if (hashtable_count(hash)) {
423                 struct hashtable_itr *iter = hashtable_iterator(hash);
424                 do {
425                         void *item = hashtable_iterator_value(iter);
426                         func(item, opaque);
427                 } while (hashtable_iterator_advance(iter));
428                 kfree(iter);
429         }
430 }
431
432 /* Runs func on each member of the hash table, removing the item after
433  * processing it.  Make sure func frees the item, o/w you'll leak. */
434 void hash_for_each_remove(struct hashtable *hash, void func(void *, void *),
435                                                   void *opaque)
436 {
437         if (hashtable_count(hash)) {
438                 struct hashtable_itr *iter = hashtable_iterator(hash);
439                 do {
440                         void *item = hashtable_iterator_value(iter);
441                         func(item, opaque);
442                 } while (hashtable_iterator_remove(iter));
443                 kfree(iter);
444         }
445 }
446
447 /*
448  * Copyright (c) 2002, 2004, Christopher Clark
449  * All rights reserved.
450  *
451  * Redistribution and use in source and binary forms, with or without
452  * modification, are permitted provided that the following conditions
453  * are met:
454  *
455  * * Redistributions of source code must retain the above copyright
456  * notice, this list of conditions and the following disclaimer.
457  *
458  * * Redistributions in binary form must reproduce the above copyright
459  * notice, this list of conditions and the following disclaimer in the
460  * documentation and/or other materials provided with the distribution.
461  *
462  * * Neither the name of the original author; nor the names of any contributors
463  * may be used to endorse or promote products derived from this software
464  * without specific prior written permission.
465  *
466  *
467  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
468  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
469  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
470  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
471  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
472  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
473  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
474  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
475  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
476  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
477  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
478 */