Rev 4192 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4192 | Rev 4263 | ||
|---|---|---|---|
| Line 142... | Line 142... | ||
| 142 | unative_t method, irq_code_t *ucode) |
142 | unative_t method, irq_code_t *ucode) |
| 143 | { |
143 | { |
| 144 | ipl_t ipl; |
144 | ipl_t ipl; |
| 145 | irq_code_t *code; |
145 | irq_code_t *code; |
| 146 | irq_t *irq; |
146 | irq_t *irq; |
| - | 147 | link_t *hlp; |
|
| 147 | unative_t key[] = { |
148 | unative_t key[] = { |
| 148 | (unative_t) inr, |
149 | (unative_t) inr, |
| 149 | (unative_t) devno |
150 | (unative_t) devno |
| 150 | }; |
151 | }; |
| 151 | 152 | ||
| Line 176... | Line 177... | ||
| 176 | * Enlist the IRQ structure in the uspace IRQ hash table and the |
177 | * Enlist the IRQ structure in the uspace IRQ hash table and the |
| 177 | * answerbox's list. |
178 | * answerbox's list. |
| 178 | */ |
179 | */ |
| 179 | ipl = interrupts_disable(); |
180 | ipl = interrupts_disable(); |
| 180 | spinlock_lock(&irq_uspace_hash_table_lock); |
181 | spinlock_lock(&irq_uspace_hash_table_lock); |
| - | 182 | hlp = hash_table_find(&irq_uspace_hash_table, key); |
|
| - | 183 | if (hlp) { |
|
| - | 184 | irq_t *hirq = hash_table_get_instance(hlp, irq_t, link); |
|
| 181 | spinlock_lock(&irq->lock); |
185 | /* hirq is locked */ |
| 182 | spinlock_lock(&box->irq_lock); |
186 | spinlock_unlock(&hirq->lock); |
| 183 | if (hash_table_find(&irq_uspace_hash_table, key)) { |
- | |
| 184 | code_free(code); |
187 | code_free(code); |
| 185 | spinlock_unlock(&box->irq_lock); |
- | |
| 186 | spinlock_unlock(&irq->lock); |
- | |
| 187 | spinlock_unlock(&irq_uspace_hash_table_lock); |
188 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 188 | free(irq); |
189 | free(irq); |
| 189 | interrupts_restore(ipl); |
190 | interrupts_restore(ipl); |
| 190 | return EEXISTS; |
191 | return EEXISTS; |
| 191 | } |
192 | } |
| - | 193 | spinlock_lock(&irq->lock); /* not really necessary, but paranoid */ |
|
| - | 194 | spinlock_lock(&box->irq_lock); |
|
| 192 | hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
195 | hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
| 193 | list_append(&irq->notif_cfg.link, &box->irq_head); |
196 | list_append(&irq->notif_cfg.link, &box->irq_head); |
| 194 | spinlock_unlock(&box->irq_lock); |
197 | spinlock_unlock(&box->irq_lock); |
| 195 | spinlock_unlock(&irq->lock); |
198 | spinlock_unlock(&irq->lock); |
| 196 | spinlock_unlock(&irq_uspace_hash_table_lock); |
199 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| Line 227... | Line 230... | ||
| 227 | spinlock_unlock(&irq_uspace_hash_table_lock); |
230 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 228 | interrupts_restore(ipl); |
231 | interrupts_restore(ipl); |
| 229 | return ENOENT; |
232 | return ENOENT; |
| 230 | } |
233 | } |
| 231 | irq = hash_table_get_instance(lnk, irq_t, link); |
234 | irq = hash_table_get_instance(lnk, irq_t, link); |
| 232 | spinlock_lock(&irq->lock); |
235 | /* irq is locked */ |
| 233 | spinlock_lock(&box->irq_lock); |
236 | spinlock_lock(&box->irq_lock); |
| 234 | 237 | ||
| 235 | ASSERT(irq->notif_cfg.answerbox == box); |
238 | ASSERT(irq->notif_cfg.answerbox == box); |
| 236 | 239 | ||
| 237 | /* Free up the pseudo code and associated structures. */ |
240 | /* Free up the pseudo code and associated structures. */ |
| 238 | code_free(irq->notif_cfg.code); |
241 | code_free(irq->notif_cfg.code); |
| 239 | 242 | ||
| 240 | /* Remove the IRQ from the answerbox's list. */ |
243 | /* Remove the IRQ from the answerbox's list. */ |
| 241 | list_remove(&irq->notif_cfg.link); |
244 | list_remove(&irq->notif_cfg.link); |
| 242 | 245 | ||
| - | 246 | /* |
|
| - | 247 | * We need to drop the IRQ lock now because hash_table_remove() will try |
|
| - | 248 | * to reacquire it. That basically violates the natural locking order, |
|
| - | 249 | * but a deadlock in hash_table_remove() is prevented by the fact that |
|
| - | 250 | * we already held the IRQ lock and didn't drop the hash table lock in |
|
| - | 251 | * the meantime. |
|
| - | 252 | */ |
|
| - | 253 | spinlock_unlock(&irq->lock); |
|
| - | 254 | ||
| 243 | /* Remove the IRQ from the uspace IRQ hash table. */ |
255 | /* Remove the IRQ from the uspace IRQ hash table. */ |
| 244 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
256 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
| 245 | 257 | ||
| 246 | spinlock_unlock(&irq_uspace_hash_table_lock); |
258 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 247 | spinlock_unlock(&irq->lock); |
- | |
| 248 | spinlock_unlock(&box->irq_lock); |
259 | spinlock_unlock(&box->irq_lock); |
| 249 | 260 | ||
| 250 | /* Free up the IRQ structure. */ |
261 | /* Free up the IRQ structure. */ |
| 251 | free(irq); |
262 | free(irq); |
| 252 | 263 | ||
| Line 296... | Line 307... | ||
| 296 | ASSERT(irq->notif_cfg.answerbox == box); |
307 | ASSERT(irq->notif_cfg.answerbox == box); |
| 297 | 308 | ||
| 298 | /* Unlist from the answerbox. */ |
309 | /* Unlist from the answerbox. */ |
| 299 | list_remove(&irq->notif_cfg.link); |
310 | list_remove(&irq->notif_cfg.link); |
| 300 | 311 | ||
| 301 | /* Remove from the hash table. */ |
- | |
| 302 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
- | |
| 303 | - | ||
| 304 | /* Free up the pseudo code and associated structures. */ |
312 | /* Free up the pseudo code and associated structures. */ |
| 305 | code_free(irq->notif_cfg.code); |
313 | code_free(irq->notif_cfg.code); |
| 306 | 314 | ||
| - | 315 | /* |
|
| - | 316 | * We need to drop the IRQ lock now because hash_table_remove() |
|
| - | 317 | * will try to reacquire it. That basically violates the natural |
|
| - | 318 | * locking order, but a deadlock in hash_table_remove() is |
|
| - | 319 | * prevented by the fact that we already held the IRQ lock and |
|
| - | 320 | * didn't drop the hash table lock in the meantime. |
|
| - | 321 | */ |
|
| 307 | spinlock_unlock(&irq->lock); |
322 | spinlock_unlock(&irq->lock); |
| - | 323 | ||
| - | 324 | /* Remove from the hash table. */ |
|
| - | 325 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
|
| - | 326 | ||
| 308 | free(irq); |
327 | free(irq); |
| 309 | } |
328 | } |
| 310 | 329 | ||
| 311 | spinlock_unlock(&box->irq_lock); |
330 | spinlock_unlock(&box->irq_lock); |
| 312 | spinlock_unlock(&irq_uspace_hash_table_lock); |
331 | spinlock_unlock(&irq_uspace_hash_table_lock); |