Changeset 82cbf8c6 in mainline for kernel/generic/src/ddi/irq.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/generic/src/ddi/irq.c

    r81b9d3e r82cbf8c6  
    4040
    4141#include <ddi/irq.h>
     42#include <adt/hash.h>
    4243#include <adt/hash_table.h>
    4344#include <mm/slab.h>
     
    7172hash_table_t irq_uspace_hash_table;
    7273
    73 static size_t irq_ht_hash(sysarg_t *key);
    74 static bool irq_ht_compare(sysarg_t *key, size_t keys, link_t *item);
    75 static void irq_ht_remove(link_t *item);
    76 
    77 static hash_table_operations_t irq_ht_ops = {
     74static size_t irq_ht_hash(const ht_link_t *);
     75static size_t irq_ht_key_hash(void *);
     76static bool irq_ht_equal(const ht_link_t *, const ht_link_t *);
     77static bool irq_ht_key_equal(void *, const ht_link_t *);
     78
     79static hash_table_ops_t irq_ht_ops = {
    7880        .hash = irq_ht_hash,
    79         .compare = irq_ht_compare,
    80         .remove_callback = irq_ht_remove,
     81        .key_hash = irq_ht_key_hash,
     82        .equal = irq_ht_equal,
     83        .key_equal = irq_ht_key_equal
    8184};
    82 
    83 /** Number of buckets in either of the hash tables */
    84 static size_t buckets;
    8585
    8686/** Last valid INR */
     
    9595void irq_init(size_t inrs, size_t chains)
    9696{
    97         buckets = chains;
    9897        last_inr = inrs - 1;
    9998
     
    102101        assert(irq_slab);
    103102
    104         hash_table_create(&irq_uspace_hash_table, chains, 2, &irq_ht_ops);
    105         hash_table_create(&irq_kernel_hash_table, chains, 2, &irq_ht_ops);
     103        hash_table_create(&irq_uspace_hash_table, chains, 0, &irq_ht_ops);
     104        hash_table_create(&irq_kernel_hash_table, chains, 0, &irq_ht_ops);
    106105}
    107106
     
    114113{
    115114        memsetb(irq, sizeof(irq_t), 0);
    116         link_initialize(&irq->link);
    117115        irq_spinlock_initialize(&irq->lock, "irq.lock");
    118116        irq->inr = -1;
     
    131129void irq_register(irq_t *irq)
    132130{
    133         sysarg_t key[] = {
    134                 [IRQ_HT_KEY_INR] = (sysarg_t) irq->inr,
    135                 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM
    136         };
    137        
    138131        irq_spinlock_lock(&irq_kernel_hash_table_lock, true);
    139132        irq_spinlock_lock(&irq->lock, false);
    140         hash_table_insert(&irq_kernel_hash_table, key, &irq->link);
     133        hash_table_insert(&irq_kernel_hash_table, &irq->link);
    141134        irq_spinlock_unlock(&irq->lock, false);
    142135        irq_spinlock_unlock(&irq_kernel_hash_table_lock, true);
    143136}
    144137
    145 /** Search and lock the uspace IRQ hash table */
    146 static irq_t *irq_dispatch_and_lock_uspace(inr_t inr)
    147 {
    148         link_t *lnk;
    149         sysarg_t key[] = {
    150                 [IRQ_HT_KEY_INR] = (sysarg_t) inr,
    151                 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM
    152         };
    153        
    154         irq_spinlock_lock(&irq_uspace_hash_table_lock, false);
    155         lnk = hash_table_find(&irq_uspace_hash_table, key);
    156         if (lnk) {
    157                 irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
    158                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, false);
    159                 return irq;
     138/** Search and lock an IRQ hash table */
     139static irq_t *
     140irq_dispatch_and_lock_table(hash_table_t *h, irq_spinlock_t *l, inr_t inr)
     141{
     142        irq_spinlock_lock(l, false);
     143        for (ht_link_t *lnk = hash_table_find(h, &inr); lnk;
     144            lnk = hash_table_find_next(h, lnk)) {
     145                irq_t *irq = hash_table_get_inst(lnk, irq_t, link);
     146                irq_spinlock_lock(&irq->lock, false);
     147                if (irq->claim(irq) == IRQ_ACCEPT) {
     148                        /* leave irq locked */
     149                        irq_spinlock_unlock(l, false);
     150                        return irq;
     151                }
     152                irq_spinlock_unlock(&irq->lock, false);
    160153        }
    161         irq_spinlock_unlock(&irq_uspace_hash_table_lock, false);
    162        
    163         return NULL;
    164 }
    165 
    166 /** Search and lock the kernel IRQ hash table */
    167 static irq_t *irq_dispatch_and_lock_kernel(inr_t inr)
    168 {
    169         link_t *lnk;
    170         sysarg_t key[] = {
    171                 [IRQ_HT_KEY_INR] = (sysarg_t) inr,
    172                 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM
    173         };
    174        
    175         irq_spinlock_lock(&irq_kernel_hash_table_lock, false);
    176         lnk = hash_table_find(&irq_kernel_hash_table, key);
    177         if (lnk) {
    178                 irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
    179                 irq_spinlock_unlock(&irq_kernel_hash_table_lock, false);
    180                 return irq;
    181         }
    182         irq_spinlock_unlock(&irq_kernel_hash_table_lock, false);
     154        irq_spinlock_unlock(l, false);
    183155       
    184156        return NULL;
     
    209181       
    210182        if (console_override) {
    211                 irq_t *irq = irq_dispatch_and_lock_kernel(inr);
     183                irq_t *irq = irq_dispatch_and_lock_table(&irq_kernel_hash_table,
     184                    &irq_kernel_hash_table_lock, inr);
    212185                if (irq)
    213186                        return irq;
    214187               
    215                 return irq_dispatch_and_lock_uspace(inr);
     188                return irq_dispatch_and_lock_table(&irq_uspace_hash_table,
     189                    &irq_uspace_hash_table_lock, inr);
    216190        }
    217191       
    218         irq_t *irq = irq_dispatch_and_lock_uspace(inr);
     192        irq_t *irq = irq_dispatch_and_lock_table(&irq_uspace_hash_table,
     193            &irq_uspace_hash_table_lock, inr);
    219194        if (irq)
    220195                return irq;
    221196       
    222         return irq_dispatch_and_lock_kernel(inr);
    223 }
    224 
    225 /** Compute hash index for the key
    226  *
    227  * @param key  The first of the keys is inr and the second is mode. Only inr is
    228  *             used to compute the hash.
    229  *
    230  * @return Index into the hash table.
    231  *
    232  */
    233 size_t irq_ht_hash(sysarg_t key[])
    234 {
    235         inr_t inr = (inr_t) key[IRQ_HT_KEY_INR];
    236         return inr % buckets;
    237 }
    238 
    239 /** Compare hash table element with a key
    240  *
    241  * If mode is IRQ_HT_MODE_CLAIM, the result of the claim() function is used for
    242  * the match. Otherwise the key does not match.
    243  *
    244  * This function assumes interrupts are already disabled.
    245  *
    246  * @param key   Keys (i.e. inr and mode).
    247  * @param keys  This is 2.
    248  * @param item  The item to compare the key with.
    249  *
    250  * @return True on match
    251  * @return False on no match
    252  *
    253  */
    254 bool irq_ht_compare(sysarg_t key[], size_t keys, link_t *item)
    255 {
    256         irq_t *irq = hash_table_get_instance(item, irq_t, link);
    257         inr_t inr = (inr_t) key[IRQ_HT_KEY_INR];
    258         irq_ht_mode_t mode = (irq_ht_mode_t) key[IRQ_HT_KEY_MODE];
    259        
    260         bool rv;
    261        
    262         irq_spinlock_lock(&irq->lock, false);
    263         if (mode == IRQ_HT_MODE_CLAIM) {
    264                 /* Invoked by irq_dispatch_and_lock(). */
    265                 rv = ((irq->inr == inr) && (irq->claim(irq) == IRQ_ACCEPT));
    266         } else {
    267                 /* Invoked by irq_find_and_lock(). */
    268                 rv = false;
    269         }
    270        
    271         /* unlock only on non-match */
    272         if (!rv)
    273                 irq_spinlock_unlock(&irq->lock, false);
    274        
    275         return rv;
    276 }
    277 
    278 /** Unlock IRQ structure after hash_table_remove()
    279  *
    280  * @param lnk  Link in the removed and locked IRQ structure.
    281  */
    282 void irq_ht_remove(link_t *lnk)
    283 {
    284         irq_t *irq __attribute__((unused))
    285             = hash_table_get_instance(lnk, irq_t, link);
    286         irq_spinlock_unlock(&irq->lock, false);
     197        return irq_dispatch_and_lock_table(&irq_kernel_hash_table,
     198            &irq_kernel_hash_table_lock, inr);
     199}
     200
     201/** Return the hash of the key stored in the item. */
     202size_t irq_ht_hash(const ht_link_t *item)
     203{
     204        irq_t *irq = hash_table_get_inst(item, irq_t, link);
     205        return hash_mix(irq->inr);
     206}
     207
     208/** Return the hash of the key. */
     209size_t irq_ht_key_hash(void *key)
     210{
     211        inr_t *inr = (inr_t *) key;
     212        return hash_mix(*inr);
     213}
     214
     215/** Return true if the items have the same lookup key. */
     216bool irq_ht_equal(const ht_link_t *item1, const ht_link_t *item2)
     217{
     218        irq_t *irq1 = hash_table_get_inst(item1, irq_t, link);
     219        irq_t *irq2 = hash_table_get_inst(item2, irq_t, link);
     220        return irq1->inr == irq2->inr;
     221}
     222
     223/** Return true if the key is equal to the item's lookup key. */
     224bool irq_ht_key_equal(void *key, const ht_link_t *item)
     225{
     226        inr_t *inr = (inr_t *) key;
     227        irq_t *irq = hash_table_get_inst(item, irq_t, link);
     228        return irq->inr == *inr;
    287229}
    288230
Note: See TracChangeset for help on using the changeset viewer.