Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/mm/page_ht.c

    rfb63c06 r82cbf8c6  
    4848#include <synch/spinlock.h>
    4949#include <arch.h>
    50 #include <debug.h>
    51 #include <memstr.h>
     50#include <assert.h>
     51#include <adt/hash.h>
    5252#include <adt/hash_table.h>
    5353#include <align.h>
    5454
    55 static size_t hash(sysarg_t[]);
    56 static bool compare(sysarg_t[], size_t, link_t *);
    57 static void remove_callback(link_t *);
     55static size_t ht_hash(const ht_link_t *);
     56static size_t ht_key_hash(void *);
     57static bool ht_key_equal(void *, const ht_link_t *);
     58static void ht_remove_callback(ht_link_t *);
    5859
    5960static void ht_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
     
    8182
    8283/** Hash table operations for page hash table. */
    83 hash_table_operations_t ht_operations = {
    84         .hash = hash,
    85         .compare = compare,
    86         .remove_callback = remove_callback
     84hash_table_ops_t ht_ops = {
     85        .hash = ht_hash,
     86        .key_hash = ht_key_hash,
     87        .key_equal = ht_key_equal,
     88        .remove_callback = ht_remove_callback
    8789};
    8890
     
    9698};
    9799
    98 /** Compute page hash table index.
    99  *
    100  * @param key Array of two keys (i.e. page and address space).
    101  *
    102  * @return Index into page hash table.
    103  *
    104  */
    105 size_t hash(sysarg_t key[])
    106 {
    107         as_t *as = (as_t *) key[KEY_AS];
    108         uintptr_t page = (uintptr_t) key[KEY_PAGE];
    109        
    110         /*
    111          * Virtual page addresses have roughly the same probability
    112          * of occurring. Least significant bits of VPN compose the
    113          * hash index.
    114          *
    115          */
    116         size_t index = ((page >> PAGE_WIDTH) & (PAGE_HT_ENTRIES - 1));
    117        
    118         /*
    119          * Address space structures are likely to be allocated from
    120          * similar addresses. Least significant bits compose the
    121          * hash index.
    122          *
    123          */
    124         index |= ((sysarg_t) as) & (PAGE_HT_ENTRIES - 1);
    125        
    126         return index;
    127 }
    128 
    129 /** Compare page hash table item with page and/or address space.
    130  *
    131  * @param key  Array of one or two keys (i.e. page and/or address space).
    132  * @param keys Number of keys passed.
    133  * @param item Item to compare the keys with.
    134  *
    135  * @return true on match, false otherwise.
    136  *
    137  */
    138 bool compare(sysarg_t key[], size_t keys, link_t *item)
    139 {
    140         ASSERT(item);
    141         ASSERT(keys > 0);
    142         ASSERT(keys <= PAGE_HT_KEYS);
    143        
    144         /*
    145          * Convert item to PTE.
    146          *
    147          */
    148         pte_t *pte = hash_table_get_instance(item, pte_t, link);
    149        
    150         if (keys == PAGE_HT_KEYS)
    151                 return (key[KEY_AS] == (uintptr_t) pte->as) &&
    152                     (key[KEY_PAGE] == pte->page);
    153        
    154         return (key[KEY_AS] == (uintptr_t) pte->as);
     100/** Return the hash of the key stored in the item */
     101size_t ht_hash(const ht_link_t *item)
     102{
     103        pte_t *pte = hash_table_get_inst(item, pte_t, link);
     104        size_t hash = 0;
     105        hash = hash_combine(hash, (uintptr_t) pte->as);
     106        hash = hash_combine(hash, pte->page >> PAGE_WIDTH);
     107        return hash;
     108}
     109
     110/** Return the hash of the key. */
     111size_t ht_key_hash(void *arg)
     112{
     113        uintptr_t *key = (uintptr_t *) arg;
     114        size_t hash = 0;
     115        hash = hash_combine(hash, key[KEY_AS]);
     116        hash = hash_combine(hash, key[KEY_PAGE] >> PAGE_WIDTH);
     117        return hash;
     118}
     119
     120/** Return true if the key is equal to the item's lookup key. */
     121bool ht_key_equal(void *arg, const ht_link_t *item)
     122{
     123        uintptr_t *key = (uintptr_t *) arg;
     124        pte_t *pte = hash_table_get_inst(item, pte_t, link);
     125        return (key[KEY_AS] == (uintptr_t) pte->as) &&
     126            (key[KEY_PAGE] == pte->page);
    155127}
    156128
     
    160132 *
    161133 */
    162 void remove_callback(link_t *item)
    163 {
    164         ASSERT(item);
    165        
    166         /*
    167          * Convert item to PTE.
    168          *
    169          */
    170         pte_t *pte = hash_table_get_instance(item, pte_t, link);
    171        
     134void ht_remove_callback(ht_link_t *item)
     135{
     136        assert(item);
     137       
     138        pte_t *pte = hash_table_get_inst(item, pte_t, link);
    172139        slab_free(pte_cache, pte);
    173140}
     
    187154    unsigned int flags)
    188155{
    189         sysarg_t key[2] = {
    190                 (uintptr_t) as,
    191                 page = ALIGN_DOWN(page, PAGE_SIZE)
     156        uintptr_t key[2] = {
     157                [KEY_AS] = (uintptr_t) as,
     158                [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE)
    192159        };
    193160
    194         ASSERT(page_table_locked(as));
     161        assert(page_table_locked(as));
    195162
    196163        irq_spinlock_lock(&page_ht_lock, true);
     
    198165        if (!hash_table_find(&page_ht, key)) {
    199166                pte_t *pte = slab_alloc(pte_cache, FRAME_LOWMEM | FRAME_ATOMIC);
    200                 ASSERT(pte != NULL);
     167                assert(pte != NULL);
    201168               
    202169                pte->g = (flags & PAGE_GLOBAL) != 0;
     
    219186                write_barrier();
    220187               
    221                 hash_table_insert(&page_ht, key, &pte->link);
     188                hash_table_insert(&page_ht, &pte->link);
    222189        }
    223190
     
    237204void ht_mapping_remove(as_t *as, uintptr_t page)
    238205{
    239         sysarg_t key[2] = {
    240                 (uintptr_t) as,
    241                 page = ALIGN_DOWN(page, PAGE_SIZE)
     206        uintptr_t key[2] = {
     207                [KEY_AS] = (uintptr_t) as,
     208                [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE)
    242209        };
    243210
    244         ASSERT(page_table_locked(as));
     211        assert(page_table_locked(as));
    245212       
    246213        irq_spinlock_lock(&page_ht_lock, true);
     
    250217         * by remove_callback().
    251218         */
    252         hash_table_remove(&page_ht, key, 2);
     219        hash_table_remove(&page_ht, key);
    253220
    254221        irq_spinlock_unlock(&page_ht_lock, true);
    255222}
    256223
    257 static pte_t *ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
    258 {
    259         sysarg_t key[2] = {
    260                 (uintptr_t) as,
    261                 page = ALIGN_DOWN(page, PAGE_SIZE)
     224static pte_t *
     225ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
     226{
     227        uintptr_t key[2] = {
     228                [KEY_AS] = (uintptr_t) as,
     229                [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE)
    262230        };
    263231
    264         ASSERT(nolock || page_table_locked(as));
    265 
    266         link_t *cur = hash_table_find(&page_ht, key);
     232        assert(nolock || page_table_locked(as));
     233
     234        ht_link_t *cur = hash_table_find(&page_ht, key);
    267235        if (cur)
    268                 return hash_table_get_instance(cur, pte_t, link);
     236                return hash_table_get_inst(cur, pte_t, link);
    269237       
    270238        return NULL;
     
    308276                panic("Updating non-existent PTE");
    309277       
    310         ASSERT(pte->as == t->as);
    311         ASSERT(pte->page == t->page);
    312         ASSERT(pte->frame == t->frame);
    313         ASSERT(pte->g == t->g);
    314         ASSERT(pte->x == t->x);
    315         ASSERT(pte->w == t->w);
    316         ASSERT(pte->k == t->k);
    317         ASSERT(pte->c == t->c);
    318         ASSERT(pte->p == t->p);
     278        assert(pte->as == t->as);
     279        assert(pte->page == t->page);
     280        assert(pte->frame == t->frame);
     281        assert(pte->g == t->g);
     282        assert(pte->x == t->x);
     283        assert(pte->w == t->w);
     284        assert(pte->k == t->k);
     285        assert(pte->c == t->c);
     286        assert(pte->p == t->p);
    319287
    320288        t->a = pte->a;
Note: See TracChangeset for help on using the changeset viewer.