128,13 → 128,14 |
|
/** Register an answerbox as a receiving end for IRQ notifications. |
* |
* @param box Receiving answerbox. |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to top-half pseudocode. |
* @param box Receiving answerbox. |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to top-half pseudocode. |
* |
* @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
* @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
* |
*/ |
int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, |
unative_t method, irq_code_t *ucode) |
142,11 → 143,12 |
ipl_t ipl; |
irq_code_t *code; |
irq_t *irq; |
link_t *hlp; |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) devno |
}; |
|
|
if (ucode) { |
code = code_from_uspace(ucode); |
if (!code) |
154,7 → 156,7 |
} else { |
code = NULL; |
} |
|
|
/* |
* Allocate and populate the IRQ structure. |
*/ |
169,7 → 171,7 |
irq->notif_cfg.method = method; |
irq->notif_cfg.code = code; |
irq->notif_cfg.counter = 0; |
|
|
/* |
* Enlist the IRQ structure in the uspace IRQ hash table and the |
* answerbox's list. |
176,23 → 178,28 |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&irq_uspace_hash_table_lock); |
spinlock_lock(&irq->lock); |
spinlock_lock(&box->irq_lock); |
if (hash_table_find(&irq_uspace_hash_table, key)) { |
hlp = hash_table_find(&irq_uspace_hash_table, key); |
if (hlp) { |
irq_t *hirq __attribute__((unused)) |
= hash_table_get_instance(hlp, irq_t, link); |
|
/* hirq is locked */ |
spinlock_unlock(&hirq->lock); |
code_free(code); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
free(irq); |
interrupts_restore(ipl); |
return EEXISTS; |
} |
|
spinlock_lock(&irq->lock); /* Not really necessary, but paranoid */ |
spinlock_lock(&box->irq_lock); |
hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
list_append(&irq->notif_cfg.link, &box->irq_head); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
|
|
interrupts_restore(ipl); |
return EOK; |
} |
222,7 → 229,7 |
return ENOENT; |
} |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_lock(&irq->lock); |
/* irq is locked */ |
spinlock_lock(&box->irq_lock); |
|
ASSERT(irq->notif_cfg.answerbox == box); |
233,11 → 240,19 |
/* Remove the IRQ from the answerbox's list. */ |
list_remove(&irq->notif_cfg.link); |
|
/* |
* We need to drop the IRQ lock now because hash_table_remove() will try |
* to reacquire it. That basically violates the natural locking order, |
* but a deadlock in hash_table_remove() is prevented by the fact that |
* we already held the IRQ lock and didn't drop the hash table lock in |
* the meantime. |
*/ |
spinlock_unlock(&irq->lock); |
|
/* Remove the IRQ from the uspace IRQ hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
|
spinlock_unlock(&irq_uspace_hash_table_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&box->irq_lock); |
|
/* Free up the IRQ structure. */ |
291,13 → 306,21 |
/* Unlist from the answerbox. */ |
list_remove(&irq->notif_cfg.link); |
|
/* Remove from the hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
|
/* Free up the pseudo code and associated structures. */ |
code_free(irq->notif_cfg.code); |
|
/* |
* We need to drop the IRQ lock now because hash_table_remove() |
* will try to reacquire it. That basically violates the natural |
* locking order, but a deadlock in hash_table_remove() is |
* prevented by the fact that we already held the IRQ lock and |
* didn't drop the hash table lock in the meantime. |
*/ |
spinlock_unlock(&irq->lock); |
|
/* Remove from the hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
|
free(irq); |
} |
|