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


Ignore:
Timestamp:
2010-05-24T18:57:31Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
File:
1 edited

Legend:

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

    r666f492 rda1bafb  
    3131 * @{
    3232 */
     33
    3334/**
    3435 * @file
     
    6768 *   structure are finished. Because we hold the hash table lock, we prevent new
    6869 *   IRQs from taking new references to the IRQ structure.
     70 *
    6971 */
    7072
     
    8183/** Free the top-half pseudocode.
    8284 *
    83  * @param code          Pointer to the top-half pseudocode.
     85 * @param code Pointer to the top-half pseudocode.
     86 *
    8487 */
    8588static void code_free(irq_code_t *code)
     
    9396/** Copy the top-half pseudocode from userspace into the kernel.
    9497 *
    95  * @param ucode         Userspace address of the top-half pseudocode.
    96  *
    97  * @return              Kernel address of the copied pseudocode.
     98 * @param ucode Userspace address of the top-half pseudocode.
     99 *
     100 * @return Kernel address of the copied pseudocode.
     101 *
    98102 */
    99103static irq_code_t *code_from_uspace(irq_code_t *ucode)
    100104{
    101         irq_code_t *code;
    102         irq_cmd_t *ucmds;
    103         int rc;
    104 
    105         code = malloc(sizeof(*code), 0);
    106         rc = copy_from_uspace(code, ucode, sizeof(*code));
     105        irq_code_t *code = malloc(sizeof(*code), 0);
     106        int rc = copy_from_uspace(code, ucode, sizeof(*code));
    107107        if (rc != 0) {
    108108                free(code);
     
    114114                return NULL;
    115115        }
    116         ucmds = code->cmds;
     116       
     117        irq_cmd_t *ucmds = code->cmds;
    117118        code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
    118119        rc = copy_from_uspace(code->cmds, ucmds,
     
    123124                return NULL;
    124125        }
    125 
     126       
    126127        return code;
    127128}
     
    141142    unative_t method, irq_code_t *ucode)
    142143{
    143         ipl_t ipl;
    144         irq_code_t *code;
    145         irq_t *irq;
    146         link_t *hlp;
    147144        unative_t key[] = {
    148145                (unative_t) inr,
     
    150147        };
    151148       
     149        irq_code_t *code;
    152150        if (ucode) {
    153151                code = code_from_uspace(ucode);
    154152                if (!code)
    155153                        return EBADMEM;
    156         } else {
     154        } else
    157155                code = NULL;
    158         }
    159156       
    160157        /*
    161158         * Allocate and populate the IRQ structure.
    162159         */
    163         irq = malloc(sizeof(irq_t), 0);
     160        irq_t *irq = malloc(sizeof(irq_t), 0);
     161       
    164162        irq_initialize(irq);
    165163        irq->devno = devno;
     
    177175         * answerbox's list.
    178176         */
    179         ipl = interrupts_disable();
    180         spinlock_lock(&irq_uspace_hash_table_lock);
    181         hlp = hash_table_find(&irq_uspace_hash_table, key);
     177        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     178       
     179        link_t *hlp = hash_table_find(&irq_uspace_hash_table, key);
    182180        if (hlp) {
    183                 irq_t *hirq __attribute__((unused))
    184                     = hash_table_get_instance(hlp, irq_t, link);
     181                irq_t *hirq = hash_table_get_instance(hlp, irq_t, link);
    185182               
    186183                /* hirq is locked */
    187                 spinlock_unlock(&hirq->lock);
     184                irq_spinlock_unlock(&hirq->lock, false);
    188185                code_free(code);
    189                 spinlock_unlock(&irq_uspace_hash_table_lock);
     186                irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     187               
    190188                free(irq);
    191                 interrupts_restore(ipl);
    192189                return EEXISTS;
    193190        }
    194191       
    195         spinlock_lock(&irq->lock);  /* Not really necessary, but paranoid */
    196         spinlock_lock(&box->irq_lock);
     192        /* Locking is not really necessary, but paranoid */
     193        irq_spinlock_lock(&irq->lock, false);
     194        irq_spinlock_lock(&box->irq_lock, false);
     195       
    197196        hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
    198197        list_append(&irq->notif_cfg.link, &box->irq_head);
    199         spinlock_unlock(&box->irq_lock);
    200         spinlock_unlock(&irq->lock);
    201         spinlock_unlock(&irq_uspace_hash_table_lock);
    202        
    203         interrupts_restore(ipl);
     198       
     199        irq_spinlock_unlock(&box->irq_lock, false);
     200        irq_spinlock_unlock(&irq->lock, false);
     201        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     202       
    204203        return EOK;
    205204}
     
    207206/** Unregister task from IRQ notification.
    208207 *
    209  * @param box           Answerbox associated with the notification.
    210  * @param inr           IRQ number.
    211  * @param devno         Device number.
     208 * @param box   Answerbox associated with the notification.
     209 * @param inr   IRQ number.
     210 * @param devno Device number.
     211 *
    212212 */
    213213int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
    214214{
    215         ipl_t ipl;
    216215        unative_t key[] = {
    217216                (unative_t) inr,
    218217                (unative_t) devno
    219218        };
    220         link_t *lnk;
    221         irq_t *irq;
    222 
    223         ipl = interrupts_disable();
    224         spinlock_lock(&irq_uspace_hash_table_lock);
    225         lnk = hash_table_find(&irq_uspace_hash_table, key);
     219       
     220        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     221        link_t *lnk = hash_table_find(&irq_uspace_hash_table, key);
    226222        if (!lnk) {
    227                 spinlock_unlock(&irq_uspace_hash_table_lock);
    228                 interrupts_restore(ipl);
     223                irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    229224                return ENOENT;
    230225        }
    231         irq = hash_table_get_instance(lnk, irq_t, link);
     226       
     227        irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
     228       
    232229        /* irq is locked */
    233         spinlock_lock(&box->irq_lock);
     230        irq_spinlock_lock(&box->irq_lock, false);
    234231       
    235232        ASSERT(irq->notif_cfg.answerbox == box);
     
    237234        /* Free up the pseudo code and associated structures. */
    238235        code_free(irq->notif_cfg.code);
    239 
    240         /* Remove the IRQ from the answerbox's list. */ 
     236       
     237        /* Remove the IRQ from the answerbox's list. */
    241238        list_remove(&irq->notif_cfg.link);
    242 
     239       
    243240        /*
    244241         * We need to drop the IRQ lock now because hash_table_remove() will try
     
    248245         * the meantime.
    249246         */
    250         spinlock_unlock(&irq->lock);
    251 
     247        irq_spinlock_unlock(&irq->lock, false);
     248       
    252249        /* Remove the IRQ from the uspace IRQ hash table. */
    253250        hash_table_remove(&irq_uspace_hash_table, key, 2);
    254251       
    255         spinlock_unlock(&irq_uspace_hash_table_lock);
    256         spinlock_unlock(&box->irq_lock);
     252        irq_spinlock_unlock(&box->irq_lock, false);
     253        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    257254       
    258255        /* Free up the IRQ structure. */
    259256        free(irq);
    260257       
    261         interrupts_restore(ipl);
    262258        return EOK;
    263259}
    264 
    265260
    266261/** Disconnect all IRQ notifications from an answerbox.
     
    270265 * send notifications to it.
    271266 *
    272  * @param box           Answerbox for which we want to carry out the cleanup.
     267 * @param box Answerbox for which we want to carry out the cleanup.
     268 *
    273269 */
    274270void ipc_irq_cleanup(answerbox_t *box)
    275271{
    276         ipl_t ipl;
    277        
    278272loop:
    279         ipl = interrupts_disable();
    280         spinlock_lock(&irq_uspace_hash_table_lock);
    281         spinlock_lock(&box->irq_lock);
     273        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     274        irq_spinlock_lock(&box->irq_lock, false);
    282275       
    283276        while (box->irq_head.next != &box->irq_head) {
    284                 link_t *cur = box->irq_head.next;
    285                 irq_t *irq;
    286277                DEADLOCK_PROBE_INIT(p_irqlock);
    287                 unative_t key[2];
    288                
    289                 irq = list_get_instance(cur, irq_t, notif_cfg.link);
    290                 if (!spinlock_trylock(&irq->lock)) {
     278               
     279                irq_t *irq = list_get_instance(box->irq_head.next, irq_t,
     280                    notif_cfg.link);
     281               
     282                if (!irq_spinlock_trylock(&irq->lock)) {
    291283                        /*
    292284                         * Avoid deadlock by trying again.
    293285                         */
    294                         spinlock_unlock(&box->irq_lock);
    295                         spinlock_unlock(&irq_uspace_hash_table_lock);
    296                         interrupts_restore(ipl);
     286                        irq_spinlock_unlock(&box->irq_lock, false);
     287                        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    297288                        DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
    298289                        goto loop;
    299290                }
     291               
     292                unative_t key[2];
    300293                key[0] = irq->inr;
    301294                key[1] = irq->devno;
    302                
    303295               
    304296                ASSERT(irq->notif_cfg.answerbox == box);
     
    317309                 * didn't drop the hash table lock in the meantime.
    318310                 */
    319                 spinlock_unlock(&irq->lock);
     311                irq_spinlock_unlock(&irq->lock, false);
    320312               
    321313                /* Remove from the hash table. */
     
    325317        }
    326318       
    327         spinlock_unlock(&box->irq_lock);
    328         spinlock_unlock(&irq_uspace_hash_table_lock);
    329         interrupts_restore(ipl);
     319        irq_spinlock_unlock(&box->irq_lock, false);
     320        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    330321}
    331322
    332323/** Add a call to the proper answerbox queue.
    333324 *
    334  * Assume irq->lock is locked.
    335  *
    336  * @param irq           IRQ structure referencing the target answerbox.
    337  * @param call          IRQ notification call.
     325 * Assume irq->lock is locked and interrupts disabled.
     326 *
     327 * @param irq  IRQ structure referencing the target answerbox.
     328 * @param call IRQ notification call.
     329 *
    338330 */
    339331static void send_call(irq_t *irq, call_t *call)
    340332{
    341         spinlock_lock(&irq->notif_cfg.answerbox->irq_lock);
     333        irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false);
    342334        list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs);
    343         spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock);
    344                
     335        irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false);
     336       
    345337        waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST);
    346338}
     
    348340/** Apply the top-half pseudo code to find out whether to accept the IRQ or not.
    349341 *
    350  * @param irq           IRQ structure.
    351  *
    352  * @return              IRQ_ACCEPT if the interrupt is accepted by the
    353  *                      pseudocode. IRQ_DECLINE otherwise.
     342 * @param irq IRQ structure.
     343 *
     344 * @return IRQ_ACCEPT if the interrupt is accepted by the
     345 *         pseudocode, IRQ_DECLINE otherwise.
     346 *
    354347 */
    355348irq_ownership_t ipc_irq_top_half_claim(irq_t *irq)
    356349{
    357         unsigned int i;
    358         unative_t dstval;
    359350        irq_code_t *code = irq->notif_cfg.code;
    360         unative_t *scratch = irq->notif_cfg.scratch;
    361 
     351        uint32_t *scratch = irq->notif_cfg.scratch;
    362352       
    363353        if (!irq->notif_cfg.notify)
     
    367357                return IRQ_DECLINE;
    368358       
     359        size_t i;
    369360        for (i = 0; i < code->cmdcount; i++) {
    370                 unsigned int srcarg = code->cmds[i].srcarg;
    371                 unsigned int dstarg = code->cmds[i].dstarg;
     361                uint32_t dstval;
     362                uintptr_t srcarg = code->cmds[i].srcarg;
     363                uintptr_t dstarg = code->cmds[i].dstarg;
    372364               
    373365                if (srcarg >= IPC_CALL_LEN)
    374366                        break;
     367               
    375368                if (dstarg >= IPC_CALL_LEN)
    376369                        break;
     
    405398                        break;
    406399                case CMD_BTEST:
    407                         if (srcarg && dstarg) {
     400                        if ((srcarg) && (dstarg)) {
    408401                                dstval = scratch[srcarg] & code->cmds[i].value;
    409402                                scratch[dstarg] = dstval;
     
    411404                        break;
    412405                case CMD_PREDICATE:
    413                         if (srcarg && !scratch[srcarg]) {
     406                        if ((srcarg) && (!scratch[srcarg])) {
    414407                                i += code->cmds[i].value;
    415408                                continue;
     
    427420}
    428421
    429 
    430422/* IRQ top-half handler.
    431423 *
    432424 * We expect interrupts to be disabled and the irq->lock already held.
    433425 *
    434  * @param irq           IRQ structure.
     426 * @param irq IRQ structure.
     427 *
    435428 */
    436429void ipc_irq_top_half_handler(irq_t *irq)
    437430{
    438431        ASSERT(irq);
    439 
     432       
    440433        if (irq->notif_cfg.answerbox) {
    441                 call_t *call;
    442 
    443                 call = ipc_call_alloc(FRAME_ATOMIC);
     434                call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    444435                if (!call)
    445436                        return;
     
    448439                /* Put a counter to the message */
    449440                call->priv = ++irq->notif_cfg.counter;
    450 
     441               
    451442                /* Set up args */
    452443                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
     
    456447                IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]);
    457448                IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]);
    458 
     449               
    459450                send_call(irq, call);
    460451        }
     
    463454/** Send notification message.
    464455 *
    465  * @param irq           IRQ structure.
    466  * @param a1            Driver-specific payload argument.
    467  * @param a2            Driver-specific payload argument.
    468  * @param a3            Driver-specific payload argument.
    469  * @param a4            Driver-specific payload argument.
    470  * @param a5            Driver-specific payload argument.
     456 * @param irq IRQ structure.
     457 * @param a1  Driver-specific payload argument.
     458 * @param a2  Driver-specific payload argument.
     459 * @param a3  Driver-specific payload argument.
     460 * @param a4  Driver-specific payload argument.
     461 * @param a5  Driver-specific payload argument.
     462 *
    471463 */
    472464void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
    473465    unative_t a4, unative_t a5)
    474466{
    475         call_t *call;
    476 
    477         spinlock_lock(&irq->lock);
    478 
     467        irq_spinlock_lock(&irq->lock, true);
     468       
    479469        if (irq->notif_cfg.answerbox) {
    480                 call = ipc_call_alloc(FRAME_ATOMIC);
     470                call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    481471                if (!call) {
    482                         spinlock_unlock(&irq->lock);
     472                        irq_spinlock_unlock(&irq->lock, true);
    483473                        return;
    484474                }
     475               
    485476                call->flags |= IPC_CALL_NOTIF;
    486477                /* Put a counter to the message */
    487478                call->priv = ++irq->notif_cfg.counter;
    488 
     479               
    489480                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
    490481                IPC_SET_ARG1(call->data, a1);
     
    496487                send_call(irq, call);
    497488        }
    498         spinlock_unlock(&irq->lock);
     489       
     490        irq_spinlock_unlock(&irq->lock, true);
    499491}
    500492
Note: See TracChangeset for help on using the changeset viewer.