Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fe74dc774f4be236805d2cc9e06c068864fa1b89
[palacios.git] / palacios / src / palacios / vmm_hashtable.c
1 /*
2   Copyright (c) 2002, 2004, Christopher Clark
3   All rights reserved.
4   
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8   
9   * Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11   
12   * Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in the
14     documentation and/or other materials provided with the distribution.
15   
16   * Neither the name of the original author; nor the names of any contributors
17     may be used to endorse or promote products derived from this software
18     without specific prior written permission.
19   
20   
21   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* Modifications made by Jack Lange <jarusl@cs.northwestern.edu> */
35
36
37
38 #include <palacios/vmm.h>
39 #include <palacios/vmm_hashtable.h>
40 #include <palacios/vmm_string.h>
41
42
43
44
45
46 struct hash_entry {
47     addr_t key;
48     addr_t value;
49     uint_t hash;
50     struct hash_entry * next;
51 };
52
53 struct hashtable {
54     uint_t table_length;
55     struct hash_entry ** table;
56     uint_t entry_count;
57     uint_t load_limit;
58     uint_t prime_index;
59     uint_t (*hash_fn) (addr_t key);
60     int (*eq_fn) (addr_t key1, addr_t key2);
61 };
62
63
64
65 /* HASH FUNCTIONS */
66
67
68
69 uint_t do_hash(struct hashtable * htable, addr_t key) {
70     /* Aim to protect against poor hash functions by adding logic here
71      * - logic taken from java 1.4 hashtable source */
72     uint_t i = htable->hash_fn(key);
73     i += ~(i << 9);
74     i ^=  ((i >> 14) | (i << 18)); /* >>> */
75     i +=  (i << 4);
76     i ^=  ((i >> 10) | (i << 22)); /* >>> */
77
78     return i;
79 }
80
81
82 /* HASH AN UNSIGNED LONG */
83 /* LINUX UNSIGHED LONG HASH FUNCTION */
84 #ifdef __V3_32BIT__
85 /* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
86 #define GOLDEN_RATIO_PRIME 0x9e370001UL
87 #define BITS_PER_LONG 32
88 #elif  defined(__V3_64BIT__)
89 /*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
90 #define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
91 #define BITS_PER_LONG 64
92 #else
93 #error Define GOLDEN_RATIO_PRIME for your wordsize.
94 #endif
95
96 ulong_t hash_long(ulong_t val, uint_t bits) {
97     ulong_t hash = val;
98
99 #ifdef __V3_64BIT__
100     /*  Sigh, gcc can't optimise this alone like it does for 32 bits. */
101     ulong_t n = hash;
102     n <<= 18;
103     hash -= n;
104     n <<= 33;
105     hash -= n;
106     n <<= 3;
107     hash += n;
108     n <<= 3;
109     hash -= n;
110     n <<= 4;
111     hash += n;
112     n <<= 2;
113     hash += n;
114 #else
115     /* On some cpus multiply is faster, on others gcc will do shifts */
116     hash *= GOLDEN_RATIO_PRIME;
117 #endif
118
119     /* High bits are more random, so use them. */
120     return hash >> (BITS_PER_LONG - bits);
121 }
122
123 /* HASH GENERIC MEMORY BUFFER */
124 /* ELF HEADER HASH FUNCTION */
125 ulong_t hash_buffer(uchar_t * msg, uint_t length) {
126     ulong_t hash = 0;
127     ulong_t temp = 0;
128     uint_t i;
129
130     for (i = 0; i < length; i++) {
131         hash = (hash << 4) + *(msg + i) + i;
132         if ((temp = (hash & 0xF0000000))) {
133             hash ^= (temp >> 24);
134         }
135         hash &= ~temp;
136     }
137     return hash;
138 }
139
140
141
142 /*****************************************************************************/
143 /* indexFor */
144 static inline uint_t indexFor(uint_t table_length, uint_t hash_value) {
145     return (hash_value % table_length);
146 };
147
148 /* Only works if table_length == 2^N */
149 /*
150   static inline uint_t indexFor(uint_t table_length, uint_t hashvalue)
151   {
152   return (hashvalue & (table_length - 1u));
153   }
154 */
155
156 /*****************************************************************************/
157 #define freekey(X) V3_Free(X)
158 /*define freekey(X) ; */
159
160
161 static void * tmp_realloc(void * old_ptr, uint_t old_size, uint_t new_size) {
162     void * new_buf = V3_Malloc(new_size);
163
164     if (new_buf == NULL) {
165         return NULL;
166     }
167
168     memcpy(new_buf, old_ptr, old_size);
169     V3_Free(old_ptr);
170
171     return new_buf;
172 }
173
174
175 /*
176   Credit for primes table: Aaron Krowne
177   http://br.endernet.org/~akrowne/
178   http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
179 */
180 static const uint_t primes[] = { 
181     53, 97, 193, 389,
182     769, 1543, 3079, 6151,
183     12289, 24593, 49157, 98317,
184     196613, 393241, 786433, 1572869,
185     3145739, 6291469, 12582917, 25165843,
186     50331653, 100663319, 201326611, 402653189,
187     805306457, 1610612741 };
188
189
190 const uint_t prime_table_length = sizeof(primes) / sizeof(primes[0]);
191
192 const float max_load_factor = 0.65;
193
194 /*****************************************************************************/
195 struct hashtable * create_hashtable(uint_t min_size,
196                                     uint_t (*hash_fn) (addr_t),
197                                     int (*eq_fn) (addr_t, addr_t)) {
198     struct hashtable * htable;
199     uint_t prime_index;
200     uint_t size = primes[0];
201
202     /* Check requested hashtable isn't too large */
203     if (min_size > (1u << 30)) {
204         return NULL;
205     }
206
207     /* Enforce size as prime */
208     for (prime_index = 0; prime_index < prime_table_length; prime_index++) {
209         if (primes[prime_index] > min_size) { 
210             size = primes[prime_index]; 
211             break; 
212         }
213     }
214
215     htable = (struct hashtable *)V3_Malloc(sizeof(struct hashtable));
216
217     if (htable == NULL) {
218         return NULL; /*oom*/
219     }
220
221     htable->table = (struct hash_entry **)V3_Malloc(sizeof(struct hash_entry*) * size);
222
223     if (htable->table == NULL) { 
224         V3_Free(htable); 
225         return NULL;  /*oom*/
226     }
227
228
229     memset(htable->table, 0, size * sizeof(struct hash_entry *));
230
231     htable->table_length  = size;
232     htable->prime_index   = prime_index;
233     htable->entry_count   = 0;
234     htable->hash_fn       = hash_fn;
235     htable->eq_fn         = eq_fn;
236     htable->load_limit    = (uint_t) v3_ceil((double)(size * max_load_factor));
237
238     return htable;
239 }
240
241
242
243 /*****************************************************************************/
244 static int hashtable_expand(struct hashtable * htable) {
245     /* Double the size of the table to accomodate more entries */
246     struct hash_entry ** new_table;
247     struct hash_entry * tmp_entry;
248     struct hash_entry ** entry_ptr;
249     uint_t new_size;
250     uint_t i;
251     uint_t index;
252
253     /* Check we're not hitting max capacity */
254     if (htable->prime_index == (prime_table_length - 1)) {
255         return 0;
256     }
257
258     new_size = primes[++(htable->prime_index)];
259
260     new_table = (struct hash_entry **)V3_Malloc(sizeof(struct hash_entry*) * new_size);
261
262     if (new_table != NULL) {
263         memset(new_table, 0, new_size * sizeof(struct hash_entry *));
264         /* This algorithm is not 'stable'. ie. it reverses the list
265          * when it transfers entries between the tables */
266
267         for (i = 0; i < htable->table_length; i++) {
268
269             while ((tmp_entry = htable->table[i]) != NULL) {
270                 htable->table[i] = tmp_entry->next;
271            
272                 index = indexFor(new_size, tmp_entry->hash);
273             
274                 tmp_entry->next = new_table[index];
275             
276                 new_table[index] = tmp_entry;
277             }
278         }
279
280         V3_Free(htable->table);
281
282         htable->table = new_table;
283     } else {
284         /* Plan B: realloc instead */
285
286         //new_table = (struct hash_entry **)realloc(htable->table, new_size * sizeof(struct hash_entry *));
287         new_table = (struct hash_entry **)tmp_realloc(htable->table, primes[htable->prime_index - 1], 
288                                                       new_size * sizeof(struct hash_entry *));
289
290         if (new_table == NULL) {
291             (htable->prime_index)--;
292             return 0;
293         }
294
295         htable->table = new_table;
296
297         memset(new_table[htable->table_length], 0, new_size - htable->table_length);
298
299         for (i = 0; i < htable->table_length; i++) {
300
301             for (entry_ptr = &(new_table[i]), tmp_entry = *entry_ptr; 
302                  tmp_entry != NULL; 
303                  tmp_entry = *entry_ptr) {
304
305                 index = indexFor(new_size, tmp_entry->hash);
306
307                 if (i == index) {
308                     entry_ptr = &(tmp_entry->next);
309                 } else {
310                     *entry_ptr = tmp_entry->next;
311                     tmp_entry->next = new_table[index];
312                     new_table[index] = tmp_entry;
313                 }
314             }
315         }
316     }
317
318     htable->table_length = new_size;
319
320     htable->load_limit   = (uint_t) v3_ceil(new_size * max_load_factor);
321
322     return -1;
323 }
324
325 /*****************************************************************************/
326 uint_t hashtable_count(struct hashtable * htable) {
327     return htable->entry_count;
328 }
329
330 /*****************************************************************************/
331 int hashtable_insert(struct hashtable * htable, addr_t key, addr_t value) {
332     /* This method allows duplicate keys - but they shouldn't be used */
333     uint_t index;
334     struct hash_entry * new_entry;
335
336     if (++(htable->entry_count) > htable->load_limit) {
337         /* Ignore the return value. If expand fails, we should
338          * still try cramming just this value into the existing table
339          * -- we may not have memory for a larger table, but one more
340          * element may be ok. Next time we insert, we'll try expanding again.*/
341         hashtable_expand(htable);
342     }
343
344
345     new_entry = (struct hash_entry *)V3_Malloc(sizeof(struct hash_entry));
346
347     if (new_entry == NULL) { 
348         (htable->entry_count)--; 
349         return 0; /*oom*/
350     }
351
352     new_entry->hash = do_hash(htable, key);
353
354     index = indexFor(htable->table_length, new_entry->hash);
355
356     new_entry->key = key;
357     new_entry->value = value;
358
359     new_entry->next = htable->table[index];
360
361     htable->table[index] = new_entry;
362
363     return -1;
364 }
365
366
367
368 int hashtable_change(struct hashtable * htable, addr_t key, addr_t value, int free_value) {
369     struct hash_entry * tmp_entry;
370     uint_t hash_value;
371     uint_t index;
372
373     hash_value = do_hash(htable, key);
374
375     index = indexFor(htable->table_length, hash_value);
376
377     tmp_entry = htable->table[index];
378
379     while (tmp_entry != NULL) {
380         /* Check hash value to short circuit heavier comparison */
381         if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
382
383             if (free_value) {
384                 V3_Free((void *)(tmp_entry->value));
385             }
386
387             tmp_entry->value = value;
388             return -1;
389         }
390         tmp_entry = tmp_entry->next;
391     }
392     return 0;
393 }
394
395
396
397 int hashtable_inc(struct hashtable * htable, addr_t key, addr_t value) {
398     struct hash_entry * tmp_entry;
399     uint_t hash_value;
400     uint_t index;
401
402     hash_value = do_hash(htable, key);
403
404     index = indexFor(htable->table_length, hash_value);
405
406     tmp_entry = htable->table[index];
407
408     while (tmp_entry != NULL) {
409         /* Check hash value to short circuit heavier comparison */
410         if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
411
412             tmp_entry->value += value;
413             return -1;
414         }
415         tmp_entry = tmp_entry->next;
416     }
417     return 0;
418 }
419
420
421 int hashtable_dec(struct hashtable * htable, addr_t key, addr_t value) {
422     struct hash_entry * tmp_entry;
423     uint_t hash_value;
424     uint_t index;
425
426     hash_value = do_hash(htable, key);
427
428     index = indexFor(htable->table_length, hash_value);
429
430     tmp_entry = htable->table[index];
431
432     while (tmp_entry != NULL) {
433         /* Check hash value to short circuit heavier comparison */
434         if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
435
436             tmp_entry->value -= value;
437             return -1;
438         }
439         tmp_entry = tmp_entry->next;
440     }
441     return 0;
442 }
443
444
445
446
447 /*****************************************************************************/
448 /* returns value associated with key */
449 addr_t hashtable_search(struct hashtable * htable, addr_t key) {
450     struct hash_entry * cursor;
451     uint_t hash_value;
452     uint_t index;
453   
454     hash_value = do_hash(htable, key);
455   
456     index = indexFor(htable->table_length, hash_value);
457   
458     cursor = htable->table[index];
459   
460     while (cursor != NULL) {
461         /* Check hash value to short circuit heavier comparison */
462         if ((hash_value == cursor->hash) && 
463             (htable->eq_fn(key, cursor->key))) {
464             return cursor->value;
465         }
466     
467         cursor = cursor->next;
468     }
469   
470     return (addr_t)NULL;
471 }
472
473 /*****************************************************************************/
474 /* returns value associated with key */
475 addr_t hashtable_remove(struct hashtable * htable, addr_t key, int free_key) {
476     /* TODO: consider compacting the table when the load factor drops enough,
477      *       or provide a 'compact' method. */
478   
479     struct hash_entry * cursor;
480     struct hash_entry ** entry_ptr;
481     addr_t value;
482     uint_t hash_value;
483     uint_t index;
484   
485     hash_value = do_hash(htable, key);
486
487     index = indexFor(htable->table_length, hash_value);
488
489     entry_ptr = &(htable->table[index]);
490     cursor = *entry_ptr;
491
492     while (cursor != NULL) {
493         /* Check hash value to short circuit heavier comparison */
494         if ((hash_value == cursor->hash) && 
495             (htable->eq_fn(key, cursor->key))) {
496      
497             *entry_ptr = cursor->next;
498             htable->entry_count--;
499             value = cursor->value;
500       
501             if (free_key) {
502                 freekey((void *)(cursor->key));
503             }
504             V3_Free(cursor);
505       
506             return value;
507         }
508
509         entry_ptr = &(cursor->next);
510         cursor = cursor->next;
511     }
512     return (addr_t)NULL;
513 }
514
515 /*****************************************************************************/
516 /* destroy */
517 void hashtable_destroy(struct hashtable * htable, int free_values, int free_keys) {
518     uint_t i;
519     struct hash_entry * cursor;;
520     struct hash_entry **table = htable->table;
521
522     if (free_values) {
523         for (i = 0; i < htable->table_length; i++) {
524             cursor = table[i];
525       
526             while (cursor != NULL) { 
527                 struct hash_entry * tmp;
528
529                 tmp = cursor; 
530                 cursor = cursor->next; 
531
532                 if (free_keys) {
533                     freekey((void *)(tmp->key)); 
534                 }
535                 V3_Free((void *)(tmp->value)); 
536                 V3_Free(tmp); 
537             }
538         }
539     } else {
540         for (i = 0; i < htable->table_length; i++) {
541             cursor = table[i];
542
543             while (cursor != NULL) { 
544                 struct hash_entry * tmp;
545
546                 tmp = cursor; 
547                 cursor = cursor->next; 
548         
549                 if (free_keys) {
550                     freekey((void *)(tmp->key)); 
551                 }
552                 V3_Free(tmp); 
553             }
554         }
555     }
556   
557     V3_Free(htable->table);
558     V3_Free(htable);
559 }
560
561
562
563
564 /* HASH TABLE ITERATORS */
565
566
567
568 struct hashtable_iter * create_hashtable_iterator(struct hashtable * htable) {
569     uint_t i;
570     uint_t table_length;
571     
572     struct hashtable_iter * iter = (struct hashtable_iter *)V3_Malloc(sizeof(struct hashtable_iter));
573
574     if (iter == NULL) {
575         return NULL;
576     }
577
578     iter->htable = htable;
579     iter->entry = NULL;
580     iter->parent = NULL;
581     table_length = htable->table_length;
582     iter->index = table_length;
583
584     if (htable->entry_count == 0) {
585         return iter;
586     }
587  
588     for (i = 0; i < table_length; i++) {
589         if (htable->table[i] != NULL) {
590             iter->entry = htable->table[i];
591             iter->index = i;
592             break;
593         }
594     }
595
596     return iter;
597 }
598
599
600 addr_t hashtable_get_iter_key(struct hashtable_iter * iter) {
601     return iter->entry->key; 
602 }
603
604 addr_t hashtable_get_iter_value(struct hashtable_iter * iter) { 
605     return iter->entry->value; 
606 }
607
608
609 /* advance - advance the iterator to the next element
610  *           returns zero if advanced to end of table */
611 int hashtable_iterator_advance(struct hashtable_iter * iter) {
612     uint_t j;
613     uint_t table_length;
614     struct hash_entry ** table;
615     struct hash_entry * next;
616   
617     if (iter->entry == NULL) {
618         return 0; /* stupidity check */
619     }
620
621   
622     next = iter->entry->next;
623
624     if (next != NULL) {
625         iter->parent = iter->entry;
626         iter->entry = next;
627         return -1;
628     }
629    
630     table_length = iter->htable->table_length;
631     iter->parent = NULL;
632     
633     if (table_length <= (j = ++(iter->index))) {
634         iter->entry = NULL;
635         return 0;
636     }
637    
638     table = iter->htable->table;
639
640     while ((next = table[j]) == NULL) {
641         if (++j >= table_length) {
642             iter->index = table_length;
643             iter->entry = NULL;
644             return 0;
645         }
646     }
647    
648     iter->index = j;
649     iter->entry = next;
650
651     return -1;
652 }
653
654
655 /* remove - remove the entry at the current iterator position
656  *          and advance the iterator, if there is a successive
657  *          element.
658  *          If you want the value, read it before you remove:
659  *          beware memory leaks if you don't.
660  *          Returns zero if end of iteration. */
661 int hashtable_iterator_remove(struct hashtable_iter * iter, int free_key) {
662     struct hash_entry * remember_entry; 
663     struct hash_entry * remember_parent;
664     int ret;
665
666     /* Do the removal */
667     if ((iter->parent) == NULL) {
668         /* element is head of a chain */
669         iter->htable->table[iter->index] = iter->entry->next;
670     } else {
671         /* element is mid-chain */
672         iter->parent->next = iter->entry->next;
673     }
674
675   
676     /* itr->e is now outside the hashtable */
677     remember_entry = iter->entry;
678     iter->htable->entry_count--;
679     if (free_key) {
680         freekey((void *)(remember_entry->key));
681     }
682
683     /* Advance the iterator, correcting the parent */
684     remember_parent = iter->parent;
685     ret = hashtable_iterator_advance(iter);
686
687     if (iter->parent == remember_entry) { 
688         iter->parent = remember_parent; 
689     }
690   
691     V3_Free(remember_entry);
692     return ret;
693 }
694
695
696 /* returns zero if not found */
697 int hashtable_iterator_search(struct hashtable_iter * iter,
698                               struct hashtable * htable, addr_t key) {
699     struct hash_entry * entry;
700     struct hash_entry * parent;
701     uint_t hash_value;
702     uint_t index;
703   
704     hash_value = do_hash(htable, key);
705     index = indexFor(htable->table_length, hash_value);
706   
707     entry = htable->table[index];
708     parent = NULL;
709   
710     while (entry != NULL) {
711         /* Check hash value to short circuit heavier comparison */
712         if ((hash_value == entry->hash) && 
713             (htable->eq_fn(key, entry->key))) {
714             iter->index = index;
715             iter->entry = entry;
716             iter->parent = parent;
717             iter->htable = htable;
718             return -1;
719         }
720         parent = entry;
721         entry = entry->next;
722     }
723     return 0;
724 }
725  
726  
727
728
729
730
731
732
733
734
735
736
737
738
739
740 /*
741  * Copyright (c) 2002, Christopher Clark
742  * All rights reserved.
743  * 
744  * Redistribution and use in source and binary forms, with or without
745  * modification, are permitted provided that the following conditions
746  * are met:
747  * 
748  * * Redistributions of source code must retain the above copyright
749  * notice, this list of conditions and the following disclaimer.
750  * 
751  * * Redistributions in binary form must reproduce the above copyright
752  * notice, this list of conditions and the following disclaimer in the
753  * documentation and/or other materials provided with the distribution.
754  * 
755  * * Neither the name of the original author; nor the names of any contributors
756  * may be used to endorse or promote products derived from this software
757  * without specific prior written permission.
758  * 
759  * 
760  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
761  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
762  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
763  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
764  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
765  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
766  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
767  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
768  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
769  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
770  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
771  */