Changeset da1bafb in mainline for kernel/generic/src/ipc


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

major code revision

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

Legend:

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

    r666f492 rda1bafb  
    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

    r666f492 rda1bafb  
    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         ipl_t ipl;
    221 
     219       
    222220        /* Count sent answer */
    223         ipl = interrupts_disable();
    224         spinlock_lock(&TASK->lock);
     221        irq_spinlock_lock(&TASK->lock, true);
    225222        TASK->ipc_info.answer_sent++;
    226         spinlock_unlock(&TASK->lock);
    227         interrupts_restore(ipl);
    228 
     223        irq_spinlock_unlock(&TASK->lock, true);
     224       
    229225        call->flags |= IPC_CALL_ANSWERED;
    230 
     226       
    231227        if (call->flags & IPC_CALL_FORWARDED) {
    232228                if (call->caller_phone) {
     
    235231                }
    236232        }
    237 
     233       
    238234        if (do_lock)
    239                 spinlock_lock(&callerbox->lock);
     235                irq_spinlock_lock(&callerbox->lock, true);
     236       
    240237        list_append(&call->link, &callerbox->answers);
     238       
    241239        if (do_lock)
    242                 spinlock_unlock(&callerbox->lock);
     240                irq_spinlock_unlock(&callerbox->lock, true);
     241       
    243242        waitq_wakeup(&callerbox->wq, WAKEUP_FIRST);
    244243}
     
    246245/** Answer a message which is in a callee queue.
    247246 *
    248  * @param box           Answerbox that is answering the message.
    249  * @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 *
    250250 */
    251251void ipc_answer(answerbox_t *box, call_t *call)
    252252{
    253253        /* Remove from active box */
    254         spinlock_lock(&box->lock);
     254        irq_spinlock_lock(&box->lock, true);
    255255        list_remove(&call->link);
    256         spinlock_unlock(&box->lock);
     256        irq_spinlock_unlock(&box->lock, true);
     257       
    257258        /* Send back answer */
    258259        _ipc_answer_free_call(call, false);
     
    264265 * message and sending it as a normal answer.
    265266 *
    266  * @param phone         Phone structure the call should appear to come from.
    267  * @param call          Call structure to be answered.
    268  * @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 *
    269271 */
    270272void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err)
     
    278280/** Unsafe unchecking version of ipc_call.
    279281 *
    280  * @param phone         Phone structure the call comes from.
    281  * @param box           Destination answerbox structure.
    282  * @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 *
    283286 */
    284287static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
    285288{
    286         ipl_t ipl;
    287 
    288289        /* Count sent ipc call */
    289         ipl = interrupts_disable();
    290         spinlock_lock(&TASK->lock);
     290        irq_spinlock_lock(&TASK->lock, true);
    291291        TASK->ipc_info.call_sent++;
    292         spinlock_unlock(&TASK->lock);
    293         interrupts_restore(ipl);
    294 
     292        irq_spinlock_unlock(&TASK->lock, true);
     293       
    295294        if (!(call->flags & IPC_CALL_FORWARDED)) {
    296295                atomic_inc(&phone->active_calls);
    297296                call->data.phone = phone;
    298297        }
    299 
    300         spinlock_lock(&box->lock);
     298       
     299        irq_spinlock_lock(&box->lock, true);
    301300        list_append(&call->link, &box->calls);
    302         spinlock_unlock(&box->lock);
     301        irq_spinlock_unlock(&box->lock, true);
     302       
    303303        waitq_wakeup(&box->wq, WAKEUP_FIRST);
    304304}
     
    306306/** Send an asynchronous request using a phone to an answerbox.
    307307 *
    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.
     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 *
    313314 */
    314315int ipc_call(phone_t *phone, call_t *call)
    315316{
    316         answerbox_t *box;
    317 
    318317        mutex_lock(&phone->lock);
    319318        if (phone->state != IPC_PHONE_CONNECTED) {
     
    328327                                ipc_backsend_err(phone, call, ENOENT);
    329328                }
     329               
    330330                return ENOENT;
    331331        }
    332         box = phone->callee;
     332       
     333        answerbox_t *box = phone->callee;
    333334        _ipc_call(phone, box, call);
    334335       
     
    342343 * lazily later.
    343344 *
    344  * @param phone         Phone structure to be hung up.
    345  *             
    346  * @return              Return 0 if the phone is disconnected.
    347  *                      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 *
    348350 */
    349351int ipc_phone_hangup(phone_t *phone)
    350352{
    351         answerbox_t *box;
    352         call_t *call;
    353        
    354353        mutex_lock(&phone->lock);
    355354        if (phone->state == IPC_PHONE_FREE ||
     
    359358                return -1;
    360359        }
    361         box = phone->callee;
     360       
     361        answerbox_t *box = phone->callee;
    362362        if (phone->state != IPC_PHONE_SLAMMED) {
    363363                /* Remove myself from answerbox */
    364                 spinlock_lock(&box->lock);
     364                irq_spinlock_lock(&box->lock, true);
    365365                list_remove(&phone->link);
    366                 spinlock_unlock(&box->lock);
    367 
    368                 call = ipc_call_alloc(0);
     366                irq_spinlock_unlock(&box->lock, true);
     367               
     368                call_t *call = ipc_call_alloc(0);
    369369                IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
    370370                call->flags |= IPC_CALL_DISCARD_ANSWER;
    371371                _ipc_call(phone, box, call);
    372372        }
    373 
     373       
    374374        phone->state = IPC_PHONE_HUNGUP;
    375375        mutex_unlock(&phone->lock);
    376 
     376       
    377377        return 0;
    378378}
     
    380380/** Forwards call from one answerbox to another one.
    381381 *
    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              Return 0 if forwarding succeeded or an error code if
    388  *                      there was error.
    389  * 
     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 *
    390390 * The return value serves only as an information for the forwarder,
    391391 * the original caller is notified automatically with EFORWARD.
    392  */
    393 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode)
    394 {
    395         ipl_t ipl;
    396 
     392 *
     393 */
     394int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox,
     395    unsigned int mode)
     396{
    397397        /* Count forwarded calls */
    398         ipl = interrupts_disable();
    399         spinlock_lock(&TASK->lock);
     398        irq_spinlock_lock(&TASK->lock, true);
    400399        TASK->ipc_info.forwarded++;
    401         spinlock_unlock(&TASK->lock);
    402         interrupts_restore(ipl);
    403 
    404         spinlock_lock(&oldbox->lock);
     400        irq_spinlock_pass(&TASK->lock, &oldbox->lock);
    405401        list_remove(&call->link);
    406         spinlock_unlock(&oldbox->lock);
    407 
     402        irq_spinlock_unlock(&oldbox->lock, true);
     403       
    408404        if (mode & IPC_FF_ROUTE_FROM_ME) {
    409405                if (!call->caller_phone)
     
    411407                call->data.phone = newphone;
    412408        }
    413 
     409       
    414410        return ipc_call(newphone, call);
    415411}
     
    418414/** Wait for a phone call.
    419415 *
    420  * @param box           Answerbox expecting the call.
    421  * @param usec          Timeout in microseconds. See documentation for
    422  *                      waitq_sleep_timeout() for decription of its special
    423  *                      meaning.
    424  * @param flags         Select mode of sleep operation. See documentation for
    425  *                      waitq_sleep_timeout() for description of its special
    426  *                      meaning.
    427  * @return              Recived call structure or NULL.
    428  *
     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 *
    429426 * To distinguish between a call and an answer, have a look at call->flags.
    430  */
    431 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)
    432430{
    433431        call_t *request;
    434         ipl_t ipl;
    435432        uint64_t irq_cnt = 0;
    436433        uint64_t answer_cnt = 0;
    437434        uint64_t call_cnt = 0;
    438435        int rc;
    439 
     436       
    440437restart:
    441438        rc = waitq_sleep_timeout(&box->wq, usec, flags);
     
    443440                return NULL;
    444441       
    445         spinlock_lock(&box->lock);
     442        irq_spinlock_lock(&box->lock, true);
    446443        if (!list_empty(&box->irq_notifs)) {
    447444                /* Count recieved IRQ notification */
    448                 irq_cnt++;     
    449 
    450                 ipl = interrupts_disable();
    451                 spinlock_lock(&box->irq_lock);
    452 
     445                irq_cnt++;
     446               
     447                irq_spinlock_lock(&box->irq_lock, false);
     448               
    453449                request = list_get_instance(box->irq_notifs.next, call_t, link);
    454450                list_remove(&request->link);
    455 
    456                 spinlock_unlock(&box->irq_lock);
    457                 interrupts_restore(ipl);
     451               
     452                irq_spinlock_unlock(&box->irq_lock, false);
    458453        } else if (!list_empty(&box->answers)) {
    459454                /* Count recieved answer */
    460455                answer_cnt++;
    461 
     456               
    462457                /* Handle asynchronous answers */
    463458                request = list_get_instance(box->answers.next, call_t, link);
     
    467462                /* Count recieved call */
    468463                call_cnt++;
    469 
     464               
    470465                /* Handle requests */
    471466                request = list_get_instance(box->calls.next, call_t, link);
    472467                list_remove(&request->link);
     468               
    473469                /* Append request to dispatch queue */
    474470                list_append(&request->link, &box->dispatched_calls);
    475471        } else {
    476472                /* This can happen regularly after ipc_cleanup */
    477                 spinlock_unlock(&box->lock);
     473                irq_spinlock_unlock(&box->lock, true);
    478474                goto restart;
    479475        }
    480         spinlock_unlock(&box->lock);
    481        
    482         ipl = interrupts_disable();
    483         spinlock_lock(&TASK->lock);
     476       
     477        irq_spinlock_pass(&box->lock, &TASK->lock);
     478       
    484479        TASK->ipc_info.irq_notif_recieved += irq_cnt;
    485480        TASK->ipc_info.answer_recieved += answer_cnt;
    486481        TASK->ipc_info.call_recieved += call_cnt;
    487         spinlock_unlock(&TASK->lock);
    488         interrupts_restore(ipl);
    489 
     482       
     483        irq_spinlock_unlock(&TASK->lock, true);
     484       
    490485        return request;
    491486}
     
    493488/** Answer all calls from list with EHANGUP answer.
    494489 *
    495  * @param lst           Head of the list to be cleaned up.
     490 * @param lst Head of the list to be cleaned up.
     491 *
    496492 */
    497493void ipc_cleanup_call_list(link_t *lst)
    498494{
    499         call_t *call;
    500 
    501495        while (!list_empty(lst)) {
    502                 call = list_get_instance(lst->next, call_t, link);
     496                call_t *call = list_get_instance(lst->next, call_t, link);
    503497                if (call->buffer)
    504498                        free(call->buffer);
     499               
    505500                list_remove(&call->link);
    506 
     501               
    507502                IPC_SET_RETVAL(call->data, EHANGUP);
    508503                _ipc_answer_free_call(call, true);
     
    512507/** Disconnects all phones connected to an answerbox.
    513508 *
    514  * @param box           Answerbox to disconnect phones from.
    515  * @param notify_box    If true, the answerbox will get a hangup message for
    516  *                      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 *
    517513 */
    518514void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box)
     
    520516        phone_t *phone;
    521517        DEADLOCK_PROBE_INIT(p_phonelck);
    522         ipl_t ipl;
    523         call_t *call;
    524 
    525         call = notify_box ? ipc_call_alloc(0) : NULL;
    526 
     518       
     519        call_t *call = notify_box ? ipc_call_alloc(0) : NULL;
     520       
    527521        /* Disconnect all phones connected to our answerbox */
    528522restart_phones:
    529         ipl = interrupts_disable();
    530         spinlock_lock(&box->lock);
     523        irq_spinlock_lock(&box->lock, true);
    531524        while (!list_empty(&box->connected_phones)) {
    532525                phone = list_get_instance(box->connected_phones.next,
    533526                    phone_t, link);
    534527                if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
    535                         spinlock_unlock(&box->lock);
    536                         interrupts_restore(ipl);
     528                        irq_spinlock_unlock(&box->lock, true);
    537529                        DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD);
    538530                        goto restart_phones;
     
    541533                /* Disconnect phone */
    542534                ASSERT(phone->state == IPC_PHONE_CONNECTED);
    543 
     535               
    544536                list_remove(&phone->link);
    545537                phone->state = IPC_PHONE_SLAMMED;
    546 
     538               
    547539                if (notify_box) {
    548540                        mutex_unlock(&phone->lock);
    549                         spinlock_unlock(&box->lock);
    550                         interrupts_restore(ipl);
    551 
     541                        irq_spinlock_unlock(&box->lock, true);
     542                       
    552543                        /*
    553544                         * Send one message to the answerbox for each
     
    559550                        call->flags |= IPC_CALL_DISCARD_ANSWER;
    560551                        _ipc_call(phone, box, call);
    561 
     552                       
    562553                        /* Allocate another call in advance */
    563554                        call = ipc_call_alloc(0);
    564 
     555                       
    565556                        /* Must start again */
    566557                        goto restart_phones;
    567558                }
    568 
     559               
    569560                mutex_unlock(&phone->lock);
    570561        }
    571 
    572         spinlock_unlock(&box->lock);
    573         interrupts_restore(ipl);
    574 
     562       
     563        irq_spinlock_unlock(&box->lock, true);
     564       
    575565        /* Free unused call */
    576566        if (call)
     
    578568}
    579569
    580 /** Cleans up all IPC communication of the current task.
     570/** Clean up all IPC communication of the current task.
    581571 *
    582572 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you
    583573 * have to change it as well if you want to cleanup other tasks than TASK.
     574 *
    584575 */
    585576void ipc_cleanup(void)
    586577{
    587         int i;
    588         call_t *call;
    589         ipl_t ipl;
    590 
    591578        /* Disconnect all our phones ('ipc_phone_hangup') */
     579        size_t i;
    592580        for (i = 0; i < IPC_MAX_PHONES; i++)
    593581                ipc_phone_hangup(&TASK->phones[i]);
    594 
     582       
    595583        /* Unsubscribe from any event notifications. */
    596584        event_cleanup_answerbox(&TASK->answerbox);
    597 
     585       
    598586        /* Disconnect all connected irqs */
    599587        ipc_irq_cleanup(&TASK->answerbox);
    600 
     588       
    601589        /* Disconnect all phones connected to our regular answerbox */
    602590        ipc_answerbox_slam_phones(&TASK->answerbox, false);
    603 
     591       
    604592#ifdef CONFIG_UDEBUG
    605593        /* Clean up kbox thread and communications */
    606594        ipc_kbox_cleanup();
    607595#endif
    608 
     596       
    609597        /* Answer all messages in 'calls' and 'dispatched_calls' queues */
    610         spinlock_lock(&TASK->answerbox.lock);
     598        irq_spinlock_lock(&TASK->answerbox.lock, true);
    611599        ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls);
    612600        ipc_cleanup_call_list(&TASK->answerbox.calls);
    613         spinlock_unlock(&TASK->answerbox.lock);
     601        irq_spinlock_unlock(&TASK->answerbox.lock, true);
    614602       
    615603        /* Wait for all answers to interrupted synchronous calls to arrive */
    616         ipl = interrupts_disable();
     604        ipl_t ipl = interrupts_disable();
    617605        while (!list_empty(&TASK->sync_box_head)) {
    618606                answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
    619607                    answerbox_t, sync_box_link);
    620 
     608               
    621609                list_remove(&box->sync_box_link);
    622                 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
     610                call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
    623611                    SYNCH_FLAGS_NONE);
    624612                ipc_call_free(call);
     
    626614        }
    627615        interrupts_restore(ipl);
    628 
     616       
    629617        /* Wait for all answers to asynchronous calls to arrive */
    630         while (1) {
    631                 /* Go through all phones, until all are FREE... */
    632                 /* Locking not needed, no one else should modify
    633                  * 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                 */
    634624                for (i = 0; i < IPC_MAX_PHONES; i++) {
    635625                        if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
     
    639629                        }
    640630                       
    641                         /* Just for sure, we might have had some
    642                          * IPC_PHONE_CONNECTING phones */
     631                        /*
     632                         * Just for sure, we might have had some
     633                         * IPC_PHONE_CONNECTING phones
     634                         */
    643635                        if (TASK->phones[i].state == IPC_PHONE_CONNECTED)
    644636                                ipc_phone_hangup(&TASK->phones[i]);
    645                         /* If the hangup succeeded, it has sent a HANGUP
     637                       
     638                        /*
     639                         * If the hangup succeeded, it has sent a HANGUP
    646640                         * message, the IPC is now in HUNGUP state, we
    647                          * wait for the reply to come */
     641                         * wait for the reply to come
     642                         */
    648643                       
    649644                        if (TASK->phones[i].state != IPC_PHONE_FREE)
    650645                                break;
    651646                }
    652                 /* Voila, got into cleanup */
     647               
     648                /* Got into cleanup */
    653649                if (i == IPC_MAX_PHONES)
    654650                        break;
    655651               
    656                 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
     652                call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
    657653                    SYNCH_FLAGS_NONE);
    658654                ASSERT((call->flags & IPC_CALL_ANSWERED) ||
     
    666662                if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
    667663                        atomic_dec(&TASK->active_calls);
     664               
    668665                ipc_call_free(call);
    669666        }
    670667}
    671668
    672 
    673 /** Initilize IPC subsystem */
     669/** Initilize IPC subsystem
     670 *
     671 */
    674672void ipc_init(void)
    675673{
     
    680678}
    681679
    682 
    683680/** List answerbox contents.
    684681 *
    685  * @param taskid        Task ID.
     682 * @param taskid Task ID.
     683 *
    686684 */
    687685void ipc_print_task(task_id_t taskid)
    688686{
    689         task_t *task;
    690         int i;
    691         call_t *call;
    692         link_t *tmp;
    693         ipl_t ipl;
    694        
    695         ipl = interrupts_disable();
    696         spinlock_lock(&tasks_lock);
    697         task = task_find_by_id(taskid);
    698         if (task)
    699                 spinlock_lock(&task->lock);
    700         spinlock_unlock(&tasks_lock);
     687        irq_spinlock_lock(&tasks_lock, true);
     688        task_t *task = task_find_by_id(taskid);
     689       
    701690        if (!task) {
    702                 interrupts_restore(ipl);
     691                irq_spinlock_unlock(&tasks_lock, true);
    703692                return;
    704693        }
    705 
     694       
     695        /* Hand-over-hand locking */
     696        irq_spinlock_exchange(&tasks_lock, &task->lock);
     697       
    706698        /* Print opened phones & details */
    707699        printf("PHONE:\n");
     700       
     701        size_t i;
    708702        for (i = 0; i < IPC_MAX_PHONES; i++) {
    709703                if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) {
     
    711705                        continue;
    712706                }
     707               
    713708                if (task->phones[i].state != IPC_PHONE_FREE) {
    714                         printf("%d: ", i);
     709                        printf("%" PRIs ": ", i);
     710                       
    715711                        switch (task->phones[i].state) {
    716712                        case IPC_PHONE_CONNECTING:
     
    718714                                break;
    719715                        case IPC_PHONE_CONNECTED:
    720                                 printf("connected to: %p ", 
    721                                        task->phones[i].callee);
     716                                printf("connected to: %p ",
     717                                    task->phones[i].callee);
    722718                                break;
    723719                        case IPC_PHONE_SLAMMED:
    724720                                printf("slammed by: %p ",
    725                                        task->phones[i].callee);
     721                                    task->phones[i].callee);
    726722                                break;
    727723                        case IPC_PHONE_HUNGUP:
    728724                                printf("hung up - was: %p ",
    729                                        task->phones[i].callee);
     725                                    task->phones[i].callee);
    730726                                break;
    731727                        default:
    732728                                break;
    733729                        }
    734                         printf("active: %ld\n",
     730                       
     731                        printf("active: %" PRIun "\n",
    735732                            atomic_get(&task->phones[i].active_calls));
    736733                }
     734               
    737735                mutex_unlock(&task->phones[i].lock);
    738736        }
    739 
    740 
     737       
     738        irq_spinlock_lock(&task->answerbox.lock, false);
     739       
     740        link_t *cur;
     741       
    741742        /* Print answerbox - calls */
    742         spinlock_lock(&task->answerbox.lock);
    743743        printf("ABOX - CALLS:\n");
    744         for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls;
    745             tmp = tmp->next) {
    746                 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);
    747747                printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
    748748                    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
     
    754754                    call->flags);
    755755        }
    756         /* Print answerbox - calls */
     756       
     757        /* Print answerbox - dispatched calls */
    757758        printf("ABOX - DISPATCHED CALLS:\n");
    758         for (tmp = task->answerbox.dispatched_calls.next;
    759             tmp != &task->answerbox.dispatched_calls;
    760             tmp = tmp->next) {
    761                 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);
    762763                printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
    763764                    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
     
    769770                    call->flags);
    770771        }
    771         /* Print answerbox - calls */
     772       
     773        /* Print answerbox - answers */
    772774        printf("ABOX - ANSWERS:\n");
    773         for (tmp = task->answerbox.answers.next;
    774             tmp != &task->answerbox.answers;
    775             tmp = tmp->next) {
    776                 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);
    777779                printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun
    778780                    " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
     
    782784                    call->flags);
    783785        }
    784 
    785         spinlock_unlock(&task->answerbox.lock);
    786         spinlock_unlock(&task->lock);
    787         interrupts_restore(ipl);
     786       
     787        irq_spinlock_unlock(&task->answerbox.lock, false);
     788        irq_spinlock_unlock(&task->lock, true);
    788789}
    789790
  • kernel/generic/src/ipc/ipcrsc.c

    r666f492 rda1bafb  
    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

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

    r666f492 rda1bafb  
    4747void ipc_kbox_cleanup(void)
    4848{
    49         bool have_kb_thread;
    50 
    51         /*
     49        /*
    5250         * Only hold kb.cleanup_lock while setting kb.finished -
    5351         * this is enough.
     
    5654        TASK->kb.finished = true;
    5755        mutex_unlock(&TASK->kb.cleanup_lock);
    58 
    59         have_kb_thread = (TASK->kb.thread != NULL);
    60 
     56       
     57        bool have_kb_thread = (TASK->kb.thread != NULL);
     58       
    6159        /*
    6260         * From now on nobody will try to connect phones or attach
    6361         * kbox threads
    6462         */
    65 
     63       
    6664        /*
    6765         * Disconnect all phones connected to our kbox. Passing true for
     
    7169         */
    7270        ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread);
    73 
    74         /* 
     71       
     72        /*
    7573         * If the task was being debugged, clean up debugging session.
    7674         * This is necessarry as slamming the phones won't force
     
    8078        udebug_task_cleanup(TASK);
    8179        mutex_unlock(&TASK->udebug.lock);
    82 
     80       
    8381        if (have_kb_thread) {
    8482                LOG("Join kb.thread.");
     
    8886                TASK->kb.thread = NULL;
    8987        }
    90 
     88       
    9189        /* Answer all messages in 'calls' and 'dispatched_calls' queues. */
    92         spinlock_lock(&TASK->kb.box.lock);
     90        irq_spinlock_lock(&TASK->kb.box.lock, true);
    9391        ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls);
    9492        ipc_cleanup_call_list(&TASK->kb.box.calls);
    95         spinlock_unlock(&TASK->kb.box.lock);
     93        irq_spinlock_unlock(&TASK->kb.box.lock, true);
    9694}
    9795
    9896/** Handle hangup message in kbox.
    9997 *
    100  * @param call  The IPC_M_PHONE_HUNGUP call structure.
    101  * @param last  Output, the function stores @c true here if
    102  *              this was the last phone, @c false otherwise.
    103  **/
     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 */
    104103static void kbox_proc_phone_hungup(call_t *call, bool *last)
    105104{
    106         ipl_t ipl;
    107 
    108105        /* Was it our debugger, who hung up? */
    109106        if (call->sender == TASK->udebug.debugger) {
    110107                /* Terminate debugging session (if any). */
    111108                LOG("Terminate debugging session.");
    112                 ipl = interrupts_disable();
    113                 spinlock_lock(&TASK->lock);
     109                irq_spinlock_lock(&TASK->lock, true);
    114110                udebug_task_cleanup(TASK);
    115                 spinlock_unlock(&TASK->lock);
    116                 interrupts_restore(ipl);
     111                irq_spinlock_unlock(&TASK->lock, true);
    117112        } else {
    118113                LOG("Was not debugger.");
    119114        }
    120 
     115       
    121116        LOG("Continue with hangup message.");
    122117        IPC_SET_RETVAL(call->data, 0);
    123118        ipc_answer(&TASK->kb.box, call);
    124 
     119       
    125120        mutex_lock(&TASK->kb.cleanup_lock);
    126 
    127         ipl = interrupts_disable();
    128         spinlock_lock(&TASK->lock);
    129         spinlock_lock(&TASK->kb.box.lock);
     121       
     122        irq_spinlock_lock(&TASK->lock, true);
     123        irq_spinlock_lock(&TASK->kb.box.lock, false);
    130124        if (list_empty(&TASK->kb.box.connected_phones)) {
    131125                /*
     
    133127                 * gets freed and signal to the caller.
    134128                 */
    135 
     129               
    136130                /* Only detach kbox thread unless already terminating. */
    137131                if (TASK->kb.finished == false) {
     
    140134                        TASK->kb.thread = NULL;
    141135                }
    142 
     136               
    143137                LOG("Phone list is empty.");
    144138                *last = true;
    145         } else {
     139        } else
    146140                *last = false;
    147         }
    148 
    149         spinlock_unlock(&TASK->kb.box.lock);
    150         spinlock_unlock(&TASK->lock);
    151         interrupts_restore(ipl);
    152 
     141       
     142        irq_spinlock_unlock(&TASK->kb.box.lock, true);
     143        irq_spinlock_unlock(&TASK->lock, false);
     144       
    153145        mutex_unlock(&TASK->kb.cleanup_lock);
    154146}
     
    159151 * when all phones are disconnected from the kbox.
    160152 *
    161  * @param arg   Ignored.
     153 * @param arg Ignored.
     154 *
    162155 */
    163156static void kbox_thread_proc(void *arg)
    164157{
    165         call_t *call;
    166         bool done;
    167 
    168         (void)arg;
     158        (void) arg;
    169159        LOG("Starting.");
    170         done = false;
    171 
     160        bool done = false;
     161       
    172162        while (!done) {
    173                 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,
    174164                        SYNCH_FLAGS_NONE);
    175 
     165               
    176166                if (call == NULL)
    177                         continue;       /* Try again. */
    178 
     167                        continue;  /* Try again. */
     168               
    179169                switch (IPC_GET_METHOD(call->data)) {
    180 
     170               
    181171                case IPC_M_DEBUG_ALL:
    182172                        /* Handle debug call. */
    183173                        udebug_call_receive(call);
    184174                        break;
    185 
     175               
    186176                case IPC_M_PHONE_HUNGUP:
    187177                        /*
     
    192182                        kbox_proc_phone_hungup(call, &done);
    193183                        break;
    194 
     184               
    195185                default:
    196186                        /* Ignore */
     
    198188                }
    199189        }
    200 
     190       
    201191        LOG("Exiting.");
    202192}
    203193
    204194
    205 /**
    206  * Connect phone to a task kernel-box specified by id.
     195/** Connect phone to a task kernel-box specified by id.
    207196 *
    208197 * Note that this is not completely atomic. For optimisation reasons, the task
     
    211200 * cleanup code.
    212201 *
    213  * @return              Phone id on success, or negative error code.
     202 * @return Phone id on success, or negative error code.
     203 *
    214204 */
    215205int ipc_connect_kbox(task_id_t taskid)
    216206{
    217         int newphid;
    218         task_t *ta;
    219         thread_t *kb_thread;
    220         ipl_t ipl;
    221 
    222         ipl = interrupts_disable();
    223         spinlock_lock(&tasks_lock);
    224 
    225         ta = task_find_by_id(taskid);
    226         if (ta == NULL) {
    227                 spinlock_unlock(&tasks_lock);
    228                 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);
    229212                return ENOENT;
    230213        }
    231 
    232         atomic_inc(&ta->refcount);
    233 
    234         spinlock_unlock(&tasks_lock);
    235         interrupts_restore(ipl);
    236 
    237         mutex_lock(&ta->kb.cleanup_lock);
    238 
    239         if (atomic_predec(&ta->refcount) == 0) {
    240                 mutex_unlock(&ta->kb.cleanup_lock);
    241                 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);
    242224                return ENOENT;
    243225        }
    244 
    245         if (ta->kb.finished != false) {
    246                 mutex_unlock(&ta->kb.cleanup_lock);
     226       
     227        if (task->kb.finished != false) {
     228                mutex_unlock(&task->kb.cleanup_lock);
    247229                return EINVAL;
    248230        }
    249 
    250         newphid = phone_alloc(TASK);
     231       
     232        int newphid = phone_alloc(TASK);
    251233        if (newphid < 0) {
    252                 mutex_unlock(&ta->kb.cleanup_lock);
     234                mutex_unlock(&task->kb.cleanup_lock);
    253235                return ELIMIT;
    254236        }
    255 
     237       
    256238        /* Connect the newly allocated phone to the kbox */
    257         ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box);
    258 
    259         if (ta->kb.thread != NULL) {
    260                 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);
    261243                return newphid;
    262244        }
    263 
     245       
    264246        /* Create a kbox thread */
    265         kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0,
     247        thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0,
    266248            "kbox", false);
    267249        if (!kb_thread) {
    268                 mutex_unlock(&ta->kb.cleanup_lock);
     250                mutex_unlock(&task->kb.cleanup_lock);
    269251                return ENOMEM;
    270252        }
    271 
    272         ta->kb.thread = kb_thread;
     253       
     254        task->kb.thread = kb_thread;
    273255        thread_ready(kb_thread);
    274 
    275         mutex_unlock(&ta->kb.cleanup_lock);
    276 
     256       
     257        mutex_unlock(&task->kb.cleanup_lock);
     258       
    277259        return newphid;
    278260}
  • kernel/generic/src/ipc/sysipc.c

    r666f492 rda1bafb  
    5656 * requests.
    5757 */
    58 #define DATA_XFER_LIMIT         (64 * 1024)
     58#define DATA_XFER_LIMIT  (64 * 1024)
     59
     60#define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
    5961
    6062/** Get phone from the current task by ID.
    6163 *
    62  * @param phoneid       Phone ID.
    63  * @param phone         Place to store pointer to phone.
    64  * @return              EOK on success, EINVAL if ID is invalid.
     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 *
    6569 */
    6670static int phone_get(unative_t phoneid, phone_t **phone)
     
    6872        if (phoneid >= IPC_MAX_PHONES)
    6973                return EINVAL;
    70 
     74       
    7175        *phone = &TASK->phones[phoneid];
    7276        return EOK;
    7377}
    7478
    75 #define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
    76 
    7779/** Decide if the method is a system method.
    7880 *
    79  * @param method        Method to be decided.
    80  *
    81  * @return              Return 1 if the method is a system method.
    82  *                      Otherwise return 0.
    83  */
    84 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)
    8587{
    8688        if (method <= IPC_M_LAST_SYSTEM)
    87                 return 1;
    88         return 0;
     89                return true;
     90       
     91        return false;
    8992}
    9093
     
    9497 *   it is useless
    9598 *
    96  * @param method        Method to be decided.
    97  *
    98  * @return              Return 1 if the method is forwardable.
    99  *                      Otherwise return 0.
    100  */
    101 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)
    102105{
    103106        switch (method) {
     
    106109        case IPC_M_PHONE_HUNGUP:
    107110                /* This message is meant only for the original recipient. */
    108                 return 0;
     111                return false;
    109112        default:
    110                 return 1;
     113                return true;
    111114        }
    112115}
     
    116119 * - some system messages may be forwarded but their content cannot be altered
    117120 *
    118  * @param method        Method to be decided.
    119  *
    120  * @return              Return 1 if the method is immutable on forward.
    121  *                      Otherwise return 0.
    122  */
    123 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)
    124127{
    125128        switch (method) {
     
    128131        case IPC_M_DATA_WRITE:
    129132        case IPC_M_DATA_READ:
    130                 return 1;
     133                return true;
    131134        default:
    132                 return 0;
     135                return false;
    133136        }
    134137}
     
    142145 * for answer_preprocess().
    143146 *
    144  * @param call          Call structure to be decided.
    145  *
    146  * @return              Return 1 if the old call contents should be saved.
    147  *                      Return 0 otherwise.
    148  */
    149 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)
    150153{
    151154        switch (IPC_GET_METHOD(call->data)) {
     
    158161        case IPC_M_DATA_WRITE:
    159162        case IPC_M_DATA_READ:
    160                 return 1;
     163                return true;
    161164        default:
    162                 return 0;
     165                return false;
    163166        }
    164167}
     
    168171 * This function is called directly after sys_ipc_answer().
    169172 *
    170  * @param answer        Call structure with the answer.
    171  * @param olddata       Saved data of the request.
    172  *
    173  * @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 *
    174178 */
    175179static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    176180{
    177         int phoneid;
    178 
    179181        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    180182                /* In case of forward, hangup the forwared phone,
     
    182184                 */
    183185                mutex_lock(&answer->data.phone->lock);
    184                 spinlock_lock(&TASK->answerbox.lock);
     186                irq_spinlock_lock(&TASK->answerbox.lock, true);
    185187                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    186188                        list_remove(&answer->data.phone->link);
    187189                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    188190                }
    189                 spinlock_unlock(&TASK->answerbox.lock);
     191                irq_spinlock_unlock(&TASK->answerbox.lock, true);
    190192                mutex_unlock(&answer->data.phone->lock);
    191193        }
    192 
     194       
    193195        if (!olddata)
    194196                return 0;
    195 
     197       
    196198        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
    197                 phoneid = IPC_GET_ARG1(*olddata);
    198                 phone_t *phone = &TASK->phones[phoneid];
     199                int phoneid = IPC_GET_ARG1(*olddata);
     200                phone_t *phone = &TASK->phones[phoneid];
     201               
    199202                if (IPC_GET_RETVAL(answer->data) != EOK) {
    200203                        /*
     
    208211                        mutex_lock(&phone->lock);
    209212                        if (phone->state == IPC_PHONE_CONNECTED) {
    210                                 spinlock_lock(&phone->callee->lock);
     213                                irq_spinlock_lock(&phone->callee->lock, true);
    211214                                list_remove(&phone->link);
    212215                                phone->state = IPC_PHONE_SLAMMED;
    213                                 spinlock_unlock(&phone->callee->lock);
     216                                irq_spinlock_unlock(&phone->callee->lock, true);
    214217                        }
    215218                        mutex_unlock(&phone->lock);
    216219                }
    217220        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
    218                 phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
     221                phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
     222               
    219223                if (IPC_GET_RETVAL(answer->data) != EOK) {
    220224                        /*
     
    226230                        mutex_lock(&phone->lock);
    227231                        if (phone->state == IPC_PHONE_CONNECTED) {
    228                                 spinlock_lock(&phone->callee->lock);
     232                                irq_spinlock_lock(&phone->callee->lock, true);
    229233                                list_remove(&phone->link);
    230234                                phone->state = IPC_PHONE_SLAMMED;
    231                                 spinlock_unlock(&phone->callee->lock);
     235                                irq_spinlock_unlock(&phone->callee->lock, true);
    232236                        }
    233237                        mutex_unlock(&phone->lock);
    234238                }
    235239        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    236                 phoneid = IPC_GET_ARG5(*olddata);
     240                int phoneid = IPC_GET_ARG5(*olddata);
     241               
    237242                if (IPC_GET_RETVAL(answer->data) != EOK) {
    238243                        /* The connection was not accepted */
     
    254259                if (!IPC_GET_RETVAL(answer->data)) {
    255260                        /* Accepted, handle as_area receipt */
    256                         ipl_t ipl;
    257                         int rc;
    258                         as_t *as;
    259261                       
    260                         ipl = interrupts_disable();
    261                         spinlock_lock(&answer->sender->lock);
    262                         as = answer->sender->as;
    263                         spinlock_unlock(&answer->sender->lock);
    264                         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);
    265265                       
    266                         rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     266                        int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
    267267                            IPC_GET_ARG2(*olddata), AS,
    268268                            IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
     
    272272        } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) {
    273273                if (!IPC_GET_RETVAL(answer->data)) {
    274                         ipl_t ipl;
    275                         as_t *as;
    276                         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);
    277277                       
    278                         ipl = interrupts_disable();
    279                         spinlock_lock(&answer->sender->lock);
    280                         as = answer->sender->as;
    281                         spinlock_unlock(&answer->sender->lock);
    282                         interrupts_restore(ipl);
    283                        
    284                         rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     278                        int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
    285279                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    286280                            IPC_GET_ARG2(answer->data));
     
    301295                                 */
    302296                                IPC_SET_ARG1(answer->data, dst);
    303 
     297                               
    304298                                answer->buffer = malloc(size, 0);
    305299                                int rc = copy_from_uspace(answer->buffer,
     
    320314                if (!IPC_GET_RETVAL(answer->data)) {
    321315                        /* The recipient agreed to receive data. */
    322                         int rc;
    323                         uintptr_t dst;
    324                         size_t size;
    325                         size_t max_size;
    326 
    327                         dst = (uintptr_t)IPC_GET_ARG1(answer->data);
    328                         size = (size_t)IPC_GET_ARG2(answer->data);
    329                         max_size = (size_t)IPC_GET_ARG2(*olddata);
    330 
     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                       
    331320                        if (size <= max_size) {
    332                                 rc = copy_to_uspace((void *) dst,
     321                                int rc = copy_to_uspace((void *) dst,
    333322                                    answer->buffer, size);
    334323                                if (rc)
     
    341330                answer->buffer = NULL;
    342331        }
     332       
    343333        return 0;
    344334}
     
    352342                mutex_lock(&p2->lock);
    353343                mutex_lock(&p1->lock);
    354         } else {
     344        } else
    355345                mutex_lock(&p1->lock);
    356         }
    357346}
    358347
     
    366355/** Called before the request is sent.
    367356 *
    368  * @param call          Call structure with the request.
    369  * @param phone         Phone that the call will be sent through.
    370  *
    371  * @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 *
    372362 */
    373363static int request_preprocess(call_t *call, phone_t *phone)
    374364{
    375         int newphid;
    376         size_t size;
    377         uintptr_t src;
    378         int rc;
    379 
    380365        switch (IPC_GET_METHOD(call->data)) {
    381366        case IPC_M_CONNECTION_CLONE: {
    382367                phone_t *cloned_phone;
    383 
    384368                if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
    385369                        return ENOENT;
     370               
    386371                phones_lock(cloned_phone, phone);
    387 
     372               
    388373                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    389374                    phone->state != IPC_PHONE_CONNECTED) {
     
    391376                        return EINVAL;
    392377                }
     378               
    393379                /*
    394380                 * We can be pretty sure now that both tasks exist and we are
     
    396382                 * we are effectively preventing them from finishing their
    397383                 * potential cleanup.
     384                 *
    398385                 */
    399                 newphid = phone_alloc(phone->callee->task);
     386                int newphid = phone_alloc(phone->callee->task);
    400387                if (newphid < 0) {
    401388                        phones_unlock(cloned_phone, phone);
    402389                        return ELIMIT;
    403390                }
     391               
    404392                ipc_phone_connect(&phone->callee->task->phones[newphid],
    405393                    cloned_phone->callee);
    406394                phones_unlock(cloned_phone, phone);
     395               
    407396                /* Set the new phone for the callee. */
    408397                IPC_SET_ARG1(call->data, newphid);
     
    412401                IPC_SET_ARG5(call->data, (unative_t) phone);
    413402                break;
    414         case IPC_M_CONNECT_ME_TO:
    415                 newphid = phone_alloc(TASK);
     403        case IPC_M_CONNECT_ME_TO: {
     404                int newphid = phone_alloc(TASK);
    416405                if (newphid < 0)
    417406                        return ELIMIT;
     407               
    418408                /* Set arg5 for server */
    419409                IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
     
    421411                call->priv = newphid;
    422412                break;
    423         case IPC_M_SHARE_OUT:
    424                 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));
    425416                if (!size)
    426417                        return EPERM;
     418               
    427419                IPC_SET_ARG2(call->data, size);
    428420                break;
    429         case IPC_M_DATA_READ:
    430                 size = IPC_GET_ARG2(call->data);
     421        }
     422        case IPC_M_DATA_READ: {
     423                size_t size = IPC_GET_ARG2(call->data);
    431424                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    432425                        return ELIMIT;
     426               
    433427                break;
    434         case IPC_M_DATA_WRITE:
    435                 src = IPC_GET_ARG1(call->data);
    436                 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);
    437432               
    438433                if (size > DATA_XFER_LIMIT)
     
    440435               
    441436                call->buffer = (uint8_t *) malloc(size, 0);
    442                 rc = copy_from_uspace(call->buffer, (void *) src, size);
     437                int rc = copy_from_uspace(call->buffer, (void *) src, size);
    443438                if (rc != 0) {
    444439                        free(call->buffer);
    445440                        return rc;
    446441                }
     442               
    447443                break;
     444        }
    448445#ifdef CONFIG_UDEBUG
    449446        case IPC_M_DEBUG_ALL:
     
    453450                break;
    454451        }
     452       
    455453        return 0;
    456454}
     
    462460/** Do basic kernel processing of received call answer.
    463461 *
    464  * @param call          Call structure with the answer.
     462 * @param call Call structure with the answer.
     463 *
    465464 */
    466465static void process_answer(call_t *call)
     
    469468            (call->flags & IPC_CALL_FORWARDED))
    470469                IPC_SET_RETVAL(call->data, EFORWARD);
    471 
     470       
    472471        if (call->flags & IPC_CALL_CONN_ME_TO) {
    473472                if (IPC_GET_RETVAL(call->data))
     
    476475                        IPC_SET_ARG5(call->data, call->priv);
    477476        }
    478 
     477       
    479478        if (call->buffer) {
    480                 /* This must be an affirmative answer to IPC_M_DATA_READ. */
    481                 /* 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                 */
    482484                uintptr_t dst = IPC_GET_ARG1(call->data);
    483485                size_t size = IPC_GET_ARG2(call->data);
     
    492494/** Do basic kernel processing of received call request.
    493495 *
    494  * @param box           Destination answerbox structure.
    495  * @param call          Call structure with the request.
    496  *
    497  * @return              Return 0 if the call should be passed to userspace.
    498  *                      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 *
    499502 */
    500503static int process_request(answerbox_t *box, call_t *call)
    501504{
    502         int phoneid;
    503 
    504505        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    505                 phoneid = phone_alloc(TASK);
     506                int phoneid = phone_alloc(TASK);
    506507                if (phoneid < 0) { /* Failed to allocate phone */
    507508                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    509510                        return -1;
    510511                }
     512               
    511513                IPC_SET_ARG5(call->data, phoneid);
    512514        }
     515       
    513516        switch (IPC_GET_METHOD(call->data)) {
    514517        case IPC_M_DEBUG_ALL:
     
    517520                break;
    518521        }
     522       
    519523        return 0;
    520524}
     
    525529 * the generic function (i.e. sys_ipc_call_sync_slow()).
    526530 *
    527  * @param phoneid       Phone handle for the call.
    528  * @param method        Method of the call.
    529  * @param arg1          Service-defined payload argument.
    530  * @param arg2          Service-defined payload argument.
    531  * @param arg3          Service-defined payload argument.
    532  * @param data          Address of userspace structure where the reply call will
    533  *                      be stored.
    534  *
    535  * @return              Returns 0 on success.
    536  *                      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 *
    537542 */
    538543unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
    539544    unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    540545{
    541         call_t *call;
    542546        phone_t *phone;
    543         int res;
    544         int rc;
    545 
    546547        if (phone_get(phoneid, &phone) != EOK)
    547548                return ENOENT;
    548549
    549         call = ipc_call_alloc(0);
     550        call_t *call = ipc_call_alloc(0);
    550551        IPC_SET_METHOD(call->data, method);
    551552        IPC_SET_ARG1(call->data, arg1);
    552553        IPC_SET_ARG2(call->data, arg2);
    553554        IPC_SET_ARG3(call->data, arg3);
     555       
    554556        /*
    555557         * To achieve deterministic behavior, zero out arguments that are beyond
     
    558560        IPC_SET_ARG4(call->data, 0);
    559561        IPC_SET_ARG5(call->data, 0);
    560 
    561         if (!(res = request_preprocess(call, phone))) {
     562       
     563        int res = request_preprocess(call, phone);
     564        int rc;
     565       
     566        if (!res) {
    562567#ifdef CONFIG_UDEBUG
    563568                udebug_stoppable_begin();
     
    567572                udebug_stoppable_end();
    568573#endif
     574               
    569575                if (rc != EOK) {
    570576                        /* The call will be freed by ipc_cleanup(). */
    571577                        return rc;
    572578                }
     579               
    573580                process_answer(call);
    574 
    575         } else {
     581               
     582        } else
    576583                IPC_SET_RETVAL(call->data, res);
    577         }
     584       
    578585        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
    579586        ipc_call_free(call);
    580587        if (rc != 0)
    581588                return rc;
    582 
     589       
    583590        return 0;
    584591}
     
    586593/** Make a synchronous IPC call allowing to transmit the entire payload.
    587594 *
    588  * @param phoneid       Phone handle for the call.
    589  * @param question      Userspace address of call data with the request.
    590  * @param reply         Userspace address of call data where to store the
    591  *                      answer.
    592  *
    593  * @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 *
    594602 */
    595603unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
    596604    ipc_data_t *reply)
    597605{
    598         call_t *call;
    599606        phone_t *phone;
    600         int res;
    601         int rc;
    602 
    603607        if (phone_get(phoneid, &phone) != EOK)
    604608                return ENOENT;
    605609
    606         call = ipc_call_alloc(0);
    607         rc = copy_from_uspace(&call->data.args, &question->args,
     610        call_t *call = ipc_call_alloc(0);
     611        int rc = copy_from_uspace(&call->data.args, &question->args,
    608612            sizeof(call->data.args));
    609613        if (rc != 0) {
     
    611615                return (unative_t) rc;
    612616        }
    613 
    614 
    615         if (!(res = request_preprocess(call, phone))) {
     617       
     618        int res = request_preprocess(call, phone);
     619       
     620        if (!res) {
    616621#ifdef CONFIG_UDEBUG
    617622                udebug_stoppable_begin();
     
    621626                udebug_stoppable_end();
    622627#endif
     628               
    623629                if (rc != EOK) {
    624630                        /* The call will be freed by ipc_cleanup(). */
    625631                        return rc;
    626632                }
     633               
    627634                process_answer(call);
    628         } else 
     635        } else
    629636                IPC_SET_RETVAL(call->data, res);
    630 
     637       
    631638        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
    632639        ipc_call_free(call);
    633640        if (rc != 0)
    634641                return rc;
    635 
     642       
    636643        return 0;
    637644}
     
    639646/** Check that the task did not exceed the allowed limit of asynchronous calls.
    640647 *
    641  * @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 *
    642650 */
    643651static int check_call_limit(void)
     
    647655                return -1;
    648656        }
     657       
    649658        return 0;
    650659}
     
    655664 * the generic function sys_ipc_call_async_slow().
    656665 *
    657  * @param phoneid       Phone handle for the call.
    658  * @param method        Method of the call.
    659  * @param arg1          Service-defined payload argument.
    660  * @param arg2          Service-defined payload argument.
    661  * @param arg3          Service-defined payload argument.
    662  * @param arg4          Service-defined payload argument.
    663  *
    664  * @return              Return call hash on success.
    665  *                      Return IPC_CALLRET_FATAL in case of a fatal error and
    666  *                      IPC_CALLRET_TEMPORARY if there are too many pending
    667  *                      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 *
    668678 */
    669679unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
    670680    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    671681{
    672         call_t *call;
    673         phone_t *phone;
    674         int res;
    675 
    676682        if (check_call_limit())
    677683                return IPC_CALLRET_TEMPORARY;
    678 
     684       
     685        phone_t *phone;
    679686        if (phone_get(phoneid, &phone) != EOK)
    680687                return IPC_CALLRET_FATAL;
    681 
    682         call = ipc_call_alloc(0);
     688       
     689        call_t *call = ipc_call_alloc(0);
    683690        IPC_SET_METHOD(call->data, method);
    684691        IPC_SET_ARG1(call->data, arg1);
     
    686693        IPC_SET_ARG3(call->data, arg3);
    687694        IPC_SET_ARG4(call->data, arg4);
     695       
    688696        /*
    689697         * To achieve deterministic behavior, zero out arguments that are beyond
     
    691699         */
    692700        IPC_SET_ARG5(call->data, 0);
    693 
    694         if (!(res = request_preprocess(call, phone)))
     701       
     702        int res = request_preprocess(call, phone);
     703       
     704        if (!res)
    695705                ipc_call(phone, call);
    696706        else
    697707                ipc_backsend_err(phone, call, res);
    698 
     708       
    699709        return (unative_t) call;
    700710}
     
    702712/** Make an asynchronous IPC call allowing to transmit the entire payload.
    703713 *
    704  * @param phoneid       Phone handle for the call.
    705  * @param data          Userspace address of call data with the request.
    706  *
    707  * @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 *
    708719 */
    709720unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
    710721{
    711         call_t *call;
    712         phone_t *phone;
    713         int res;
    714         int rc;
    715 
    716722        if (check_call_limit())
    717723                return IPC_CALLRET_TEMPORARY;
    718 
     724       
     725        phone_t *phone;
    719726        if (phone_get(phoneid, &phone) != EOK)
    720727                return IPC_CALLRET_FATAL;
    721728
    722         call = ipc_call_alloc(0);
    723         rc = copy_from_uspace(&call->data.args, &data->args,
     729        call_t *call = ipc_call_alloc(0);
     730        int rc = copy_from_uspace(&call->data.args, &data->args,
    724731            sizeof(call->data.args));
    725732        if (rc != 0) {
     
    727734                return (unative_t) rc;
    728735        }
    729         if (!(res = request_preprocess(call, phone)))
     736       
     737        int res = request_preprocess(call, phone);
     738       
     739        if (!res)
    730740                ipc_call(phone, call);
    731741        else
    732742                ipc_backsend_err(phone, call, res);
    733 
     743       
    734744        return (unative_t) call;
    735745}
    736746
    737 /** Forward a received call to another destination - common code for both the
    738  * fast and the slow version.
    739  *
    740  * @param callid        Hash of the call to forward.
    741  * @param phoneid       Phone handle to use for forwarding.
    742  * @param method        New method to use for the forwarded call.
    743  * @param arg1          New value of the first argument for the forwarded call.
    744  * @param arg2          New value of the second argument for the forwarded call.
    745  * @param arg3          New value of the third argument for the forwarded call.
    746  * @param arg4          New value of the fourth argument for the forwarded call.
    747  * @param arg5          New value of the fifth argument for the forwarded call.
    748  * @param mode          Flags that specify mode of the forward operation.
    749  * @param slow          If true, arg3, arg4 and arg5 are considered. Otherwise
    750  *                      the function considers only the fast version arguments:
    751  *                      i.e. arg1 and arg2.
    752  *
    753  * @return              Return 0 on succes, otherwise return an error code.
    754  *
    755  * 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 *
    756768 */
    757769static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
    758770    unative_t method, unative_t arg1, unative_t arg2, unative_t arg3,
    759     unative_t arg4, unative_t arg5, int mode, bool slow)
    760 {
    761         call_t *call;
    762         phone_t *phone;
    763 
    764         call = get_call(callid);
     771    unative_t arg4, unative_t arg5, unsigned int mode, bool slow)
     772{
     773        call_t *call = get_call(callid);
    765774        if (!call)
    766775                return ENOENT;
    767776       
    768777        call->flags |= IPC_CALL_FORWARDED;
    769 
     778       
     779        phone_t *phone;
    770780        if (phone_get(phoneid, &phone) != EOK) {
    771781                IPC_SET_RETVAL(call->data, EFORWARD);
     
    773783                return ENOENT;
    774784        }
    775 
     785       
    776786        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
    777787                IPC_SET_RETVAL(call->data, EFORWARD);
     
    779789                return EPERM;
    780790        }
    781 
     791       
    782792        /*
    783793         * Userspace is not allowed to change method of system methods on
     
    790800                        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
    791801                                phone_dealloc(IPC_GET_ARG5(call->data));
    792 
     802                       
    793803                        IPC_SET_ARG1(call->data, method);
    794804                        IPC_SET_ARG2(call->data, arg1);
    795805                        IPC_SET_ARG3(call->data, arg2);
     806                       
    796807                        if (slow) {
    797808                                IPC_SET_ARG4(call->data, arg3);
     
    812823                }
    813824        }
    814 
     825       
    815826        return ipc_forward(call, phone, &TASK->answerbox, mode);
    816827}
    817828
    818829/** Forward a received call to another destination - fast version.
    819  *
    820  * @param callid        Hash of the call to forward.
    821  * @param phoneid       Phone handle to use for forwarding.
    822  * @param method        New method to use for the forwarded call.
    823  * @param arg1          New value of the first argument for the forwarded call.
    824  * @param arg2          New value of the second argument for the forwarded call.
    825  * @param mode          Flags that specify mode of the forward operation.
    826  *
    827  * @return              Return 0 on succes, otherwise return an error code.
    828830 *
    829831 * In case the original method is a system method, ARG1, ARG2 and ARG3 are
     
    833835 * is a set of immutable methods, for which the new method and arguments are not
    834836 * 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 *
    835847 */
    836848unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
    837     unative_t method, unative_t arg1, unative_t arg2, int mode)
     849    unative_t method, unative_t arg1, unative_t arg2, unsigned int mode)
    838850{
    839851        return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
     
    842854
    843855/** Forward a received call to another destination - slow version.
    844  *
    845  * @param callid        Hash of the call to forward.
    846  * @param phoneid       Phone handle to use for forwarding.
    847  * @param data          Userspace address of the new IPC data.
    848  * @param mode          Flags that specify mode of the forward operation.
    849  *
    850  * @return              Return 0 on succes, otherwise return an error code.
    851856 *
    852857 * This function is the slow verision of the sys_ipc_forward_fast interface.
     
    856861 * methods, it additionally stores the new value of arg3, arg4 and arg5,
    857862 * 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 *
    858871 */
    859872unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    860     ipc_data_t *data, int mode)
     873    ipc_data_t *data, unsigned int mode)
    861874{
    862875        ipc_data_t newdata;
    863         int rc;
    864 
    865         rc = copy_from_uspace(&newdata.args, &data->args,
     876        int rc = copy_from_uspace(&newdata.args, &data->args,
    866877            sizeof(newdata.args));
    867         if (rc != 0) 
     878        if (rc != 0)
    868879                return (unative_t) rc;
    869 
     880       
    870881        return sys_ipc_forward_common(callid, phoneid,
    871882            IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
     
    879890 * than the generic sys_ipc_answer().
    880891 *
    881  * @param callid        Hash of the call to be answered.
    882  * @param retval        Return value of the answer.
    883  * @param arg1          Service-defined return value.
    884  * @param arg2          Service-defined return value.
    885  * @param arg3          Service-defined return value.
    886  * @param arg4          Service-defined return value.
    887  *
    888  * @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 *
    889901 */
    890902unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    891903    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    892904{
    893         call_t *call;
    894         ipc_data_t saved_data;
    895         int saveddata = 0;
    896         int rc;
    897 
    898905        /* Do not answer notification callids */
    899906        if (callid & IPC_CALLID_NOTIFICATION)
    900907                return 0;
    901 
    902         call = get_call(callid);
     908       
     909        call_t *call = get_call(callid);
    903910        if (!call)
    904911                return ENOENT;
    905 
     912       
     913        ipc_data_t saved_data;
     914        bool saved;
     915       
    906916        if (answer_need_old(call)) {
    907917                memcpy(&saved_data, &call->data, sizeof(call->data));
    908                 saveddata = 1;
    909         }
    910 
     918                saved = true;
     919        } else
     920                saved = false;
     921       
    911922        IPC_SET_RETVAL(call->data, retval);
    912923        IPC_SET_ARG1(call->data, arg1);
     
    914925        IPC_SET_ARG3(call->data, arg3);
    915926        IPC_SET_ARG4(call->data, arg4);
     927       
    916928        /*
    917929         * To achieve deterministic behavior, zero out arguments that are beyond
     
    919931         */
    920932        IPC_SET_ARG5(call->data, 0);
    921         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    922 
     933        int rc = answer_preprocess(call, saved ? &saved_data : NULL);
     934       
    923935        ipc_answer(&TASK->answerbox, call);
    924936        return rc;
     
    927939/** Answer an IPC call.
    928940 *
    929  * @param callid        Hash of the call to be answered.
    930  * @param data          Userspace address of call data with the answer.
    931  *
    932  * @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 *
    933946 */
    934947unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data)
    935948{
    936         call_t *call;
    937         ipc_data_t saved_data;
    938         int saveddata = 0;
    939         int rc;
    940 
    941949        /* Do not answer notification callids */
    942950        if (callid & IPC_CALLID_NOTIFICATION)
    943951                return 0;
    944 
    945         call = get_call(callid);
     952       
     953        call_t *call = get_call(callid);
    946954        if (!call)
    947955                return ENOENT;
    948 
     956       
     957        ipc_data_t saved_data;
     958        bool saved;
     959       
    949960        if (answer_need_old(call)) {
    950961                memcpy(&saved_data, &call->data, sizeof(call->data));
    951                 saveddata = 1;
    952         }
    953         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,
    954967            sizeof(call->data.args));
    955968        if (rc != 0)
    956969                return rc;
    957 
    958         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     970       
     971        rc = answer_preprocess(call, saved ? &saved_data : NULL);
    959972       
    960973        ipc_answer(&TASK->answerbox, call);
    961 
    962974        return rc;
    963975}
     
    965977/** Hang up a phone.
    966978 *
    967  * @param               Phone handle of the phone to be hung up.
    968  *
    969  * @return              Return 0 on success or an error code.
     979 * @param Phone handle of the phone to be hung up.
     980 *
     981 * @return 0 on success or an error code.
     982 *
    970983 */
    971984unative_t sys_ipc_hangup(unative_t phoneid)
    972985{
    973986        phone_t *phone;
    974 
     987       
    975988        if (phone_get(phoneid, &phone) != EOK)
    976989                return ENOENT;
    977 
     990       
    978991        if (ipc_phone_hangup(phone))
    979992                return -1;
    980 
     993       
    981994        return 0;
    982995}
     
    984997/** Wait for an incoming IPC call or an answer.
    985998 *
    986  * @param calldata      Pointer to buffer where the call/answer data is stored.
    987  * @param usec          Timeout. See waitq_sleep_timeout() for explanation.
    988  * @param flags         Select mode of sleep operation. See waitq_sleep_timeout()
    989  *                      for explanation.
    990  *
    991  * @return              Hash of the call.
    992  *                      If IPC_CALLID_NOTIFICATION bit is set in the hash, the
    993  *                      call is a notification. IPC_CALLID_ANSWERED denotes an
    994  *                      answer.
    995  */
    996 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)
    9971012{
    9981013        call_t *call;
    999 
     1014       
    10001015restart:
    1001 
     1016       
    10021017#ifdef CONFIG_UDEBUG
    10031018        udebug_stoppable_begin();
    1004 #endif 
     1019#endif
     1020       
    10051021        call = ipc_wait_for_call(&TASK->answerbox, usec,
    10061022            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    1007 
     1023       
    10081024#ifdef CONFIG_UDEBUG
    10091025        udebug_stoppable_end();
    10101026#endif
     1027       
    10111028        if (!call)
    10121029                return 0;
    1013 
     1030       
    10141031        if (call->flags & IPC_CALL_NOTIF) {
    10151032                /* Set in_phone_hash to the interrupt counter */
     
    10171034               
    10181035                STRUCT_TO_USPACE(calldata, &call->data);
    1019 
     1036               
    10201037                ipc_call_free(call);
    10211038               
    10221039                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    10231040        }
    1024 
     1041       
    10251042        if (call->flags & IPC_CALL_ANSWERED) {
    10261043                process_answer(call);
    1027 
     1044               
    10281045                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10291046                        ipc_call_free(call);
     
    10371054                        atomic_dec(&TASK->active_calls);
    10381055                }
    1039 
     1056               
    10401057                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10411058                ipc_call_free(call);
    1042 
     1059               
    10431060                return ((unative_t) call) | IPC_CALLID_ANSWERED;
    10441061        }
    1045 
     1062       
    10461063        if (process_request(&TASK->answerbox, call))
    10471064                goto restart;
    1048 
     1065       
    10491066        /* Include phone address('id') of the caller in the request,
    10501067         * copy whole call->data, not only call->data.args */
     
    10551072                 */
    10561073                ipc_data_t saved_data;
    1057                 int saveddata = 0;
    1058 
     1074                bool saved;
     1075               
    10591076                if (answer_need_old(call)) {
    10601077                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1061                         saveddata = 1;
    1062                 }
     1078                        saved = true;
     1079                } else
     1080                        saved = false;
    10631081               
    10641082                IPC_SET_RETVAL(call->data, EPARTY);
    1065                 (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
     1083                (void) answer_preprocess(call, saved ? &saved_data : NULL);
    10661084                ipc_answer(&TASK->answerbox, call);
    10671085                return 0;
    10681086        }
    1069         return (unative_t)call;
    1070 }
    1071 
    1072 /** 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 */
    10731094unative_t sys_ipc_poke(void)
    10741095{
    1075         waitq_unsleep(&TASK->answerbox.wq);     
     1096        waitq_unsleep(&TASK->answerbox.wq);
    10761097        return EOK;
    10771098}
     
    10791100/** Connect an IRQ handler to a task.
    10801101 *
    1081  * @param inr           IRQ number.
    1082  * @param devno         Device number.
    1083  * @param method        Method to be associated with the notification.
    1084  * @param ucode         Uspace pointer to the top-half pseudocode.
    1085  *
    1086  * @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 *
    10871109 */
    10881110unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     
    10911113        if (!(cap_get(TASK) & CAP_IRQ_REG))
    10921114                return EPERM;
    1093 
     1115       
    10941116        return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
    10951117}
     
    10971119/** Disconnect an IRQ handler from a task.
    10981120 *
    1099  * @param inr           IRQ number.
    1100  * @param devno         Device number.
    1101  *
    1102  * @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 *
    11031126 */
    11041127unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
     
    11061129        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11071130                return EPERM;
    1108 
     1131       
    11091132        ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1110 
     1133       
    11111134        return 0;
    11121135}
     
    11141137#include <console/console.h>
    11151138
    1116 /**
    1117  * Syscall connect to a task by id.
    1118  *
    1119  * @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 *
    11201143 */
    11211144unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     
    11231146#ifdef CONFIG_UDEBUG
    11241147        sysarg64_t taskid_arg;
    1125         int rc;
    1126        
    1127         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));
    11281149        if (rc != 0)
    11291150                return (unative_t) rc;
    1130 
     1151       
    11311152        LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
    1132 
     1153       
    11331154        return ipc_connect_kbox(taskid_arg.value);
    11341155#else
Note: See TracChangeset for help on using the changeset viewer.