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