Changeset e9d15d9 in mainline for kernel/generic/src/ipc/irq.c


Ignore:
Timestamp:
2017-08-18T21:15:26Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
24abb85d
Parents:
1c85bae
Message:

Turn IRQ structures into kernel objects

ipc_irq_subscribe() now returns a capability for the underlying IRQ kernel
object. ipc_irq_unsubscribe() can now be done only with a valid IRQ capability.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/irq.c

    r1c85bae re9d15d9  
    8484#include <print.h>
    8585#include <macros.h>
     86#include <kobject/kobject.h>
    8687
    8788static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
     
    298299 * @param ucode   Uspace pointer to top-half pseudocode.
    299300 *
    300  * @return EOK on success or a negative error code.
     301 * @return  IRQ capability.
     302 * @return  Negative error code.
    301303 *
    302304 */
     
    321323       
    322324        /*
    323          * Allocate and populate the IRQ structure.
     325         * Allocate and populate the IRQ kernel object.
    324326         */
    325         irq_t *irq = malloc(sizeof(irq_t), 0);
    326        
     327        int cap = kobject_alloc(TASK);
     328        if (cap < 0)
     329                return cap;
     330        kobject_t *kobj = kobject_get_current(cap, KOBJECT_TYPE_ALLOCATED);
     331        assert(kobj);
     332        kobj->type = KOBJECT_TYPE_IRQ;
     333
     334        irq_t *irq = &kobj->irq;
    327335        irq_initialize(irq);
    328336        irq->devno = devno;
     
    351359                irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    352360               
    353                 free(irq);
     361                kobject_free(TASK, cap);
    354362                return EEXIST;
    355363        }
     
    366374        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    367375       
    368         return EOK;
     376        return cap;
    369377}
    370378
    371379/** Unsubscribe task from IRQ notification.
    372380 *
    373  * @param box   Answerbox associated with the notification.
    374  * @param inr   IRQ number.
    375  * @param devno Device number.
     381 * @param box      Answerbox associated with the notification.
     382 * @param irq_cap  IRQ capability.
    376383 *
    377384 * @return EOK on success or a negative error code.
    378385 *
    379386 */
    380 int ipc_irq_unsubscribe(answerbox_t *box, inr_t inr, devno_t devno)
    381 {
    382         sysarg_t key[] = {
    383                 (sysarg_t) inr,
    384                 (sysarg_t) devno
    385         };
    386        
    387         if ((inr < 0) || (inr > last_inr))
    388                 return ELIMIT;
    389        
     387int ipc_irq_unsubscribe(answerbox_t *box, int irq_cap)
     388{
     389        kobject_t *kobj = kobject_get_current(irq_cap, KOBJECT_TYPE_IRQ);
     390        if (!kobj)
     391                return ENOENT;
     392        irq_t *irq = &kobj->irq;
     393
    390394        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    391         link_t *lnk = hash_table_find(&irq_uspace_hash_table, key);
    392         if (!lnk) {
    393                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    394                 return ENOENT;
    395         }
    396        
    397         irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
    398        
    399         /* irq is locked */
     395        irq_spinlock_lock(&irq->lock, false);
    400396        irq_spinlock_lock(&box->irq_lock, false);
    401397       
     
    405401        list_remove(&irq->notif_cfg.link);
    406402       
    407         /*
    408          * We need to drop the IRQ lock now because hash_table_remove() will try
    409          * to reacquire it. That basically violates the natural locking order,
    410          * but a deadlock in hash_table_remove() is prevented by the fact that
    411          * we already held the IRQ lock and didn't drop the hash table lock in
    412          * the meantime.
    413          */
    414         irq_spinlock_unlock(&irq->lock, false);
    415        
    416403        /* Remove the IRQ from the uspace IRQ hash table. */
    417         hash_table_remove(&irq_uspace_hash_table, key, 2);
     404        hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
    418405       
    419406        irq_spinlock_unlock(&box->irq_lock, false);
     407        /* irq->lock unlocked by the hash table remove_callback */
    420408        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    421409       
     
    423411        code_free(irq->notif_cfg.code);
    424412       
    425         /* Free up the IRQ structure. */
    426         free(irq);
     413        /* Free up the IRQ kernel object. */
     414        kobject_free(TASK, irq_cap);
    427415       
    428416        return EOK;
     
    431419/** Disconnect all IRQ notifications from an answerbox.
    432420 *
    433  * This function is effective because the answerbox contains
    434  * list of all irq_t structures that are subscribed to
    435  * send notifications to it.
     421 * This function is effective because the answerbox contains list of all irq_t
     422 * structures that are subscribed to send notifications to it.
    436423 *
    437424 * @param box Answerbox for which we want to carry out the cleanup.
     
    460447                }
    461448               
    462                 sysarg_t key[2];
    463                 key[0] = irq->inr;
    464                 key[1] = irq->devno;
    465                
    466449                assert(irq->notif_cfg.answerbox == box);
    467450               
     
    469452                list_remove(&irq->notif_cfg.link);
    470453               
    471                 /*
    472                  * We need to drop the IRQ lock now because hash_table_remove()
    473                  * will try to reacquire it. That basically violates the natural
    474                  * locking order, but a deadlock in hash_table_remove() is
    475                  * prevented by the fact that we already held the IRQ lock and
    476                  * didn't drop the hash table lock in the meantime.
    477                  */
    478                 irq_spinlock_unlock(&irq->lock, false);
    479                
    480454                /* Remove from the hash table. */
    481                 hash_table_remove(&irq_uspace_hash_table, key, 2);
     455                hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
    482456               
    483457                /*
     
    488462               
    489463                code_free(irq->notif_cfg.code);
    490                 free(irq);
     464               
     465                // XXX: what to do about the irq capability? The task is in
     466                // clean-up anyway.
    491467               
    492468                /* Reacquire both locks before taking another round. */
Note: See TracChangeset for help on using the changeset viewer.