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