Changeset 82cbf8c6 in mainline for kernel/generic/src/ddi/irq.c
- Timestamp:
- 2017-10-08T19:37:24Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2fd26bb
- Parents:
- 81b9d3e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/irq.c
r81b9d3e r82cbf8c6 40 40 41 41 #include <ddi/irq.h> 42 #include <adt/hash.h> 42 43 #include <adt/hash_table.h> 43 44 #include <mm/slab.h> … … 71 72 hash_table_t irq_uspace_hash_table; 72 73 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 = { 74 static size_t irq_ht_hash(const ht_link_t *); 75 static size_t irq_ht_key_hash(void *); 76 static bool irq_ht_equal(const ht_link_t *, const ht_link_t *); 77 static bool irq_ht_key_equal(void *, const ht_link_t *); 78 79 static hash_table_ops_t irq_ht_ops = { 78 80 .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 81 84 }; 82 83 /** Number of buckets in either of the hash tables */84 static size_t buckets;85 85 86 86 /** Last valid INR */ … … 95 95 void irq_init(size_t inrs, size_t chains) 96 96 { 97 buckets = chains;98 97 last_inr = inrs - 1; 99 98 … … 102 101 assert(irq_slab); 103 102 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); 106 105 } 107 106 … … 114 113 { 115 114 memsetb(irq, sizeof(irq_t), 0); 116 link_initialize(&irq->link);117 115 irq_spinlock_initialize(&irq->lock, "irq.lock"); 118 116 irq->inr = -1; … … 131 129 void irq_register(irq_t *irq) 132 130 { 133 sysarg_t key[] = {134 [IRQ_HT_KEY_INR] = (sysarg_t) irq->inr,135 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM136 };137 138 131 irq_spinlock_lock(&irq_kernel_hash_table_lock, true); 139 132 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); 141 134 irq_spinlock_unlock(&irq->lock, false); 142 135 irq_spinlock_unlock(&irq_kernel_hash_table_lock, true); 143 136 } 144 137 145 /** Search and lock the uspaceIRQ 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_CLAIM152 };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 */ 139 static irq_t * 140 irq_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); 160 153 } 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); 183 155 184 156 return NULL; … … 209 181 210 182 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); 212 185 if (irq) 213 186 return irq; 214 187 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); 216 190 } 217 191 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); 219 194 if (irq) 220 195 return irq; 221 196 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. */ 202 size_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. */ 209 size_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. */ 216 bool 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. */ 224 bool 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; 287 229 } 288 230
Note:
See TracChangeset
for help on using the changeset viewer.