Changeset 82cbf8c6 in mainline for kernel/genarch/src/mm/page_ht.c


Ignore:
Timestamp:
2017-10-08T19:37:24Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2fd26bb
Parents:
81b9d3e
Message:

Replace the old hash table implementation in the kernel with the newer one

This replaces the original hash table implementation with the resizable one
already used in uspace. Along the way, the IRQ hash table code was streamlined
and cleaned up.

File:
1 edited

Legend:

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

    r81b9d3e r82cbf8c6  
    4949#include <arch.h>
    5050#include <assert.h>
     51#include <adt/hash.h>
    5152#include <adt/hash_table.h>
    5253#include <align.h>
    5354
    54 static size_t hash(sysarg_t[]);
    55 static bool compare(sysarg_t[], size_t, link_t *);
    56 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 *);
    5759
    5860static void ht_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
     
    8082
    8183/** Hash table operations for page hash table. */
    82 hash_table_operations_t ht_operations = {
    83         .hash = hash,
    84         .compare = compare,
    85         .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
    8689};
    8790
     
    9598};
    9699
    97 /** Compute page hash table index.
    98  *
    99  * @param key Array of two keys (i.e. page and address space).
    100  *
    101  * @return Index into page hash table.
    102  *
    103  */
    104 size_t hash(sysarg_t key[])
    105 {
    106         as_t *as = (as_t *) key[KEY_AS];
    107         uintptr_t page = (uintptr_t) key[KEY_PAGE];
    108        
    109         /*
    110          * Virtual page addresses have roughly the same probability
    111          * of occurring. Least significant bits of VPN compose the
    112          * hash index.
    113          *
    114          */
    115         size_t index = ((page >> PAGE_WIDTH) & (PAGE_HT_ENTRIES - 1));
    116        
    117         /*
    118          * Address space structures are likely to be allocated from
    119          * similar addresses. Least significant bits compose the
    120          * hash index.
    121          *
    122          */
    123         index |= ((sysarg_t) as) & (PAGE_HT_ENTRIES - 1);
    124        
    125         return index;
    126 }
    127 
    128 /** Compare page hash table item with page and/or address space.
    129  *
    130  * @param key  Array of one or two keys (i.e. page and/or address space).
    131  * @param keys Number of keys passed.
    132  * @param item Item to compare the keys with.
    133  *
    134  * @return true on match, false otherwise.
    135  *
    136  */
    137 bool compare(sysarg_t key[], size_t keys, link_t *item)
     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);
     127}
     128
     129/** Callback on page hash table item removal.
     130 *
     131 * @param item Page hash table item being removed.
     132 *
     133 */
     134void ht_remove_callback(ht_link_t *item)
    138135{
    139136        assert(item);
    140         assert(keys > 0);
    141         assert(keys <= PAGE_HT_KEYS);
    142        
    143         /*
    144          * Convert item to PTE.
    145          *
    146          */
    147         pte_t *pte = hash_table_get_instance(item, pte_t, link);
    148        
    149         if (keys == PAGE_HT_KEYS)
    150                 return (key[KEY_AS] == (uintptr_t) pte->as) &&
    151                     (key[KEY_PAGE] == pte->page);
    152        
    153         return (key[KEY_AS] == (uintptr_t) pte->as);
    154 }
    155 
    156 /** Callback on page hash table item removal.
    157  *
    158  * @param item Page hash table item being removed.
    159  *
    160  */
    161 void remove_callback(link_t *item)
    162 {
    163         assert(item);
    164        
    165         /*
    166          * Convert item to PTE.
    167          *
    168          */
    169         pte_t *pte = hash_table_get_instance(item, pte_t, link);
    170        
     137       
     138        pte_t *pte = hash_table_get_inst(item, pte_t, link);
    171139        slab_free(pte_cache, pte);
    172140}
     
    186154    unsigned int flags)
    187155{
    188         sysarg_t key[2] = {
    189                 (uintptr_t) as,
    190                 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)
    191159        };
    192160
     
    218186                write_barrier();
    219187               
    220                 hash_table_insert(&page_ht, key, &pte->link);
     188                hash_table_insert(&page_ht, &pte->link);
    221189        }
    222190
     
    236204void ht_mapping_remove(as_t *as, uintptr_t page)
    237205{
    238         sysarg_t key[2] = {
    239                 (uintptr_t) as,
    240                 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)
    241209        };
    242210
     
    249217         * by remove_callback().
    250218         */
    251         hash_table_remove(&page_ht, key, 2);
     219        hash_table_remove(&page_ht, key);
    252220
    253221        irq_spinlock_unlock(&page_ht_lock, true);
    254222}
    255223
    256 static pte_t *ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
    257 {
    258         sysarg_t key[2] = {
    259                 (uintptr_t) as,
    260                 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)
    261230        };
    262231
    263232        assert(nolock || page_table_locked(as));
    264233
    265         link_t *cur = hash_table_find(&page_ht, key);
     234        ht_link_t *cur = hash_table_find(&page_ht, key);
    266235        if (cur)
    267                 return hash_table_get_instance(cur, pte_t, link);
     236                return hash_table_get_inst(cur, pte_t, link);
    268237       
    269238        return NULL;
Note: See TracChangeset for help on using the changeset viewer.