Changeset 46c20c8 in mainline for kernel/generic/src/ipc


Ignore:
Timestamp:
2010-11-26T20:08:10Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
45df59a
Parents:
fb150d78 (diff), ffdd2b9 (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 mainline changes.

Location:
kernel/generic/src/ipc
Files:
6 edited

Legend:

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

    rfb150d78 r46c20c8  
    3838#include <ipc/event_types.h>
    3939#include <mm/slab.h>
    40 #include <arch/types.h>
     40#include <typedefs.h>
    4141#include <synch/spinlock.h>
    4242#include <console/console.h>
     
    137137                        IPC_SET_ARG5(call->data, a5);
    138138                       
    139                         ipl_t ipl = interrupts_disable();
    140                         spinlock_lock(&events[evno].answerbox->irq_lock);
     139                        irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
    141140                        list_append(&call->link, &events[evno].answerbox->irq_notifs);
    142                         spinlock_unlock(&events[evno].answerbox->irq_lock);
    143                         interrupts_restore(ipl);
     141                        irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
    144142                       
    145143                        waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
  • kernel/generic/src/ipc/ipc.c

    rfb150d78 r46c20c8  
    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))) {
    659                         printf("%d: mutex busy\n", i);
     704                        printf("%zu: mutex busy\n", i);
    660705                        continue;
    661706                }
     707               
    662708                if (task->phones[i].state != IPC_PHONE_FREE) {
    663                         printf("%d: ", i);
     709                        printf("%zu: ", 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
  • kernel/generic/src/ipc/ipcrsc.c

    rfb150d78 r46c20c8  
    4545 * - hangup phone (the caller has hung up)
    4646 * - hangup phone (the answerbox is exiting)
    47  * 
     47 *
    4848 * Locking strategy
    4949 *
     
    8585 *
    8686 * Phone hangup
    87  * 
     87 *
    8888 * *** The caller hangs up (sys_ipc_hangup) ***
    8989 * - The phone is disconnected (no more messages can be sent over this phone),
     
    9999 *
    100100 * Call forwarding
    101  * 
     101 *
    102102 * The call can be forwarded, so that the answer to call is passed directly
    103103 * to the original sender. However, this poses special problems regarding
     
    114114 *
    115115 * Cleanup strategy
    116  * 
     116 *
    117117 * 1) Disconnect all our phones ('ipc_phone_hangup').
    118118 *
     
    123123 *
    124124 * 4) Wait for all async answers to arrive and dispose of them.
    125  * 
     125 *
    126126 */
    127127
     
    137137 * @todo Some speedup (hash table?)
    138138 *
    139  * @param callid        Userspace hash of the call. Currently it is the call
    140  *                      structure kernel address.
    141  *
    142  * @return              NULL on not found, otherwise pointer to the call
    143  *                      structure.
     139 * @param callid Userspace hash of the call. Currently it is the call
     140 *               structure kernel address.
     141 *
     142 * @return NULL on not found, otherwise pointer to the call
     143 *         structure.
     144 *
    144145 */
    145146call_t *get_call(unative_t callid)
    146147{
    147148        link_t *lst;
    148         call_t *call, *result = NULL;
    149 
    150         spinlock_lock(&TASK->answerbox.lock);
     149        call_t *result = NULL;
     150       
     151        irq_spinlock_lock(&TASK->answerbox.lock, true);
    151152        for (lst = TASK->answerbox.dispatched_calls.next;
    152153            lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
    153                 call = list_get_instance(lst, call_t, link);
     154                call_t *call = list_get_instance(lst, call_t, link);
    154155                if ((unative_t) call == callid) {
    155156                        result = call;
     
    157158                }
    158159        }
    159         spinlock_unlock(&TASK->answerbox.lock);
     160       
     161        irq_spinlock_unlock(&TASK->answerbox.lock, true);
    160162        return result;
    161163}
     
    163165/** Allocate new phone slot in the specified task.
    164166 *
    165  * @param t             Task for which to allocate a new phone.
    166  *
    167  * @return              New phone handle or -1 if the phone handle limit is
    168  *                      exceeded.
    169  */
    170 int phone_alloc(task_t *t)
    171 {
    172         int i;
    173 
    174         spinlock_lock(&t->lock);
     167 * @param task Task for which to allocate a new phone.
     168 *
     169 * @return New phone handle or -1 if the phone handle limit is
     170 *         exceeded.
     171 *
     172 */
     173int phone_alloc(task_t *task)
     174{
     175        irq_spinlock_lock(&task->lock, true);
     176       
     177        size_t i;
    175178        for (i = 0; i < IPC_MAX_PHONES; i++) {
    176                 if (t->phones[i].state == IPC_PHONE_HUNGUP &&
    177                     atomic_get(&t->phones[i].active_calls) == 0)
    178                         t->phones[i].state = IPC_PHONE_FREE;
    179 
    180                 if (t->phones[i].state == IPC_PHONE_FREE) {
    181                         t->phones[i].state = IPC_PHONE_CONNECTING;
     179                if ((task->phones[i].state == IPC_PHONE_HUNGUP) &&
     180                    (atomic_get(&task->phones[i].active_calls) == 0))
     181                        task->phones[i].state = IPC_PHONE_FREE;
     182               
     183                if (task->phones[i].state == IPC_PHONE_FREE) {
     184                        task->phones[i].state = IPC_PHONE_CONNECTING;
    182185                        break;
    183186                }
    184187        }
    185         spinlock_unlock(&t->lock);
    186 
     188       
     189        irq_spinlock_unlock(&task->lock, true);
     190       
    187191        if (i == IPC_MAX_PHONES)
    188192                return -1;
    189 
     193       
    190194        return i;
    191195}
     
    193197/** Mark a phone structure free.
    194198 *
    195  * @param phone         Phone structure to be marked free.
     199 * @param phone Phone structure to be marked free.
     200 *
    196201 */
    197202static void phone_deallocp(phone_t *phone)
     
    199204        ASSERT(phone->state == IPC_PHONE_CONNECTING);
    200205       
    201         /* atomic operation */
     206        /* Atomic operation */
    202207        phone->state = IPC_PHONE_FREE;
    203208}
     
    207212 * All already sent messages will be correctly processed.
    208213 *
    209  * @param phoneid       Phone handle of the phone to be freed.
     214 * @param phoneid Phone handle of the phone to be freed.
     215 *
    210216 */
    211217void phone_dealloc(int phoneid)
     
    216222/** Connect phone to a given answerbox.
    217223 *
    218  * @param phoneid       Phone handle to be connected.
    219  * @param box           Answerbox to which to connect the phone handle.
     224 * @param phoneid Phone handle to be connected.
     225 * @param box     Answerbox to which to connect the phone handle.
    220226 *
    221227 * The procedure _enforces_ that the user first marks the phone
    222228 * busy (e.g. via phone_alloc) and then connects the phone, otherwise
    223229 * race condition may appear.
     230 *
    224231 */
    225232void phone_connect(int phoneid, answerbox_t *box)
  • kernel/generic/src/ipc/irq.c

    rfb150d78 r46c20c8  
    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)
     
    438431        ASSERT(irq);
    439432
     433        ASSERT(interrupts_disabled());
     434        ASSERT(irq_spinlock_locked(&irq->lock));
     435       
    440436        if (irq->notif_cfg.answerbox) {
    441                 call_t *call;
    442 
    443                 call = ipc_call_alloc(FRAME_ATOMIC);
     437                call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    444438                if (!call)
    445439                        return;
     
    448442                /* Put a counter to the message */
    449443                call->priv = ++irq->notif_cfg.counter;
    450 
     444               
    451445                /* Set up args */
    452446                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
     
    456450                IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]);
    457451                IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]);
    458 
     452               
    459453                send_call(irq, call);
    460454        }
     
    463457/** Send notification message.
    464458 *
    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.
     459 * @param irq IRQ structure.
     460 * @param a1  Driver-specific payload argument.
     461 * @param a2  Driver-specific payload argument.
     462 * @param a3  Driver-specific payload argument.
     463 * @param a4  Driver-specific payload argument.
     464 * @param a5  Driver-specific payload argument.
     465 *
    471466 */
    472467void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
    473468    unative_t a4, unative_t a5)
    474469{
    475         call_t *call;
    476 
    477         spinlock_lock(&irq->lock);
    478 
     470        irq_spinlock_lock(&irq->lock, true);
     471       
    479472        if (irq->notif_cfg.answerbox) {
    480                 call = ipc_call_alloc(FRAME_ATOMIC);
     473                call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    481474                if (!call) {
    482                         spinlock_unlock(&irq->lock);
     475                        irq_spinlock_unlock(&irq->lock, true);
    483476                        return;
    484477                }
     478               
    485479                call->flags |= IPC_CALL_NOTIF;
    486480                /* Put a counter to the message */
    487481                call->priv = ++irq->notif_cfg.counter;
    488 
     482               
    489483                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
    490484                IPC_SET_ARG1(call->data, a1);
     
    496490                send_call(irq, call);
    497491        }
    498         spinlock_unlock(&irq->lock);
     492       
     493        irq_spinlock_unlock(&irq->lock, true);
    499494}
    500495
  • kernel/generic/src/ipc/kbox.c

    rfb150d78 r46c20c8  
    4747void ipc_kbox_cleanup(void)
    4848{
    49         ipl_t ipl;
    50         bool have_kb_thread;
    51 
    52         /*
     49        /*
    5350         * Only hold kb.cleanup_lock while setting kb.finished -
    5451         * this is enough.
     
    5754        TASK->kb.finished = true;
    5855        mutex_unlock(&TASK->kb.cleanup_lock);
    59 
    60         have_kb_thread = (TASK->kb.thread != NULL);
    61 
     56       
     57        bool have_kb_thread = (TASK->kb.thread != NULL);
     58       
    6259        /*
    6360         * From now on nobody will try to connect phones or attach
    6461         * kbox threads
    6562         */
    66 
     63       
    6764        /*
    6865         * Disconnect all phones connected to our kbox. Passing true for
     
    7269         */
    7370        ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread);
    74 
    75         /* 
     71       
     72        /*
    7673         * If the task was being debugged, clean up debugging session.
    7774         * This is necessarry as slamming the phones won't force
    7875         * kbox thread to clean it up since sender != debugger.
    7976         */
    80         ipl = interrupts_disable();
    81         spinlock_lock(&TASK->lock);
     77        mutex_lock(&TASK->udebug.lock);
    8278        udebug_task_cleanup(TASK);
    83         spinlock_unlock(&TASK->lock);
    84         interrupts_restore(ipl);
     79        mutex_unlock(&TASK->udebug.lock);
    8580       
    8681        if (have_kb_thread) {
     
    9186                TASK->kb.thread = NULL;
    9287        }
    93 
     88       
    9489        /* Answer all messages in 'calls' and 'dispatched_calls' queues. */
    95         spinlock_lock(&TASK->kb.box.lock);
     90        irq_spinlock_lock(&TASK->kb.box.lock, true);
    9691        ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls);
    9792        ipc_cleanup_call_list(&TASK->kb.box.calls);
    98         spinlock_unlock(&TASK->kb.box.lock);
     93        irq_spinlock_unlock(&TASK->kb.box.lock, true);
    9994}
    10095
    10196/** Handle hangup message in kbox.
    10297 *
    103  * @param call  The IPC_M_PHONE_HUNGUP call structure.
    104  * @param last  Output, the function stores @c true here if
    105  *              this was the last phone, @c false otherwise.
    106  **/
     98 * @param call The IPC_M_PHONE_HUNGUP call structure.
     99 * @param last Output, the function stores @c true here if
     100 *             this was the last phone, @c false otherwise.
     101 *
     102 */
    107103static void kbox_proc_phone_hungup(call_t *call, bool *last)
    108104{
    109         ipl_t ipl;
    110 
    111105        /* Was it our debugger, who hung up? */
    112106        if (call->sender == TASK->udebug.debugger) {
    113107                /* Terminate debugging session (if any). */
    114108                LOG("Terminate debugging session.");
    115                 ipl = interrupts_disable();
    116                 spinlock_lock(&TASK->lock);
     109                mutex_lock(&TASK->udebug.lock);
    117110                udebug_task_cleanup(TASK);
    118                 spinlock_unlock(&TASK->lock);
    119                 interrupts_restore(ipl);
     111                mutex_unlock(&TASK->udebug.lock);
    120112        } else {
    121113                LOG("Was not debugger.");
    122114        }
    123 
     115       
    124116        LOG("Continue with hangup message.");
    125117        IPC_SET_RETVAL(call->data, 0);
    126118        ipc_answer(&TASK->kb.box, call);
    127 
    128         ipl = interrupts_disable();
    129         spinlock_lock(&TASK->lock);
    130         spinlock_lock(&TASK->kb.box.lock);
     119       
     120        mutex_lock(&TASK->kb.cleanup_lock);
     121       
     122        irq_spinlock_lock(&TASK->lock, true);
     123        irq_spinlock_lock(&TASK->kb.box.lock, false);
    131124        if (list_empty(&TASK->kb.box.connected_phones)) {
    132125                /*
     
    134127                 * gets freed and signal to the caller.
    135128                 */
    136 
     129               
    137130                /* Only detach kbox thread unless already terminating. */
    138                 mutex_lock(&TASK->kb.cleanup_lock);
    139131                if (TASK->kb.finished == false) {
    140132                        /* Detach kbox thread so it gets freed from memory. */
     
    142134                        TASK->kb.thread = NULL;
    143135                }
    144                 mutex_unlock(&TASK->kb.cleanup_lock);
    145 
     136               
    146137                LOG("Phone list is empty.");
    147138                *last = true;
    148         } else {
     139        } else
    149140                *last = false;
    150         }
    151 
    152         spinlock_unlock(&TASK->kb.box.lock);
    153         spinlock_unlock(&TASK->lock);
    154         interrupts_restore(ipl);
     141       
     142        irq_spinlock_unlock(&TASK->kb.box.lock, false);
     143        irq_spinlock_unlock(&TASK->lock, true);
     144       
     145        mutex_unlock(&TASK->kb.cleanup_lock);
    155146}
    156147
     
    160151 * when all phones are disconnected from the kbox.
    161152 *
    162  * @param arg   Ignored.
     153 * @param arg Ignored.
     154 *
    163155 */
    164156static void kbox_thread_proc(void *arg)
    165157{
    166         call_t *call;
    167         bool done;
    168 
    169         (void)arg;
     158        (void) arg;
    170159        LOG("Starting.");
    171         done = false;
    172 
     160        bool done = false;
     161       
    173162        while (!done) {
    174                 call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
     163                call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
    175164                        SYNCH_FLAGS_NONE);
    176 
     165               
    177166                if (call == NULL)
    178                         continue;       /* Try again. */
    179 
     167                        continue;  /* Try again. */
     168               
    180169                switch (IPC_GET_METHOD(call->data)) {
    181 
     170               
    182171                case IPC_M_DEBUG_ALL:
    183172                        /* Handle debug call. */
    184173                        udebug_call_receive(call);
    185174                        break;
    186 
     175               
    187176                case IPC_M_PHONE_HUNGUP:
    188177                        /*
     
    193182                        kbox_proc_phone_hungup(call, &done);
    194183                        break;
    195 
     184               
    196185                default:
    197186                        /* Ignore */
     
    199188                }
    200189        }
    201 
     190       
    202191        LOG("Exiting.");
    203192}
    204193
    205194
    206 /**
    207  * Connect phone to a task kernel-box specified by id.
     195/** Connect phone to a task kernel-box specified by id.
    208196 *
    209197 * Note that this is not completely atomic. For optimisation reasons, the task
     
    212200 * cleanup code.
    213201 *
    214  * @return              Phone id on success, or negative error code.
     202 * @return Phone id on success, or negative error code.
     203 *
    215204 */
    216205int ipc_connect_kbox(task_id_t taskid)
    217206{
    218         int newphid;
    219         task_t *ta;
    220         thread_t *kb_thread;
    221         ipl_t ipl;
    222 
    223         ipl = interrupts_disable();
    224         spinlock_lock(&tasks_lock);
    225 
    226         ta = task_find_by_id(taskid);
    227         if (ta == NULL) {
    228                 spinlock_unlock(&tasks_lock);
    229                 interrupts_restore(ipl);
     207        irq_spinlock_lock(&tasks_lock, true);
     208       
     209        task_t *task = task_find_by_id(taskid);
     210        if (task == NULL) {
     211                irq_spinlock_unlock(&tasks_lock, true);
    230212                return ENOENT;
    231213        }
    232 
    233         atomic_inc(&ta->refcount);
    234 
    235         spinlock_unlock(&tasks_lock);
    236         interrupts_restore(ipl);
    237 
    238         mutex_lock(&ta->kb.cleanup_lock);
    239 
    240         if (atomic_predec(&ta->refcount) == 0) {
    241                 mutex_unlock(&ta->kb.cleanup_lock);
    242                 task_destroy(ta);
     214       
     215        atomic_inc(&task->refcount);
     216       
     217        irq_spinlock_unlock(&tasks_lock, true);
     218       
     219        mutex_lock(&task->kb.cleanup_lock);
     220       
     221        if (atomic_predec(&task->refcount) == 0) {
     222                mutex_unlock(&task->kb.cleanup_lock);
     223                task_destroy(task);
    243224                return ENOENT;
    244225        }
    245 
    246         if (ta->kb.finished != false) {
    247                 mutex_unlock(&ta->kb.cleanup_lock);
     226       
     227        if (task->kb.finished != false) {
     228                mutex_unlock(&task->kb.cleanup_lock);
    248229                return EINVAL;
    249230        }
    250 
    251         newphid = phone_alloc(TASK);
     231       
     232        int newphid = phone_alloc(TASK);
    252233        if (newphid < 0) {
    253                 mutex_unlock(&ta->kb.cleanup_lock);
     234                mutex_unlock(&task->kb.cleanup_lock);
    254235                return ELIMIT;
    255236        }
    256 
     237       
    257238        /* Connect the newly allocated phone to the kbox */
    258         ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box);
    259 
    260         if (ta->kb.thread != NULL) {
    261                 mutex_unlock(&ta->kb.cleanup_lock);
     239        ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
     240       
     241        if (task->kb.thread != NULL) {
     242                mutex_unlock(&task->kb.cleanup_lock);
    262243                return newphid;
    263244        }
    264 
     245       
    265246        /* Create a kbox thread */
    266         kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0,
     247        thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0,
    267248            "kbox", false);
    268249        if (!kb_thread) {
    269                 mutex_unlock(&ta->kb.cleanup_lock);
     250                mutex_unlock(&task->kb.cleanup_lock);
    270251                return ENOMEM;
    271252        }
    272 
    273         ta->kb.thread = kb_thread;
     253       
     254        task->kb.thread = kb_thread;
    274255        thread_ready(kb_thread);
    275 
    276         mutex_unlock(&ta->kb.cleanup_lock);
    277 
     256       
     257        mutex_unlock(&task->kb.cleanup_lock);
     258       
    278259        return newphid;
    279260}
  • kernel/generic/src/ipc/sysipc.c

    rfb150d78 r46c20c8  
    5656 * requests.
    5757 */
    58 #define DATA_XFER_LIMIT         (64 * 1024)
    59 
    60 #define GET_CHECK_PHONE(phone, phoneid, err) \
    61 { \
    62         if (phoneid > IPC_MAX_PHONES) { \
    63                 err \
    64         } \
    65         phone = &TASK->phones[phoneid]; \
    66 }
    67 
    68 #define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
     58#define DATA_XFER_LIMIT  (64 * 1024)
     59
     60#define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
     61
     62/** Get phone from the current task by ID.
     63 *
     64 * @param phoneid Phone ID.
     65 * @param phone   Place to store pointer to phone.
     66 *
     67 * @return EOK on success, EINVAL if ID is invalid.
     68 *
     69 */
     70static int phone_get(unative_t phoneid, phone_t **phone)
     71{
     72        if (phoneid >= IPC_MAX_PHONES)
     73                return EINVAL;
     74       
     75        *phone = &TASK->phones[phoneid];
     76        return EOK;
     77}
    6978
    7079/** Decide if the method is a system method.
    7180 *
    72  * @param method        Method to be decided.
    73  *
    74  * @return              Return 1 if the method is a system method.
    75  *                      Otherwise return 0.
    76  */
    77 static inline int method_is_system(unative_t method)
     81 * @param method Method to be decided.
     82 *
     83 * @return true if the method is a system method.
     84 *
     85 */
     86static inline bool method_is_system(unative_t method)
    7887{
    7988        if (method <= IPC_M_LAST_SYSTEM)
    80                 return 1;
    81         return 0;
     89                return true;
     90       
     91        return false;
    8292}
    8393
     
    8797 *   it is useless
    8898 *
    89  * @param method        Method to be decided.
    90  *
    91  * @return              Return 1 if the method is forwardable.
    92  *                      Otherwise return 0.
    93  */
    94 static inline int method_is_forwardable(unative_t method)
     99 * @param method Method to be decided.
     100 *
     101 * @return true if the method is forwardable.
     102 *
     103 */
     104static inline bool method_is_forwardable(unative_t method)
    95105{
    96106        switch (method) {
     
    99109        case IPC_M_PHONE_HUNGUP:
    100110                /* This message is meant only for the original recipient. */
    101                 return 0;
     111                return false;
    102112        default:
    103                 return 1;
     113                return true;
    104114        }
    105115}
     
    109119 * - some system messages may be forwarded but their content cannot be altered
    110120 *
    111  * @param method        Method to be decided.
    112  *
    113  * @return              Return 1 if the method is immutable on forward.
    114  *                      Otherwise return 0.
    115  */
    116 static inline int method_is_immutable(unative_t method)
     121 * @param method Method to be decided.
     122 *
     123 * @return true if the method is immutable on forward.
     124 *
     125 */
     126static inline bool method_is_immutable(unative_t method)
    117127{
    118128        switch (method) {
     
    121131        case IPC_M_DATA_WRITE:
    122132        case IPC_M_DATA_READ:
    123                 return 1;
     133                return true;
    124134        default:
    125                 return 0;
     135                return false;
    126136        }
    127137}
     
    135145 * for answer_preprocess().
    136146 *
    137  * @param call          Call structure to be decided.
    138  *
    139  * @return              Return 1 if the old call contents should be saved.
    140  *                      Return 0 otherwise.
    141  */
    142 static inline int answer_need_old(call_t *call)
     147 * @param call Call structure to be decided.
     148 *
     149 * @return true if the old call contents should be saved.
     150 *
     151 */
     152static inline bool answer_need_old(call_t *call)
    143153{
    144154        switch (IPC_GET_METHOD(call->data)) {
     
    151161        case IPC_M_DATA_WRITE:
    152162        case IPC_M_DATA_READ:
    153                 return 1;
     163                return true;
    154164        default:
    155                 return 0;
     165                return false;
    156166        }
    157167}
     
    161171 * This function is called directly after sys_ipc_answer().
    162172 *
    163  * @param answer        Call structure with the answer.
    164  * @param olddata       Saved data of the request.
    165  *
    166  * @return              Return 0 on success or an error code.
     173 * @param answer  Call structure with the answer.
     174 * @param olddata Saved data of the request.
     175 *
     176 * @return Return 0 on success or an error code.
     177 *
    167178 */
    168179static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    169180{
    170         int phoneid;
    171 
    172181        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    173182                /* In case of forward, hangup the forwared phone,
     
    175184                 */
    176185                mutex_lock(&answer->data.phone->lock);
    177                 spinlock_lock(&TASK->answerbox.lock);
     186                irq_spinlock_lock(&TASK->answerbox.lock, true);
    178187                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    179188                        list_remove(&answer->data.phone->link);
    180189                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    181190                }
    182                 spinlock_unlock(&TASK->answerbox.lock);
     191                irq_spinlock_unlock(&TASK->answerbox.lock, true);
    183192                mutex_unlock(&answer->data.phone->lock);
    184193        }
    185 
     194       
    186195        if (!olddata)
    187196                return 0;
    188 
     197       
    189198        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
    190                 phoneid = IPC_GET_ARG1(*olddata);
    191                 phone_t *phone = &TASK->phones[phoneid];
     199                int phoneid = IPC_GET_ARG1(*olddata);
     200                phone_t *phone = &TASK->phones[phoneid];
     201               
    192202                if (IPC_GET_RETVAL(answer->data) != EOK) {
    193203                        /*
     
    201211                        mutex_lock(&phone->lock);
    202212                        if (phone->state == IPC_PHONE_CONNECTED) {
    203                                 spinlock_lock(&phone->callee->lock);
     213                                irq_spinlock_lock(&phone->callee->lock, true);
    204214                                list_remove(&phone->link);
    205215                                phone->state = IPC_PHONE_SLAMMED;
    206                                 spinlock_unlock(&phone->callee->lock);
     216                                irq_spinlock_unlock(&phone->callee->lock, true);
    207217                        }
    208218                        mutex_unlock(&phone->lock);
    209219                }
    210220        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
    211                 phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
     221                phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
     222               
    212223                if (IPC_GET_RETVAL(answer->data) != EOK) {
    213224                        /*
     
    219230                        mutex_lock(&phone->lock);
    220231                        if (phone->state == IPC_PHONE_CONNECTED) {
    221                                 spinlock_lock(&phone->callee->lock);
     232                                irq_spinlock_lock(&phone->callee->lock, true);
    222233                                list_remove(&phone->link);
    223234                                phone->state = IPC_PHONE_SLAMMED;
    224                                 spinlock_unlock(&phone->callee->lock);
     235                                irq_spinlock_unlock(&phone->callee->lock, true);
    225236                        }
    226237                        mutex_unlock(&phone->lock);
    227238                }
    228239        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    229                 phoneid = IPC_GET_ARG5(*olddata);
     240                int phoneid = IPC_GET_ARG5(*olddata);
     241               
    230242                if (IPC_GET_RETVAL(answer->data) != EOK) {
    231243                        /* The connection was not accepted */
     
    247259                if (!IPC_GET_RETVAL(answer->data)) {
    248260                        /* Accepted, handle as_area receipt */
    249                         ipl_t ipl;
    250                         int rc;
    251                         as_t *as;
    252261                       
    253                         ipl = interrupts_disable();
    254                         spinlock_lock(&answer->sender->lock);
    255                         as = answer->sender->as;
    256                         spinlock_unlock(&answer->sender->lock);
    257                         interrupts_restore(ipl);
     262                        irq_spinlock_lock(&answer->sender->lock, true);
     263                        as_t *as = answer->sender->as;
     264                        irq_spinlock_unlock(&answer->sender->lock, true);
    258265                       
    259                         rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     266                        int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
    260267                            IPC_GET_ARG2(*olddata), AS,
    261268                            IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
     
    265272        } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) {
    266273                if (!IPC_GET_RETVAL(answer->data)) {
    267                         ipl_t ipl;
    268                         as_t *as;
    269                         int rc;
     274                        irq_spinlock_lock(&answer->sender->lock, true);
     275                        as_t *as = answer->sender->as;
     276                        irq_spinlock_unlock(&answer->sender->lock, true);
    270277                       
    271                         ipl = interrupts_disable();
    272                         spinlock_lock(&answer->sender->lock);
    273                         as = answer->sender->as;
    274                         spinlock_unlock(&answer->sender->lock);
    275                         interrupts_restore(ipl);
    276                        
    277                         rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     278                        int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
    278279                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    279280                            IPC_GET_ARG2(answer->data));
     
    294295                                 */
    295296                                IPC_SET_ARG1(answer->data, dst);
    296 
     297                               
    297298                                answer->buffer = malloc(size, 0);
    298299                                int rc = copy_from_uspace(answer->buffer,
     
    313314                if (!IPC_GET_RETVAL(answer->data)) {
    314315                        /* The recipient agreed to receive data. */
    315                         int rc;
    316                         uintptr_t dst;
    317                         size_t size;
    318                         size_t max_size;
    319 
    320                         dst = (uintptr_t)IPC_GET_ARG1(answer->data);
    321                         size = (size_t)IPC_GET_ARG2(answer->data);
    322                         max_size = (size_t)IPC_GET_ARG2(*olddata);
    323 
     316                        uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);
     317                        size_t size = (size_t)IPC_GET_ARG2(answer->data);
     318                        size_t max_size = (size_t)IPC_GET_ARG2(*olddata);
     319                       
    324320                        if (size <= max_size) {
    325                                 rc = copy_to_uspace((void *) dst,
     321                                int rc = copy_to_uspace((void *) dst,
    326322                                    answer->buffer, size);
    327323                                if (rc)
     
    334330                answer->buffer = NULL;
    335331        }
     332       
    336333        return 0;
    337334}
     
    345342                mutex_lock(&p2->lock);
    346343                mutex_lock(&p1->lock);
    347         } else {
     344        } else
    348345                mutex_lock(&p1->lock);
    349         }
    350346}
    351347
     
    359355/** Called before the request is sent.
    360356 *
    361  * @param call          Call structure with the request.
    362  * @param phone         Phone that the call will be sent through.
    363  *
    364  * @return              Return 0 on success, ELIMIT or EPERM on error.
     357 * @param call  Call structure with the request.
     358 * @param phone Phone that the call will be sent through.
     359 *
     360 * @return Return 0 on success, ELIMIT or EPERM on error.
     361 *
    365362 */
    366363static int request_preprocess(call_t *call, phone_t *phone)
    367364{
    368         int newphid;
    369         size_t size;
    370         uintptr_t src;
    371         int rc;
    372 
    373365        switch (IPC_GET_METHOD(call->data)) {
    374366        case IPC_M_CONNECTION_CLONE: {
    375367                phone_t *cloned_phone;
    376                 GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
    377                     return ENOENT;);
     368                if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
     369                        return ENOENT;
     370               
    378371                phones_lock(cloned_phone, phone);
     372               
    379373                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    380374                    phone->state != IPC_PHONE_CONNECTED) {
     
    382376                        return EINVAL;
    383377                }
     378               
    384379                /*
    385380                 * We can be pretty sure now that both tasks exist and we are
     
    387382                 * we are effectively preventing them from finishing their
    388383                 * potential cleanup.
     384                 *
    389385                 */
    390                 newphid = phone_alloc(phone->callee->task);
     386                int newphid = phone_alloc(phone->callee->task);
    391387                if (newphid < 0) {
    392388                        phones_unlock(cloned_phone, phone);
    393389                        return ELIMIT;
    394390                }
     391               
    395392                ipc_phone_connect(&phone->callee->task->phones[newphid],
    396393                    cloned_phone->callee);
    397394                phones_unlock(cloned_phone, phone);
     395               
    398396                /* Set the new phone for the callee. */
    399397                IPC_SET_ARG1(call->data, newphid);
     
    403401                IPC_SET_ARG5(call->data, (unative_t) phone);
    404402                break;
    405         case IPC_M_CONNECT_ME_TO:
    406                 newphid = phone_alloc(TASK);
     403        case IPC_M_CONNECT_ME_TO: {
     404                int newphid = phone_alloc(TASK);
    407405                if (newphid < 0)
    408406                        return ELIMIT;
     407               
    409408                /* Set arg5 for server */
    410409                IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
     
    412411                call->priv = newphid;
    413412                break;
    414         case IPC_M_SHARE_OUT:
    415                 size = as_area_get_size(IPC_GET_ARG1(call->data));
     413        }
     414        case IPC_M_SHARE_OUT: {
     415                size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
    416416                if (!size)
    417417                        return EPERM;
     418               
    418419                IPC_SET_ARG2(call->data, size);
    419420                break;
    420         case IPC_M_DATA_READ:
    421                 size = IPC_GET_ARG2(call->data);
     421        }
     422        case IPC_M_DATA_READ: {
     423                size_t size = IPC_GET_ARG2(call->data);
    422424                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    423425                        return ELIMIT;
     426               
    424427                break;
    425         case IPC_M_DATA_WRITE:
    426                 src = IPC_GET_ARG1(call->data);
    427                 size = IPC_GET_ARG2(call->data);
     428        }
     429        case IPC_M_DATA_WRITE: {
     430                uintptr_t src = IPC_GET_ARG1(call->data);
     431                size_t size = IPC_GET_ARG2(call->data);
    428432               
    429433                if (size > DATA_XFER_LIMIT)
     
    431435               
    432436                call->buffer = (uint8_t *) malloc(size, 0);
    433                 rc = copy_from_uspace(call->buffer, (void *) src, size);
     437                int rc = copy_from_uspace(call->buffer, (void *) src, size);
    434438                if (rc != 0) {
    435439                        free(call->buffer);
    436440                        return rc;
    437441                }
     442               
    438443                break;
     444        }
    439445#ifdef CONFIG_UDEBUG
    440446        case IPC_M_DEBUG_ALL:
     
    444450                break;
    445451        }
     452       
    446453        return 0;
    447454}
     
    453460/** Do basic kernel processing of received call answer.
    454461 *
    455  * @param call          Call structure with the answer.
     462 * @param call Call structure with the answer.
     463 *
    456464 */
    457465static void process_answer(call_t *call)
     
    460468            (call->flags & IPC_CALL_FORWARDED))
    461469                IPC_SET_RETVAL(call->data, EFORWARD);
    462 
     470       
    463471        if (call->flags & IPC_CALL_CONN_ME_TO) {
    464472                if (IPC_GET_RETVAL(call->data))
     
    467475                        IPC_SET_ARG5(call->data, call->priv);
    468476        }
    469 
     477       
    470478        if (call->buffer) {
    471                 /* This must be an affirmative answer to IPC_M_DATA_READ. */
    472                 /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
     479                /*
     480                 * This must be an affirmative answer to IPC_M_DATA_READ
     481                 * or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ...
     482                 *
     483                 */
    473484                uintptr_t dst = IPC_GET_ARG1(call->data);
    474485                size_t size = IPC_GET_ARG2(call->data);
     
    483494/** Do basic kernel processing of received call request.
    484495 *
    485  * @param box           Destination answerbox structure.
    486  * @param call          Call structure with the request.
    487  *
    488  * @return              Return 0 if the call should be passed to userspace.
    489  *                      Return -1 if the call should be ignored.
     496 * @param box  Destination answerbox structure.
     497 * @param call Call structure with the request.
     498 *
     499 * @return 0 if the call should be passed to userspace.
     500 * @return -1 if the call should be ignored.
     501 *
    490502 */
    491503static int process_request(answerbox_t *box, call_t *call)
    492504{
    493         int phoneid;
    494 
    495505        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    496                 phoneid = phone_alloc(TASK);
     506                int phoneid = phone_alloc(TASK);
    497507                if (phoneid < 0) { /* Failed to allocate phone */
    498508                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    500510                        return -1;
    501511                }
     512               
    502513                IPC_SET_ARG5(call->data, phoneid);
    503514        }
     515       
    504516        switch (IPC_GET_METHOD(call->data)) {
    505517        case IPC_M_DEBUG_ALL:
     
    508520                break;
    509521        }
     522       
    510523        return 0;
    511524}
     
    516529 * the generic function (i.e. sys_ipc_call_sync_slow()).
    517530 *
    518  * @param phoneid       Phone handle for the call.
    519  * @param method        Method of the call.
    520  * @param arg1          Service-defined payload argument.
    521  * @param arg2          Service-defined payload argument.
    522  * @param arg3          Service-defined payload argument.
    523  * @param data          Address of userspace structure where the reply call will
    524  *                      be stored.
    525  *
    526  * @return              Returns 0 on success.
    527  *                      Return ENOENT if there is no such phone handle.
     531 * @param phoneid Phone handle for the call.
     532 * @param method  Method of the call.
     533 * @param arg1    Service-defined payload argument.
     534 * @param arg2    Service-defined payload argument.
     535 * @param arg3    Service-defined payload argument.
     536 * @param data    Address of userspace structure where the reply call will
     537 *                be stored.
     538 *
     539 * @return 0 on success.
     540 * @return ENOENT if there is no such phone handle.
     541 *
    528542 */
    529543unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
    530544    unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    531545{
    532         call_t *call;
    533546        phone_t *phone;
    534         int res;
    535         int rc;
    536        
    537         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
    538 
    539         call = ipc_call_alloc(0);
     547        if (phone_get(phoneid, &phone) != EOK)
     548                return ENOENT;
     549
     550        call_t *call = ipc_call_alloc(0);
    540551        IPC_SET_METHOD(call->data, method);
    541552        IPC_SET_ARG1(call->data, arg1);
    542553        IPC_SET_ARG2(call->data, arg2);
    543554        IPC_SET_ARG3(call->data, arg3);
     555       
    544556        /*
    545557         * To achieve deterministic behavior, zero out arguments that are beyond
     
    548560        IPC_SET_ARG4(call->data, 0);
    549561        IPC_SET_ARG5(call->data, 0);
    550 
    551         if (!(res = request_preprocess(call, phone))) {
     562       
     563        int res = request_preprocess(call, phone);
     564        int rc;
     565       
     566        if (!res) {
    552567#ifdef CONFIG_UDEBUG
    553568                udebug_stoppable_begin();
     
    557572                udebug_stoppable_end();
    558573#endif
     574               
    559575                if (rc != EOK) {
    560576                        /* The call will be freed by ipc_cleanup(). */
    561577                        return rc;
    562578                }
     579               
    563580                process_answer(call);
    564 
    565         } else {
     581               
     582        } else
    566583                IPC_SET_RETVAL(call->data, res);
    567         }
     584       
    568585        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
    569586        ipc_call_free(call);
    570587        if (rc != 0)
    571588                return rc;
    572 
     589       
    573590        return 0;
    574591}
     
    576593/** Make a synchronous IPC call allowing to transmit the entire payload.
    577594 *
    578  * @param phoneid       Phone handle for the call.
    579  * @param question      Userspace address of call data with the request.
    580  * @param reply         Userspace address of call data where to store the
    581  *                      answer.
    582  *
    583  * @return              Zero on success or an error code.
     595 * @param phoneid  Phone handle for the call.
     596 * @param question Userspace address of call data with the request.
     597 * @param reply    Userspace address of call data where to store the
     598 *                 answer.
     599 *
     600 * @return Zero on success or an error code.
     601 *
    584602 */
    585603unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
    586604    ipc_data_t *reply)
    587605{
    588         call_t *call;
    589606        phone_t *phone;
    590         int res;
    591         int rc;
    592 
    593         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
    594 
    595         call = ipc_call_alloc(0);
    596         rc = copy_from_uspace(&call->data.args, &question->args,
     607        if (phone_get(phoneid, &phone) != EOK)
     608                return ENOENT;
     609
     610        call_t *call = ipc_call_alloc(0);
     611        int rc = copy_from_uspace(&call->data.args, &question->args,
    597612            sizeof(call->data.args));
    598613        if (rc != 0) {
     
    600615                return (unative_t) rc;
    601616        }
    602 
    603 
    604         if (!(res = request_preprocess(call, phone))) {
     617       
     618        int res = request_preprocess(call, phone);
     619       
     620        if (!res) {
    605621#ifdef CONFIG_UDEBUG
    606622                udebug_stoppable_begin();
     
    610626                udebug_stoppable_end();
    611627#endif
     628               
    612629                if (rc != EOK) {
    613630                        /* The call will be freed by ipc_cleanup(). */
    614631                        return rc;
    615632                }
     633               
    616634                process_answer(call);
    617         } else 
     635        } else
    618636                IPC_SET_RETVAL(call->data, res);
    619 
     637       
    620638        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
    621639        ipc_call_free(call);
    622640        if (rc != 0)
    623641                return rc;
    624 
     642       
    625643        return 0;
    626644}
     
    628646/** Check that the task did not exceed the allowed limit of asynchronous calls.
    629647 *
    630  * @return              Return 0 if limit not reached or -1 if limit exceeded.
     648 * @return 0 if limit not reached or -1 if limit exceeded.
     649 *
    631650 */
    632651static int check_call_limit(void)
     
    636655                return -1;
    637656        }
     657       
    638658        return 0;
    639659}
     
    644664 * the generic function sys_ipc_call_async_slow().
    645665 *
    646  * @param phoneid       Phone handle for the call.
    647  * @param method        Method of the call.
    648  * @param arg1          Service-defined payload argument.
    649  * @param arg2          Service-defined payload argument.
    650  * @param arg3          Service-defined payload argument.
    651  * @param arg4          Service-defined payload argument.
    652  *
    653  * @return              Return call hash on success.
    654  *                      Return IPC_CALLRET_FATAL in case of a fatal error and
    655  *                      IPC_CALLRET_TEMPORARY if there are too many pending
    656  *                      asynchronous requests; answers should be handled first.
     666 * @param phoneid Phone handle for the call.
     667 * @param method  Method of the call.
     668 * @param arg1    Service-defined payload argument.
     669 * @param arg2    Service-defined payload argument.
     670 * @param arg3    Service-defined payload argument.
     671 * @param arg4    Service-defined payload argument.
     672 *
     673 * @return Call hash on success.
     674 * @return IPC_CALLRET_FATAL in case of a fatal error.
     675 * @return IPC_CALLRET_TEMPORARY if there are too many pending
     676 *         asynchronous requests; answers should be handled first.
     677 *
    657678 */
    658679unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
    659680    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    660681{
    661         call_t *call;
    662         phone_t *phone;
    663         int res;
    664 
    665682        if (check_call_limit())
    666683                return IPC_CALLRET_TEMPORARY;
    667 
    668         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
    669 
    670         call = ipc_call_alloc(0);
     684       
     685        phone_t *phone;
     686        if (phone_get(phoneid, &phone) != EOK)
     687                return IPC_CALLRET_FATAL;
     688       
     689        call_t *call = ipc_call_alloc(0);
    671690        IPC_SET_METHOD(call->data, method);
    672691        IPC_SET_ARG1(call->data, arg1);
     
    674693        IPC_SET_ARG3(call->data, arg3);
    675694        IPC_SET_ARG4(call->data, arg4);
     695       
    676696        /*
    677697         * To achieve deterministic behavior, zero out arguments that are beyond
     
    679699         */
    680700        IPC_SET_ARG5(call->data, 0);
    681 
    682         if (!(res = request_preprocess(call, phone)))
     701       
     702        int res = request_preprocess(call, phone);
     703       
     704        if (!res)
    683705                ipc_call(phone, call);
    684706        else
    685707                ipc_backsend_err(phone, call, res);
    686 
     708       
    687709        return (unative_t) call;
    688710}
     
    690712/** Make an asynchronous IPC call allowing to transmit the entire payload.
    691713 *
    692  * @param phoneid       Phone handle for the call.
    693  * @param data          Userspace address of call data with the request.
    694  *
    695  * @return              See sys_ipc_call_async_fast().
     714 * @param phoneid Phone handle for the call.
     715 * @param data    Userspace address of call data with the request.
     716 *
     717 * @return See sys_ipc_call_async_fast().
     718 *
    696719 */
    697720unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
    698721{
    699         call_t *call;
    700         phone_t *phone;
    701         int res;
    702         int rc;
    703 
    704722        if (check_call_limit())
    705723                return IPC_CALLRET_TEMPORARY;
    706 
    707         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
    708 
    709         call = ipc_call_alloc(0);
    710         rc = copy_from_uspace(&call->data.args, &data->args,
     724       
     725        phone_t *phone;
     726        if (phone_get(phoneid, &phone) != EOK)
     727                return IPC_CALLRET_FATAL;
     728
     729        call_t *call = ipc_call_alloc(0);
     730        int rc = copy_from_uspace(&call->data.args, &data->args,
    711731            sizeof(call->data.args));
    712732        if (rc != 0) {
     
    714734                return (unative_t) rc;
    715735        }
    716         if (!(res = request_preprocess(call, phone)))
     736       
     737        int res = request_preprocess(call, phone);
     738       
     739        if (!res)
    717740                ipc_call(phone, call);
    718741        else
    719742                ipc_backsend_err(phone, call, res);
    720 
     743       
    721744        return (unative_t) call;
    722745}
    723746
    724 /** Forward a received call to another destination - common code for both the
    725  * fast and the slow version.
    726  *
    727  * @param callid        Hash of the call to forward.
    728  * @param phoneid       Phone handle to use for forwarding.
    729  * @param method        New method to use for the forwarded call.
    730  * @param arg1          New value of the first argument for the forwarded call.
    731  * @param arg2          New value of the second argument for the forwarded call.
    732  * @param arg3          New value of the third argument for the forwarded call.
    733  * @param arg4          New value of the fourth argument for the forwarded call.
    734  * @param arg5          New value of the fifth argument for the forwarded call.
    735  * @param mode          Flags that specify mode of the forward operation.
    736  * @param slow          If true, arg3, arg4 and arg5 are considered. Otherwise
    737  *                      the function considers only the fast version arguments:
    738  *                      i.e. arg1 and arg2.
    739  *
    740  * @return              Return 0 on succes, otherwise return an error code.
    741  *
    742  * Warning:     Make sure that ARG5 is not rewritten for certain system IPC
     747/** Forward a received call to another destination
     748 *
     749 * Common code for both the fast and the slow version.
     750 *
     751 * @param callid  Hash of the call to forward.
     752 * @param phoneid Phone handle to use for forwarding.
     753 * @param method  New method to use for the forwarded call.
     754 * @param arg1    New value of the first argument for the forwarded call.
     755 * @param arg2    New value of the second argument for the forwarded call.
     756 * @param arg3    New value of the third argument for the forwarded call.
     757 * @param arg4    New value of the fourth argument for the forwarded call.
     758 * @param arg5    New value of the fifth argument for the forwarded call.
     759 * @param mode    Flags that specify mode of the forward operation.
     760 * @param slow    If true, arg3, arg4 and arg5 are considered. Otherwise
     761 *                the function considers only the fast version arguments:
     762 *                i.e. arg1 and arg2.
     763 *
     764 * @return 0 on succes, otherwise an error code.
     765 *
     766 * Warning: Make sure that ARG5 is not rewritten for certain system IPC
     767 *
    743768 */
    744769static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
    745770    unative_t method, unative_t arg1, unative_t arg2, unative_t arg3,
    746     unative_t arg4, unative_t arg5, int mode, bool slow)
    747 {
    748         call_t *call;
    749         phone_t *phone;
    750 
    751         call = get_call(callid);
     771    unative_t arg4, unative_t arg5, unsigned int mode, bool slow)
     772{
     773        call_t *call = get_call(callid);
    752774        if (!call)
    753775                return ENOENT;
    754776       
    755777        call->flags |= IPC_CALL_FORWARDED;
    756 
    757         GET_CHECK_PHONE(phone, phoneid, {
     778       
     779        phone_t *phone;
     780        if (phone_get(phoneid, &phone) != EOK) {
    758781                IPC_SET_RETVAL(call->data, EFORWARD);
    759782                ipc_answer(&TASK->answerbox, call);
    760783                return ENOENT;
    761         });
    762 
     784        }
     785       
    763786        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
    764787                IPC_SET_RETVAL(call->data, EFORWARD);
     
    766789                return EPERM;
    767790        }
    768 
     791       
    769792        /*
    770793         * Userspace is not allowed to change method of system methods on
     
    777800                        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
    778801                                phone_dealloc(IPC_GET_ARG5(call->data));
    779 
     802                       
    780803                        IPC_SET_ARG1(call->data, method);
    781804                        IPC_SET_ARG2(call->data, arg1);
    782805                        IPC_SET_ARG3(call->data, arg2);
     806                       
    783807                        if (slow) {
    784808                                IPC_SET_ARG4(call->data, arg3);
     
    799823                }
    800824        }
    801 
     825       
    802826        return ipc_forward(call, phone, &TASK->answerbox, mode);
    803827}
    804828
    805829/** Forward a received call to another destination - fast version.
    806  *
    807  * @param callid        Hash of the call to forward.
    808  * @param phoneid       Phone handle to use for forwarding.
    809  * @param method        New method to use for the forwarded call.
    810  * @param arg1          New value of the first argument for the forwarded call.
    811  * @param arg2          New value of the second argument for the forwarded call.
    812  * @param mode          Flags that specify mode of the forward operation.
    813  *
    814  * @return              Return 0 on succes, otherwise return an error code.
    815830 *
    816831 * In case the original method is a system method, ARG1, ARG2 and ARG3 are
     
    820835 * is a set of immutable methods, for which the new method and arguments are not
    821836 * set and these values are ignored.
     837 *
     838 * @param callid  Hash of the call to forward.
     839 * @param phoneid Phone handle to use for forwarding.
     840 * @param method  New method to use for the forwarded call.
     841 * @param arg1    New value of the first argument for the forwarded call.
     842 * @param arg2    New value of the second argument for the forwarded call.
     843 * @param mode    Flags that specify mode of the forward operation.
     844 *
     845 * @return 0 on succes, otherwise an error code.
     846 *
    822847 */
    823848unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
    824     unative_t method, unative_t arg1, unative_t arg2, int mode)
     849    unative_t method, unative_t arg1, unative_t arg2, unsigned int mode)
    825850{
    826851        return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
     
    829854
    830855/** Forward a received call to another destination - slow version.
    831  *
    832  * @param callid        Hash of the call to forward.
    833  * @param phoneid       Phone handle to use for forwarding.
    834  * @param data          Userspace address of the new IPC data.
    835  * @param mode          Flags that specify mode of the forward operation.
    836  *
    837  * @return              Return 0 on succes, otherwise return an error code.
    838856 *
    839857 * This function is the slow verision of the sys_ipc_forward_fast interface.
     
    843861 * methods, it additionally stores the new value of arg3, arg4 and arg5,
    844862 * respectively, to ARG3, ARG4 and ARG5, respectively.
     863 *
     864 * @param callid  Hash of the call to forward.
     865 * @param phoneid Phone handle to use for forwarding.
     866 * @param data    Userspace address of the new IPC data.
     867 * @param mode    Flags that specify mode of the forward operation.
     868 *
     869 * @return 0 on succes, otherwise an error code.
     870 *
    845871 */
    846872unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    847     ipc_data_t *data, int mode)
     873    ipc_data_t *data, unsigned int mode)
    848874{
    849875        ipc_data_t newdata;
    850         int rc;
    851 
    852         rc = copy_from_uspace(&newdata.args, &data->args,
     876        int rc = copy_from_uspace(&newdata.args, &data->args,
    853877            sizeof(newdata.args));
    854         if (rc != 0) 
     878        if (rc != 0)
    855879                return (unative_t) rc;
    856 
     880       
    857881        return sys_ipc_forward_common(callid, phoneid,
    858882            IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
     
    866890 * than the generic sys_ipc_answer().
    867891 *
    868  * @param callid        Hash of the call to be answered.
    869  * @param retval        Return value of the answer.
    870  * @param arg1          Service-defined return value.
    871  * @param arg2          Service-defined return value.
    872  * @param arg3          Service-defined return value.
    873  * @param arg4          Service-defined return value.
    874  *
    875  * @return              Return 0 on success, otherwise return an error code.   
     892 * @param callid Hash of the call to be answered.
     893 * @param retval Return value of the answer.
     894 * @param arg1   Service-defined return value.
     895 * @param arg2   Service-defined return value.
     896 * @param arg3   Service-defined return value.
     897 * @param arg4   Service-defined return value.
     898 *
     899 * @return 0 on success, otherwise an error code.
     900 *
    876901 */
    877902unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    878903    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    879904{
    880         call_t *call;
    881         ipc_data_t saved_data;
    882         int saveddata = 0;
    883         int rc;
    884 
    885905        /* Do not answer notification callids */
    886906        if (callid & IPC_CALLID_NOTIFICATION)
    887907                return 0;
    888 
    889         call = get_call(callid);
     908       
     909        call_t *call = get_call(callid);
    890910        if (!call)
    891911                return ENOENT;
    892 
     912       
     913        ipc_data_t saved_data;
     914        bool saved;
     915       
    893916        if (answer_need_old(call)) {
    894917                memcpy(&saved_data, &call->data, sizeof(call->data));
    895                 saveddata = 1;
    896         }
    897 
     918                saved = true;
     919        } else
     920                saved = false;
     921       
    898922        IPC_SET_RETVAL(call->data, retval);
    899923        IPC_SET_ARG1(call->data, arg1);
     
    901925        IPC_SET_ARG3(call->data, arg3);
    902926        IPC_SET_ARG4(call->data, arg4);
     927       
    903928        /*
    904929         * To achieve deterministic behavior, zero out arguments that are beyond
     
    906931         */
    907932        IPC_SET_ARG5(call->data, 0);
    908         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    909 
     933        int rc = answer_preprocess(call, saved ? &saved_data : NULL);
     934       
    910935        ipc_answer(&TASK->answerbox, call);
    911936        return rc;
     
    914939/** Answer an IPC call.
    915940 *
    916  * @param callid        Hash of the call to be answered.
    917  * @param data          Userspace address of call data with the answer.
    918  *
    919  * @return              Return 0 on success, otherwise return an error code.
     941 * @param callid Hash of the call to be answered.
     942 * @param data   Userspace address of call data with the answer.
     943 *
     944 * @return 0 on success, otherwise an error code.
     945 *
    920946 */
    921947unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data)
    922948{
    923         call_t *call;
    924         ipc_data_t saved_data;
    925         int saveddata = 0;
    926         int rc;
    927 
    928949        /* Do not answer notification callids */
    929950        if (callid & IPC_CALLID_NOTIFICATION)
    930951                return 0;
    931 
    932         call = get_call(callid);
     952       
     953        call_t *call = get_call(callid);
    933954        if (!call)
    934955                return ENOENT;
    935 
     956       
     957        ipc_data_t saved_data;
     958        bool saved;
     959       
    936960        if (answer_need_old(call)) {
    937961                memcpy(&saved_data, &call->data, sizeof(call->data));
    938                 saveddata = 1;
    939         }
    940         rc = copy_from_uspace(&call->data.args, &data->args,
     962                saved = true;
     963        } else
     964                saved = false;
     965       
     966        int rc = copy_from_uspace(&call->data.args, &data->args,
    941967            sizeof(call->data.args));
    942968        if (rc != 0)
    943969                return rc;
    944 
    945         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     970       
     971        rc = answer_preprocess(call, saved ? &saved_data : NULL);
    946972       
    947973        ipc_answer(&TASK->answerbox, call);
    948 
    949974        return rc;
    950975}
     
    952977/** Hang up a phone.
    953978 *
    954  * @param               Phone handle of the phone to be hung up.
    955  *
    956  * @return              Return 0 on success or an error code.
    957  */
    958 unative_t sys_ipc_hangup(int phoneid)
     979 * @param Phone handle of the phone to be hung up.
     980 *
     981 * @return 0 on success or an error code.
     982 *
     983 */
     984unative_t sys_ipc_hangup(unative_t phoneid)
    959985{
    960986        phone_t *phone;
    961 
    962         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
    963 
     987       
     988        if (phone_get(phoneid, &phone) != EOK)
     989                return ENOENT;
     990       
    964991        if (ipc_phone_hangup(phone))
    965992                return -1;
    966 
     993       
    967994        return 0;
    968995}
     
    970997/** Wait for an incoming IPC call or an answer.
    971998 *
    972  * @param calldata      Pointer to buffer where the call/answer data is stored.
    973  * @param usec          Timeout. See waitq_sleep_timeout() for explanation.
    974  * @param flags         Select mode of sleep operation. See waitq_sleep_timeout()
    975  *                      for explanation.
    976  *
    977  * @return              Hash of the call.
    978  *                      If IPC_CALLID_NOTIFICATION bit is set in the hash, the
    979  *                      call is a notification. IPC_CALLID_ANSWERED denotes an
    980  *                      answer.
    981  */
    982 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
     999 * @param calldata Pointer to buffer where the call/answer data is stored.
     1000 * @param usec     Timeout. See waitq_sleep_timeout() for explanation.
     1001 * @param flags    Select mode of sleep operation. See waitq_sleep_timeout()
     1002 *                 for explanation.
     1003 *
     1004 * @return Hash of the call.
     1005 *         If IPC_CALLID_NOTIFICATION bit is set in the hash, the
     1006 *         call is a notification. IPC_CALLID_ANSWERED denotes an
     1007 *         answer.
     1008 *
     1009 */
     1010unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
     1011    unsigned int flags)
    9831012{
    9841013        call_t *call;
    985 
     1014       
    9861015restart:
    987 
     1016       
    9881017#ifdef CONFIG_UDEBUG
    9891018        udebug_stoppable_begin();
    990 #endif 
     1019#endif
     1020       
    9911021        call = ipc_wait_for_call(&TASK->answerbox, usec,
    9921022            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    993 
     1023       
    9941024#ifdef CONFIG_UDEBUG
    9951025        udebug_stoppable_end();
    9961026#endif
     1027       
    9971028        if (!call)
    9981029                return 0;
    999 
     1030       
    10001031        if (call->flags & IPC_CALL_NOTIF) {
    10011032                /* Set in_phone_hash to the interrupt counter */
     
    10031034               
    10041035                STRUCT_TO_USPACE(calldata, &call->data);
    1005 
     1036               
    10061037                ipc_call_free(call);
    10071038               
    10081039                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    10091040        }
    1010 
     1041       
    10111042        if (call->flags & IPC_CALL_ANSWERED) {
    10121043                process_answer(call);
    1013 
     1044               
    10141045                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10151046                        ipc_call_free(call);
     
    10231054                        atomic_dec(&TASK->active_calls);
    10241055                }
    1025 
     1056               
    10261057                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10271058                ipc_call_free(call);
    1028 
     1059               
    10291060                return ((unative_t) call) | IPC_CALLID_ANSWERED;
    10301061        }
    1031 
     1062       
    10321063        if (process_request(&TASK->answerbox, call))
    10331064                goto restart;
    1034 
     1065       
    10351066        /* Include phone address('id') of the caller in the request,
    10361067         * copy whole call->data, not only call->data.args */
     
    10411072                 */
    10421073                ipc_data_t saved_data;
    1043                 int saveddata = 0;
    1044 
     1074                bool saved;
     1075               
    10451076                if (answer_need_old(call)) {
    10461077                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1047                         saveddata = 1;
    1048                 }
     1078                        saved = true;
     1079                } else
     1080                        saved = false;
    10491081               
    10501082                IPC_SET_RETVAL(call->data, EPARTY);
    1051                 (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
     1083                (void) answer_preprocess(call, saved ? &saved_data : NULL);
    10521084                ipc_answer(&TASK->answerbox, call);
    10531085                return 0;
    10541086        }
    1055         return (unative_t)call;
    1056 }
    1057 
    1058 /** Interrupt one thread from sys_ipc_wait_for_call(). */
     1087       
     1088        return (unative_t) call;
     1089}
     1090
     1091/** Interrupt one thread from sys_ipc_wait_for_call().
     1092 *
     1093 */
    10591094unative_t sys_ipc_poke(void)
    10601095{
    1061         waitq_unsleep(&TASK->answerbox.wq);     
     1096        waitq_unsleep(&TASK->answerbox.wq);
    10621097        return EOK;
    10631098}
     
    10651100/** Connect an IRQ handler to a task.
    10661101 *
    1067  * @param inr           IRQ number.
    1068  * @param devno         Device number.
    1069  * @param method        Method to be associated with the notification.
    1070  * @param ucode         Uspace pointer to the top-half pseudocode.
    1071  *
    1072  * @return              EPERM or a return code returned by ipc_irq_register().
     1102 * @param inr    IRQ number.
     1103 * @param devno  Device number.
     1104 * @param method Method to be associated with the notification.
     1105 * @param ucode  Uspace pointer to the top-half pseudocode.
     1106 *
     1107 * @return EPERM or a return code returned by ipc_irq_register().
     1108 *
    10731109 */
    10741110unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     
    10771113        if (!(cap_get(TASK) & CAP_IRQ_REG))
    10781114                return EPERM;
    1079 
     1115       
    10801116        return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
    10811117}
     
    10831119/** Disconnect an IRQ handler from a task.
    10841120 *
    1085  * @param inr           IRQ number.
    1086  * @param devno         Device number.
    1087  *
    1088  * @return              Zero on success or EPERM on error..
     1121 * @param inr   IRQ number.
     1122 * @param devno Device number.
     1123 *
     1124 * @return Zero on success or EPERM on error.
     1125 *
    10891126 */
    10901127unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
     
    10921129        if (!(cap_get(TASK) & CAP_IRQ_REG))
    10931130                return EPERM;
    1094 
     1131       
    10951132        ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1096 
     1133       
    10971134        return 0;
    10981135}
     
    11001137#include <console/console.h>
    11011138
    1102 /**
    1103  * Syscall connect to a task by id.
    1104  *
    1105  * @return              Phone id on success, or negative error code.
     1139/** Syscall connect to a task by id.
     1140 *
     1141 * @return Phone id on success, or negative error code.
     1142 *
    11061143 */
    11071144unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     
    11091146#ifdef CONFIG_UDEBUG
    11101147        sysarg64_t taskid_arg;
    1111         int rc;
    1112        
    1113         rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
     1148        int rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    11141149        if (rc != 0)
    11151150                return (unative_t) rc;
    1116 
    1117         LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
    1118 
     1151       
     1152        LOG("sys_ipc_connect_kbox(%" PRIu64 ")", taskid_arg.value);
     1153       
    11191154        return ipc_connect_kbox(taskid_arg.value);
    11201155#else
Note: See TracChangeset for help on using the changeset viewer.