Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 9306cd7 in mainline


Ignore:
Timestamp:
2017-09-03T18:14:15Z (4 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
3422fb6
Parents:
4d6629f
Message:

Make IRQ subscribe/unsubscribe thread safe again

Location:
kernel/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/irq.h

    r4d6629f r9306cd7  
    5353extern int ipc_irq_subscribe(answerbox_t *, inr_t, sysarg_t, irq_code_t *);
    5454extern int ipc_irq_unsubscribe(answerbox_t *, int);
    55 extern void ipc_irq_cleanup(answerbox_t *);
    5655
    5756/*
  • kernel/generic/src/ipc/ipc.c

    r4d6629f r9306cd7  
    828828        event_cleanup_answerbox(&TASK->answerbox);
    829829       
    830         /* Disconnect all connected irqs */
    831         ipc_irq_cleanup(&TASK->answerbox);
     830        /* Disconnect all connected IRQs */
     831        for_each_cap_current(cap, CAP_TYPE_IRQ) {
     832                ipc_irq_unsubscribe(&TASK->answerbox, cap->handle);
     833        }
    832834       
    833835        /* Disconnect all phones connected to our regular answerbox */
  • kernel/generic/src/ipc/irq.c

    r4d6629f r9306cd7  
    329329        cap_t *cap = cap_get_current(handle, CAP_TYPE_ALLOCATED);
    330330        assert(cap);
    331         cap->type = CAP_TYPE_IRQ;
    332 
     331       
    333332        irq_t *irq = &cap->irq;
    334333        irq_initialize(irq);
     
    344343        /*
    345344         * Enlist the IRQ structure in the uspace IRQ hash table and the
    346          * answerbox's list.
     345         * answerbox's list and make the IRQ capability valid.
    347346         */
    348347        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     
    350349        irq_spinlock_lock(&box->irq_lock, false);
    351350       
     351        cap->type = CAP_TYPE_IRQ;
    352352        hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
    353353        list_append(&irq->notif_cfg.link, &box->irq_list);
     
    370370int ipc_irq_unsubscribe(answerbox_t *box, int handle)
    371371{
     372        irq_spinlock_lock(&TASK->lock, true);
    372373        cap_t *cap = cap_get_current(handle, CAP_TYPE_IRQ);
    373         if (!cap)
     374        if (!cap) {
     375                irq_spinlock_unlock(&TASK->lock, true);
    374376                return ENOENT;
     377        }
     378        cap->type = CAP_TYPE_ALLOCATED;
     379        irq_spinlock_unlock(&TASK->lock, true);
     380       
    375381        irq_t *irq = &cap->irq;
    376 
     382       
    377383        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    378384        irq_spinlock_lock(&irq->lock, false);
     
    398404       
    399405        return EOK;
    400 }
    401 
    402 /** Disconnect all IRQ notifications from an answerbox.
    403  *
    404  * This function is effective because the answerbox contains list of all irq_t
    405  * structures that are subscribed to send notifications to it.
    406  *
    407  * @param box Answerbox for which we want to carry out the cleanup.
    408  *
    409  */
    410 void ipc_irq_cleanup(answerbox_t *box)
    411 {
    412 loop:
    413         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    414         irq_spinlock_lock(&box->irq_lock, false);
    415        
    416         while (!list_empty(&box->irq_list)) {
    417                 DEADLOCK_PROBE_INIT(p_irqlock);
    418                
    419                 irq_t *irq = list_get_instance(list_first(&box->irq_list), irq_t,
    420                     notif_cfg.link);
    421                
    422                 if (!irq_spinlock_trylock(&irq->lock)) {
    423                         /*
    424                          * Avoid deadlock by trying again.
    425                          */
    426                         irq_spinlock_unlock(&box->irq_lock, false);
    427                         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    428                         DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
    429                         goto loop;
    430                 }
    431                
    432                 assert(irq->notif_cfg.answerbox == box);
    433                
    434                 /* Unlist from the answerbox. */
    435                 list_remove(&irq->notif_cfg.link);
    436                
    437                 /* Remove from the hash table. */
    438                 hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
    439                
    440                 /*
    441                  * Release both locks so that we can free the IRQ code.
    442                  */
    443                 irq_spinlock_unlock(&box->irq_lock, false);
    444                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    445                
    446                 code_free(irq->notif_cfg.code);
    447                
    448                 // XXX: what to do about the irq capability? The task is in
    449                 // clean-up anyway.
    450                
    451                 /* Reacquire both locks before taking another round. */
    452                 irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    453                 irq_spinlock_lock(&box->irq_lock, false);
    454         }
    455        
    456         irq_spinlock_unlock(&box->irq_lock, false);
    457         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    458406}
    459407
Note: See TracChangeset for help on using the changeset viewer.