Changeset c621f4aa in mainline for kernel/generic/src/ipc/ipc.c


Ignore:
Timestamp:
2010-07-25T10:11:13Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
377cce8
Parents:
24a2517 (diff), a2da43c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline.

File:
1 edited

Legend:

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

    r24a2517 rc621f4aa  
    6666/** Initialize a call structure.
    6767 *
    68  * @param call          Call structure to be initialized.
     68 * @param call Call structure to be initialized.
     69 *
    6970 */
    7071static void _ipc_call_init(call_t *call)
     
    7778
    7879/** Allocate and initialize a call structure.
    79  * 
     80 *
    8081 * The call is initialized, so that the reply will be directed to
    8182 * TASK->answerbox.
    8283 *
    83  * @param flags         Parameters for slab_alloc (e.g FRAME_ATOMIC).
    84  *
    85  * @return              If flags permit it, return NULL, or initialized kernel
    86  *                      call structure.
    87  */
    88 call_t *ipc_call_alloc(int flags)
    89 {
    90         call_t *call;
    91 
    92         call = slab_alloc(ipc_call_slab, flags);
     84 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC).
     85 *
     86 * @return If flags permit it, return NULL, or initialized kernel
     87 *         call structure.
     88 *
     89 */
     90call_t *ipc_call_alloc(unsigned int flags)
     91{
     92        call_t *call = slab_alloc(ipc_call_slab, flags);
    9393        if (call)
    9494                _ipc_call_init(call);
    95 
     95       
    9696        return call;
    9797}
     
    9999/** Deallocate a call structure.
    100100 *
    101  * @param call          Call structure to be freed.
     101 * @param call Call structure to be freed.
     102 *
    102103 */
    103104void ipc_call_free(call_t *call)
     
    111112/** Initialize an answerbox structure.
    112113 *
    113  * @param box           Answerbox structure to be initialized.
    114  * @param task          Task to which the answerbox belongs.
     114 * @param box  Answerbox structure to be initialized.
     115 * @param task Task to which the answerbox belongs.
     116 *
    115117 */
    116118void ipc_answerbox_init(answerbox_t *box, task_t *task)
    117119{
    118         spinlock_initialize(&box->lock, "ipc_box_lock");
    119         spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
     120        irq_spinlock_initialize(&box->lock, "ipc.box.lock");
     121        irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock");
    120122        waitq_initialize(&box->wq);
    121123        link_initialize(&box->sync_box_link);
     
    131133/** Connect a phone to an answerbox.
    132134 *
    133  * @param phone         Initialized phone structure.
    134  * @param box           Initialized answerbox structure.
     135 * @param phone Initialized phone structure.
     136 * @param box   Initialized answerbox structure.
     137 *
    135138 */
    136139void ipc_phone_connect(phone_t *phone, answerbox_t *box)
    137140{
    138141        mutex_lock(&phone->lock);
    139 
     142       
    140143        phone->state = IPC_PHONE_CONNECTED;
    141144        phone->callee = box;
    142 
    143         spinlock_lock(&box->lock);
     145       
     146        irq_spinlock_lock(&box->lock, true);
    144147        list_append(&phone->link, &box->connected_phones);
    145         spinlock_unlock(&box->lock);
    146 
     148        irq_spinlock_unlock(&box->lock, true);
     149       
    147150        mutex_unlock(&phone->lock);
    148151}
     
    150153/** Initialize a phone structure.
    151154 *
    152  * @param phone         Phone structure to be initialized.
     155 * @param phone Phone structure to be initialized.
     156 *
    153157 */
    154158void ipc_phone_init(phone_t *phone)
     
    162166/** Helper function to facilitate synchronous calls.
    163167 *
    164  * @param phone         Destination kernel phone structure.
    165  * @param request       Call structure with request.
    166  *
    167  * @return              EOK on success or EINTR if the sleep was interrupted.
     168 * @param phone   Destination kernel phone structure.
     169 * @param request Call structure with request.
     170 *
     171 * @return EOK on success or EINTR if the sleep was interrupted.
     172 *
    168173 */
    169174int ipc_call_sync(phone_t *phone, call_t *request)
    170175{
    171         answerbox_t *sync_box;
    172         ipl_t ipl;
    173 
    174         sync_box = slab_alloc(ipc_answerbox_slab, 0);
     176        answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0);
    175177        ipc_answerbox_init(sync_box, TASK);
    176 
     178       
    177179        /*
    178180         * Put the answerbox on the TASK's list of synchronous answerboxes so
    179181         * that it can be cleaned up if the call is interrupted.
    180182         */
    181         ipl = interrupts_disable();
    182         spinlock_lock(&TASK->lock);
     183        irq_spinlock_lock(&TASK->lock, true);
    183184        list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
    184         spinlock_unlock(&TASK->lock);
    185         interrupts_restore(ipl);
    186 
     185        irq_spinlock_unlock(&TASK->lock, true);
     186       
    187187        /* We will receive data in a special box. */
    188188        request->callerbox = sync_box;
    189 
     189       
    190190        ipc_call(phone, request);
    191191        if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
    192192            SYNCH_FLAGS_INTERRUPTIBLE)) {
    193                 /* The answerbox and the call will be freed by ipc_cleanup(). */
     193                /* The answerbox and the call will be freed by ipc_cleanup(). */
    194194                return EINTR;
    195195        }
    196 
     196       
    197197        /*
    198198         * The answer arrived without interruption so we can remove the
    199199         * answerbox from the TASK's list of synchronous answerboxes.
    200200         */
    201         (void) interrupts_disable();
    202         spinlock_lock(&TASK->lock);
     201        irq_spinlock_lock(&TASK->lock, true);
    203202        list_remove(&sync_box->sync_box_link);
    204         spinlock_unlock(&TASK->lock);
    205         interrupts_restore(ipl);
    206 
     203        irq_spinlock_unlock(&TASK->lock, true);
     204       
    207205        slab_free(ipc_answerbox_slab, sync_box);
    208206        return EOK;
     
    211209/** Answer a message which was not dispatched and is not listed in any queue.
    212210 *
    213  * @param call          Call structure to be answered.
    214  * @param selflocked    If true, then TASK->answebox is locked.
     211 * @param call       Call structure to be answered.
     212 * @param selflocked If true, then TASK->answebox is locked.
     213 *
    215214 */
    216215static void _ipc_answer_free_call(call_t *call, bool selflocked)
     
    218217        answerbox_t *callerbox = call->callerbox;
    219218        bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
    220 
     219       
     220        /* Count sent answer */
     221        irq_spinlock_lock(&TASK->lock, true);
     222        TASK->ipc_info.answer_sent++;
     223        irq_spinlock_unlock(&TASK->lock, true);
     224       
    221225        call->flags |= IPC_CALL_ANSWERED;
    222 
     226       
    223227        if (call->flags & IPC_CALL_FORWARDED) {
    224228                if (call->caller_phone) {
     
    227231                }
    228232        }
    229 
     233       
    230234        if (do_lock)
    231                 spinlock_lock(&callerbox->lock);
     235                irq_spinlock_lock(&callerbox->lock, true);
     236       
    232237        list_append(&call->link, &callerbox->answers);
     238       
    233239        if (do_lock)
    234                 spinlock_unlock(&callerbox->lock);
     240                irq_spinlock_unlock(&callerbox->lock, true);
     241       
    235242        waitq_wakeup(&callerbox->wq, WAKEUP_FIRST);
    236243}
     
    238245/** Answer a message which is in a callee queue.
    239246 *
    240  * @param box           Answerbox that is answering the message.
    241  * @param call          Modified request that is being sent back.
     247 * @param box  Answerbox that is answering the message.
     248 * @param call Modified request that is being sent back.
     249 *
    242250 */
    243251void ipc_answer(answerbox_t *box, call_t *call)
    244252{
    245253        /* Remove from active box */
    246         spinlock_lock(&box->lock);
     254        irq_spinlock_lock(&box->lock, true);
    247255        list_remove(&call->link);
    248         spinlock_unlock(&box->lock);
     256        irq_spinlock_unlock(&box->lock, true);
     257       
    249258        /* Send back answer */
    250259        _ipc_answer_free_call(call, false);
     
    256265 * message and sending it as a normal answer.
    257266 *
    258  * @param phone         Phone structure the call should appear to come from.
    259  * @param call          Call structure to be answered.
    260  * @param err           Return value to be used for the answer.
     267 * @param phone Phone structure the call should appear to come from.
     268 * @param call  Call structure to be answered.
     269 * @param err   Return value to be used for the answer.
     270 *
    261271 */
    262272void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err)
     
    270280/** Unsafe unchecking version of ipc_call.
    271281 *
    272  * @param phone         Phone structure the call comes from.
    273  * @param box           Destination answerbox structure.
    274  * @param call          Call structure with request.
     282 * @param phone Phone structure the call comes from.
     283 * @param box   Destination answerbox structure.
     284 * @param call  Call structure with request.
     285 *
    275286 */
    276287static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
    277288{
     289        /* Count sent ipc call */
     290        irq_spinlock_lock(&TASK->lock, true);
     291        TASK->ipc_info.call_sent++;
     292        irq_spinlock_unlock(&TASK->lock, true);
     293       
    278294        if (!(call->flags & IPC_CALL_FORWARDED)) {
    279295                atomic_inc(&phone->active_calls);
    280296                call->data.phone = phone;
    281297        }
    282 
    283         spinlock_lock(&box->lock);
     298       
     299        irq_spinlock_lock(&box->lock, true);
    284300        list_append(&call->link, &box->calls);
    285         spinlock_unlock(&box->lock);
     301        irq_spinlock_unlock(&box->lock, true);
     302       
    286303        waitq_wakeup(&box->wq, WAKEUP_FIRST);
    287304}
     
    289306/** Send an asynchronous request using a phone to an answerbox.
    290307 *
    291  * @param phone         Phone structure the call comes from and which is
    292  *                      connected to the destination answerbox.
    293  * @param call          Call structure with request.
    294  *
    295  * @return              Return 0 on success, ENOENT on error.
     308 * @param phone Phone structure the call comes from and which is
     309 *              connected to the destination answerbox.
     310 * @param call  Call structure with request.
     311 *
     312 * @return Return 0 on success, ENOENT on error.
     313 *
    296314 */
    297315int ipc_call(phone_t *phone, call_t *call)
    298316{
    299         answerbox_t *box;
    300 
    301317        mutex_lock(&phone->lock);
    302318        if (phone->state != IPC_PHONE_CONNECTED) {
     
    311327                                ipc_backsend_err(phone, call, ENOENT);
    312328                }
     329               
    313330                return ENOENT;
    314331        }
    315         box = phone->callee;
     332       
     333        answerbox_t *box = phone->callee;
    316334        _ipc_call(phone, box, call);
    317335       
     
    325343 * lazily later.
    326344 *
    327  * @param phone         Phone structure to be hung up.
    328  *             
    329  * @return              Return 0 if the phone is disconnected.
    330  *                      Return -1 if the phone was already disconnected.
     345 * @param phone Phone structure to be hung up.
     346 *
     347 * @return 0 if the phone is disconnected.
     348 * @return -1 if the phone was already disconnected.
     349 *
    331350 */
    332351int ipc_phone_hangup(phone_t *phone)
    333352{
    334         answerbox_t *box;
    335         call_t *call;
    336        
    337353        mutex_lock(&phone->lock);
    338354        if (phone->state == IPC_PHONE_FREE ||
     
    342358                return -1;
    343359        }
    344         box = phone->callee;
     360       
     361        answerbox_t *box = phone->callee;
    345362        if (phone->state != IPC_PHONE_SLAMMED) {
    346363                /* Remove myself from answerbox */
    347                 spinlock_lock(&box->lock);
     364                irq_spinlock_lock(&box->lock, true);
    348365                list_remove(&phone->link);
    349                 spinlock_unlock(&box->lock);
    350 
    351                 call = ipc_call_alloc(0);
     366                irq_spinlock_unlock(&box->lock, true);
     367               
     368                call_t *call = ipc_call_alloc(0);
    352369                IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
    353370                call->flags |= IPC_CALL_DISCARD_ANSWER;
    354371                _ipc_call(phone, box, call);
    355372        }
    356 
     373       
    357374        phone->state = IPC_PHONE_HUNGUP;
    358375        mutex_unlock(&phone->lock);
    359 
     376       
    360377        return 0;
    361378}
     
    363380/** Forwards call from one answerbox to another one.
    364381 *
    365  * @param call          Call structure to be redirected.
    366  * @param newphone      Phone structure to target answerbox.
    367  * @param oldbox        Old answerbox structure.
    368  * @param mode          Flags that specify mode of the forward operation.
    369  *
    370  * @return              Return 0 if forwarding succeeded or an error code if
    371  *                      there was error.
    372  * 
     382 * @param call     Call structure to be redirected.
     383 * @param newphone Phone structure to target answerbox.
     384 * @param oldbox   Old answerbox structure.
     385 * @param mode     Flags that specify mode of the forward operation.
     386 *
     387 * @return 0 if forwarding succeeded or an error code if
     388 *         there was an error.
     389 *
    373390 * The return value serves only as an information for the forwarder,
    374391 * the original caller is notified automatically with EFORWARD.
    375  */
    376 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode)
    377 {
    378         spinlock_lock(&oldbox->lock);
     392 *
     393 */
     394int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox,
     395    unsigned int mode)
     396{
     397        /* Count forwarded calls */
     398        irq_spinlock_lock(&TASK->lock, true);
     399        TASK->ipc_info.forwarded++;
     400        irq_spinlock_pass(&TASK->lock, &oldbox->lock);
    379401        list_remove(&call->link);
    380         spinlock_unlock(&oldbox->lock);
    381 
     402        irq_spinlock_unlock(&oldbox->lock, true);
     403       
    382404        if (mode & IPC_FF_ROUTE_FROM_ME) {
    383405                if (!call->caller_phone)
     
    385407                call->data.phone = newphone;
    386408        }
    387 
     409       
    388410        return ipc_call(newphone, call);
    389411}
     
    392414/** Wait for a phone call.
    393415 *
    394  * @param box           Answerbox expecting the call.
    395  * @param usec          Timeout in microseconds. See documentation for
    396  *                      waitq_sleep_timeout() for decription of its special
    397  *                      meaning.
    398  * @param flags         Select mode of sleep operation. See documentation for
    399  *                      waitq_sleep_timeout() for description of its special
    400  *                      meaning.
    401  * @return              Recived call structure or NULL.
    402  *
     416 * @param box   Answerbox expecting the call.
     417 * @param usec  Timeout in microseconds. See documentation for
     418 *              waitq_sleep_timeout() for decription of its special
     419 *              meaning.
     420 * @param flags Select mode of sleep operation. See documentation for
     421 *              waitq_sleep_timeout() for description of its special
     422 *              meaning.
     423 *
     424 * @return Recived call structure or NULL.
     425 *
    403426 * To distinguish between a call and an answer, have a look at call->flags.
    404  */
    405 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags)
     427 *
     428 */
     429call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags)
    406430{
    407431        call_t *request;
    408         ipl_t ipl;
     432        uint64_t irq_cnt = 0;
     433        uint64_t answer_cnt = 0;
     434        uint64_t call_cnt = 0;
    409435        int rc;
    410 
     436       
    411437restart:
    412438        rc = waitq_sleep_timeout(&box->wq, usec, flags);
     
    414440                return NULL;
    415441       
    416         spinlock_lock(&box->lock);
     442        irq_spinlock_lock(&box->lock, true);
    417443        if (!list_empty(&box->irq_notifs)) {
    418                 ipl = interrupts_disable();
    419                 spinlock_lock(&box->irq_lock);
    420 
     444                /* Count received IRQ notification */
     445                irq_cnt++;
     446               
     447                irq_spinlock_lock(&box->irq_lock, false);
     448               
    421449                request = list_get_instance(box->irq_notifs.next, call_t, link);
    422450                list_remove(&request->link);
    423 
    424                 spinlock_unlock(&box->irq_lock);
    425                 interrupts_restore(ipl);
     451               
     452                irq_spinlock_unlock(&box->irq_lock, false);
    426453        } else if (!list_empty(&box->answers)) {
     454                /* Count received answer */
     455                answer_cnt++;
     456               
    427457                /* Handle asynchronous answers */
    428458                request = list_get_instance(box->answers.next, call_t, link);
     
    430460                atomic_dec(&request->data.phone->active_calls);
    431461        } else if (!list_empty(&box->calls)) {
     462                /* Count received call */
     463                call_cnt++;
     464               
    432465                /* Handle requests */
    433466                request = list_get_instance(box->calls.next, call_t, link);
    434467                list_remove(&request->link);
     468               
    435469                /* Append request to dispatch queue */
    436470                list_append(&request->link, &box->dispatched_calls);
    437471        } else {
    438472                /* This can happen regularly after ipc_cleanup */
    439                 spinlock_unlock(&box->lock);
     473                irq_spinlock_unlock(&box->lock, true);
    440474                goto restart;
    441475        }
    442         spinlock_unlock(&box->lock);
     476       
     477        irq_spinlock_pass(&box->lock, &TASK->lock);
     478       
     479        TASK->ipc_info.irq_notif_received += irq_cnt;
     480        TASK->ipc_info.answer_received += answer_cnt;
     481        TASK->ipc_info.call_received += call_cnt;
     482       
     483        irq_spinlock_unlock(&TASK->lock, true);
     484       
    443485        return request;
    444486}
     
    446488/** Answer all calls from list with EHANGUP answer.
    447489 *
    448  * @param lst           Head of the list to be cleaned up.
     490 * @param lst Head of the list to be cleaned up.
     491 *
    449492 */
    450493void ipc_cleanup_call_list(link_t *lst)
    451494{
    452         call_t *call;
    453 
    454495        while (!list_empty(lst)) {
    455                 call = list_get_instance(lst->next, call_t, link);
     496                call_t *call = list_get_instance(lst->next, call_t, link);
    456497                if (call->buffer)
    457498                        free(call->buffer);
     499               
    458500                list_remove(&call->link);
    459 
     501               
    460502                IPC_SET_RETVAL(call->data, EHANGUP);
    461503                _ipc_answer_free_call(call, true);
     
    465507/** Disconnects all phones connected to an answerbox.
    466508 *
    467  * @param box           Answerbox to disconnect phones from.
    468  * @param notify_box    If true, the answerbox will get a hangup message for
    469  *                      each disconnected phone.
     509 * @param box        Answerbox to disconnect phones from.
     510 * @param notify_box If true, the answerbox will get a hangup message for
     511 *                   each disconnected phone.
     512 *
    470513 */
    471514void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box)
     
    473516        phone_t *phone;
    474517        DEADLOCK_PROBE_INIT(p_phonelck);
    475         ipl_t ipl;
    476         call_t *call;
    477 
    478         call = notify_box ? ipc_call_alloc(0) : NULL;
    479 
     518       
     519        call_t *call = notify_box ? ipc_call_alloc(0) : NULL;
     520       
    480521        /* Disconnect all phones connected to our answerbox */
    481522restart_phones:
    482         ipl = interrupts_disable();
    483         spinlock_lock(&box->lock);
     523        irq_spinlock_lock(&box->lock, true);
    484524        while (!list_empty(&box->connected_phones)) {
    485525                phone = list_get_instance(box->connected_phones.next,
    486526                    phone_t, link);
    487527                if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
    488                         spinlock_unlock(&box->lock);
    489                         interrupts_restore(ipl);
     528                        irq_spinlock_unlock(&box->lock, true);
    490529                        DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD);
    491530                        goto restart_phones;
     
    494533                /* Disconnect phone */
    495534                ASSERT(phone->state == IPC_PHONE_CONNECTED);
    496 
     535               
    497536                list_remove(&phone->link);
    498537                phone->state = IPC_PHONE_SLAMMED;
    499 
     538               
    500539                if (notify_box) {
    501540                        mutex_unlock(&phone->lock);
    502                         spinlock_unlock(&box->lock);
    503                         interrupts_restore(ipl);
    504 
     541                        irq_spinlock_unlock(&box->lock, true);
     542                       
    505543                        /*
    506544                         * Send one message to the answerbox for each
     
    512550                        call->flags |= IPC_CALL_DISCARD_ANSWER;
    513551                        _ipc_call(phone, box, call);
    514 
     552                       
    515553                        /* Allocate another call in advance */
    516554                        call = ipc_call_alloc(0);
    517 
     555                       
    518556                        /* Must start again */
    519557                        goto restart_phones;
    520558                }
    521 
     559               
    522560                mutex_unlock(&phone->lock);
    523561        }
    524 
    525         spinlock_unlock(&box->lock);
    526         interrupts_restore(ipl);
    527 
     562       
     563        irq_spinlock_unlock(&box->lock, true);
     564       
    528565        /* Free unused call */
    529566        if (call)
     
    531568}
    532569
    533 /** Cleans up all IPC communication of the current task.
     570/** Clean up all IPC communication of the current task.
    534571 *
    535572 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you
    536573 * have to change it as well if you want to cleanup other tasks than TASK.
     574 *
    537575 */
    538576void ipc_cleanup(void)
    539577{
    540         int i;
    541         call_t *call;
    542         ipl_t ipl;
    543 
    544578        /* Disconnect all our phones ('ipc_phone_hangup') */
     579        size_t i;
    545580        for (i = 0; i < IPC_MAX_PHONES; i++)
    546581                ipc_phone_hangup(&TASK->phones[i]);
    547 
     582       
    548583        /* Unsubscribe from any event notifications. */
    549584        event_cleanup_answerbox(&TASK->answerbox);
    550 
     585       
    551586        /* Disconnect all connected irqs */
    552587        ipc_irq_cleanup(&TASK->answerbox);
    553 
     588       
    554589        /* Disconnect all phones connected to our regular answerbox */
    555590        ipc_answerbox_slam_phones(&TASK->answerbox, false);
    556 
     591       
    557592#ifdef CONFIG_UDEBUG
    558593        /* Clean up kbox thread and communications */
    559594        ipc_kbox_cleanup();
    560595#endif
    561 
     596       
    562597        /* Answer all messages in 'calls' and 'dispatched_calls' queues */
    563         spinlock_lock(&TASK->answerbox.lock);
     598        irq_spinlock_lock(&TASK->answerbox.lock, true);
    564599        ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls);
    565600        ipc_cleanup_call_list(&TASK->answerbox.calls);
    566         spinlock_unlock(&TASK->answerbox.lock);
     601        irq_spinlock_unlock(&TASK->answerbox.lock, true);
    567602       
    568603        /* Wait for all answers to interrupted synchronous calls to arrive */
    569         ipl = interrupts_disable();
     604        ipl_t ipl = interrupts_disable();
    570605        while (!list_empty(&TASK->sync_box_head)) {
    571606                answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
    572607                    answerbox_t, sync_box_link);
    573 
     608               
    574609                list_remove(&box->sync_box_link);
    575                 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
     610                call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
    576611                    SYNCH_FLAGS_NONE);
    577612                ipc_call_free(call);
     
    579614        }
    580615        interrupts_restore(ipl);
    581 
     616       
    582617        /* Wait for all answers to asynchronous calls to arrive */
    583         while (1) {
    584                 /* Go through all phones, until all are FREE... */
    585                 /* Locking not needed, no one else should modify
    586                  * it, when we are in cleanup */
     618        while (true) {
     619                /*
     620                 * Go through all phones, until they are all FREE
     621                 * Locking is not needed, no one else should modify
     622                 * it when we are in cleanup
     623                 */
    587624                for (i = 0; i < IPC_MAX_PHONES; i++) {
    588625                        if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
     
    592629                        }
    593630                       
    594                         /* Just for sure, we might have had some
    595                          * IPC_PHONE_CONNECTING phones */
     631                        /*
     632                         * Just for sure, we might have had some
     633                         * IPC_PHONE_CONNECTING phones
     634                         */
    596635                        if (TASK->phones[i].state == IPC_PHONE_CONNECTED)
    597636                                ipc_phone_hangup(&TASK->phones[i]);
    598                         /* If the hangup succeeded, it has sent a HANGUP
     637                       
     638                        /*
     639                         * If the hangup succeeded, it has sent a HANGUP
    599640                         * message, the IPC is now in HUNGUP state, we
    600                          * wait for the reply to come */
     641                         * wait for the reply to come
     642                         */
    601643                       
    602644                        if (TASK->phones[i].state != IPC_PHONE_FREE)
    603645                                break;
    604646                }
    605                 /* Voila, got into cleanup */
     647               
     648                /* Got into cleanup */
    606649                if (i == IPC_MAX_PHONES)
    607650                        break;
    608651               
    609                 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
     652                call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
    610653                    SYNCH_FLAGS_NONE);
    611654                ASSERT((call->flags & IPC_CALL_ANSWERED) ||
     
    619662                if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
    620663                        atomic_dec(&TASK->active_calls);
     664               
    621665                ipc_call_free(call);
    622666        }
    623667}
    624668
    625 
    626 /** Initilize IPC subsystem */
     669/** Initilize IPC subsystem
     670 *
     671 */
    627672void ipc_init(void)
    628673{
     
    633678}
    634679
    635 
    636680/** List answerbox contents.
    637681 *
    638  * @param taskid        Task ID.
     682 * @param taskid Task ID.
     683 *
    639684 */
    640685void ipc_print_task(task_id_t taskid)
    641686{
    642         task_t *task;
    643         int i;
    644         call_t *call;
    645         link_t *tmp;
    646        
    647         spinlock_lock(&tasks_lock);
    648         task = task_find_by_id(taskid);
    649         if (task)
    650                 spinlock_lock(&task->lock);
    651         spinlock_unlock(&tasks_lock);
    652         if (!task)
     687        irq_spinlock_lock(&tasks_lock, true);
     688        task_t *task = task_find_by_id(taskid);
     689       
     690        if (!task) {
     691                irq_spinlock_unlock(&tasks_lock, true);
    653692                return;
    654 
     693        }
     694       
     695        /* Hand-over-hand locking */
     696        irq_spinlock_exchange(&tasks_lock, &task->lock);
     697       
    655698        /* Print opened phones & details */
    656699        printf("PHONE:\n");
     700       
     701        size_t i;
    657702        for (i = 0; i < IPC_MAX_PHONES; i++) {
    658703                if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) {
     
    660705                        continue;
    661706                }
     707               
    662708                if (task->phones[i].state != IPC_PHONE_FREE) {
    663                         printf("%d: ", i);
     709                        printf("%" PRIs ": ", i);
     710                       
    664711                        switch (task->phones[i].state) {
    665712                        case IPC_PHONE_CONNECTING:
     
    667714                                break;
    668715                        case IPC_PHONE_CONNECTED:
    669                                 printf("connected to: %p ", 
    670                                        task->phones[i].callee);
     716                                printf("connected to: %p ",
     717                                    task->phones[i].callee);
    671718                                break;
    672719                        case IPC_PHONE_SLAMMED:
    673720                                printf("slammed by: %p ",
    674                                        task->phones[i].callee);
     721                                    task->phones[i].callee);
    675722                                break;
    676723                        case IPC_PHONE_HUNGUP:
    677724                                printf("hung up - was: %p ",
    678                                        task->phones[i].callee);
     725                                    task->phones[i].callee);
    679726                                break;
    680727                        default:
    681728                                break;
    682729                        }
    683                         printf("active: %ld\n",
     730                       
     731                        printf("active: %" PRIun "\n",
    684732                            atomic_get(&task->phones[i].active_calls));
    685733                }
     734               
    686735                mutex_unlock(&task->phones[i].lock);
    687736        }
    688 
    689 
     737       
     738        irq_spinlock_lock(&task->answerbox.lock, false);
     739       
     740        link_t *cur;
     741       
    690742        /* Print answerbox - calls */
    691         spinlock_lock(&task->answerbox.lock);
    692743        printf("ABOX - CALLS:\n");
    693         for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls;
    694             tmp = tmp->next) {
    695                 call = list_get_instance(tmp, call_t, link);
     744        for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls;
     745            cur = cur->next) {
     746                call_t *call = list_get_instance(cur, call_t, link);
    696747                printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
    697748                    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
     
    703754                    call->flags);
    704755        }
    705         /* Print answerbox - calls */
     756       
     757        /* Print answerbox - dispatched calls */
    706758        printf("ABOX - DISPATCHED CALLS:\n");
    707         for (tmp = task->answerbox.dispatched_calls.next;
    708             tmp != &task->answerbox.dispatched_calls;
    709             tmp = tmp->next) {
    710                 call = list_get_instance(tmp, call_t, link);
     759        for (cur = task->answerbox.dispatched_calls.next;
     760            cur != &task->answerbox.dispatched_calls;
     761            cur = cur->next) {
     762                call_t *call = list_get_instance(cur, call_t, link);
    711763                printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
    712764                    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
     
    718770                    call->flags);
    719771        }
    720         /* Print answerbox - calls */
     772       
     773        /* Print answerbox - answers */
    721774        printf("ABOX - ANSWERS:\n");
    722         for (tmp = task->answerbox.answers.next;
    723             tmp != &task->answerbox.answers;
    724             tmp = tmp->next) {
    725                 call = list_get_instance(tmp, call_t, link);
     775        for (cur = task->answerbox.answers.next;
     776            cur != &task->answerbox.answers;
     777            cur = cur->next) {
     778                call_t *call = list_get_instance(cur, call_t, link);
    726779                printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun
    727780                    " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
     
    731784                    call->flags);
    732785        }
    733 
    734         spinlock_unlock(&task->answerbox.lock);
    735         spinlock_unlock(&task->lock);
     786       
     787        irq_spinlock_unlock(&task->answerbox.lock, false);
     788        irq_spinlock_unlock(&task->lock, true);
    736789}
    737790
Note: See TracChangeset for help on using the changeset viewer.