Ignore:
File:
1 edited

Legend:

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

    rfa3b8e4 rc9fff17  
    5656 * requests.
    5757 */
    58 #define DATA_XFER_LIMIT  (64 * 1024)
    59 
    60 #define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
     58#define DATA_XFER_LIMIT         (64 * 1024)
    6159
    6260/** Get phone from the current task by ID.
    6361 *
    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  *
     62 * @param phoneid       Phone ID.
     63 * @param phone         Place to store pointer to phone.
     64 * @return              EOK on success, EINVAL if ID is invalid.
    6965 */
    7066static int phone_get(unative_t phoneid, phone_t **phone)
     
    7268        if (phoneid >= IPC_MAX_PHONES)
    7369                return EINVAL;
    74        
     70
    7571        *phone = &TASK->phones[phoneid];
    7672        return EOK;
    7773}
    7874
     75#define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
     76
    7977/** Decide if the method is a system method.
    8078 *
    81  * @param method Method to be decided.
    82  *
    83  * @return true if the method is a system method.
    84  *
    85  */
    86 static inline bool method_is_system(unative_t method)
     79 * @param method        Method to be decided.
     80 *
     81 * @return              Return 1 if the method is a system method.
     82 *                      Otherwise return 0.
     83 */
     84static inline int method_is_system(unative_t method)
    8785{
    8886        if (method <= IPC_M_LAST_SYSTEM)
    89                 return true;
    90        
    91         return false;
     87                return 1;
     88        return 0;
    9289}
    9390
     
    9794 *   it is useless
    9895 *
    99  * @param method Method to be decided.
    100  *
    101  * @return true if the method is forwardable.
    102  *
    103  */
    104 static inline bool method_is_forwardable(unative_t method)
     96 * @param method        Method to be decided.
     97 *
     98 * @return              Return 1 if the method is forwardable.
     99 *                      Otherwise return 0.
     100 */
     101static inline int method_is_forwardable(unative_t method)
    105102{
    106103        switch (method) {
     
    109106        case IPC_M_PHONE_HUNGUP:
    110107                /* This message is meant only for the original recipient. */
    111                 return false;
     108                return 0;
    112109        default:
    113                 return true;
     110                return 1;
    114111        }
    115112}
     
    119116 * - some system messages may be forwarded but their content cannot be altered
    120117 *
    121  * @param method Method to be decided.
    122  *
    123  * @return true if the method is immutable on forward.
    124  *
    125  */
    126 static inline bool method_is_immutable(unative_t method)
     118 * @param method        Method to be decided.
     119 *
     120 * @return              Return 1 if the method is immutable on forward.
     121 *                      Otherwise return 0.
     122 */
     123static inline int method_is_immutable(unative_t method)
    127124{
    128125        switch (method) {
     
    131128        case IPC_M_DATA_WRITE:
    132129        case IPC_M_DATA_READ:
    133                 return true;
     130                return 1;
    134131        default:
    135                 return false;
     132                return 0;
    136133        }
    137134}
     
    145142 * for answer_preprocess().
    146143 *
    147  * @param call Call structure to be decided.
    148  *
    149  * @return true if the old call contents should be saved.
    150  *
    151  */
    152 static inline bool answer_need_old(call_t *call)
     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 */
     149static inline int answer_need_old(call_t *call)
    153150{
    154151        switch (IPC_GET_METHOD(call->data)) {
     
    161158        case IPC_M_DATA_WRITE:
    162159        case IPC_M_DATA_READ:
    163                 return true;
     160                return 1;
    164161        default:
    165                 return false;
     162                return 0;
    166163        }
    167164}
     
    171168 * This function is called directly after sys_ipc_answer().
    172169 *
    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  *
     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.
    178174 */
    179175static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    180176{
     177        int phoneid;
     178
    181179        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    182180                /* In case of forward, hangup the forwared phone,
     
    184182                 */
    185183                mutex_lock(&answer->data.phone->lock);
    186                 irq_spinlock_lock(&TASK->answerbox.lock, true);
     184                spinlock_lock(&TASK->answerbox.lock);
    187185                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    188186                        list_remove(&answer->data.phone->link);
    189187                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    190188                }
    191                 irq_spinlock_unlock(&TASK->answerbox.lock, true);
     189                spinlock_unlock(&TASK->answerbox.lock);
    192190                mutex_unlock(&answer->data.phone->lock);
    193191        }
    194        
     192
    195193        if (!olddata)
    196194                return 0;
    197        
     195
    198196        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
    199                 int phoneid = IPC_GET_ARG1(*olddata);
    200                 phone_t *phone = &TASK->phones[phoneid];
    201                
     197                phoneid = IPC_GET_ARG1(*olddata);
     198                phone_t *phone = &TASK->phones[phoneid];
    202199                if (IPC_GET_RETVAL(answer->data) != EOK) {
    203200                        /*
     
    211208                        mutex_lock(&phone->lock);
    212209                        if (phone->state == IPC_PHONE_CONNECTED) {
    213                                 irq_spinlock_lock(&phone->callee->lock, true);
     210                                spinlock_lock(&phone->callee->lock);
    214211                                list_remove(&phone->link);
    215212                                phone->state = IPC_PHONE_SLAMMED;
    216                                 irq_spinlock_unlock(&phone->callee->lock, true);
     213                                spinlock_unlock(&phone->callee->lock);
    217214                        }
    218215                        mutex_unlock(&phone->lock);
    219216                }
    220217        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
    221                 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
    222                
     218                phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
    223219                if (IPC_GET_RETVAL(answer->data) != EOK) {
    224220                        /*
     
    230226                        mutex_lock(&phone->lock);
    231227                        if (phone->state == IPC_PHONE_CONNECTED) {
    232                                 irq_spinlock_lock(&phone->callee->lock, true);
     228                                spinlock_lock(&phone->callee->lock);
    233229                                list_remove(&phone->link);
    234230                                phone->state = IPC_PHONE_SLAMMED;
    235                                 irq_spinlock_unlock(&phone->callee->lock, true);
     231                                spinlock_unlock(&phone->callee->lock);
    236232                        }
    237233                        mutex_unlock(&phone->lock);
    238234                }
    239235        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    240                 int phoneid = IPC_GET_ARG5(*olddata);
    241                
     236                phoneid = IPC_GET_ARG5(*olddata);
    242237                if (IPC_GET_RETVAL(answer->data) != EOK) {
    243238                        /* The connection was not accepted */
     
    259254                if (!IPC_GET_RETVAL(answer->data)) {
    260255                        /* Accepted, handle as_area receipt */
     256                        ipl_t ipl;
     257                        int rc;
     258                        as_t *as;
    261259                       
    262                         irq_spinlock_lock(&answer->sender->lock, true);
    263                         as_t *as = answer->sender->as;
    264                         irq_spinlock_unlock(&answer->sender->lock, true);
     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);
    265265                       
    266                         int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     266                        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                         irq_spinlock_lock(&answer->sender->lock, true);
    275                         as_t *as = answer->sender->as;
    276                         irq_spinlock_unlock(&answer->sender->lock, true);
     274                        ipl_t ipl;
     275                        as_t *as;
     276                        int rc;
    277277                       
    278                         int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     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),
    279285                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    280286                            IPC_GET_ARG2(answer->data));
     
    295301                                 */
    296302                                IPC_SET_ARG1(answer->data, dst);
    297                                
     303
    298304                                answer->buffer = malloc(size, 0);
    299305                                int rc = copy_from_uspace(answer->buffer,
     
    314320                if (!IPC_GET_RETVAL(answer->data)) {
    315321                        /* The recipient agreed to receive data. */
    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                        
     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
    320331                        if (size <= max_size) {
    321                                 int rc = copy_to_uspace((void *) dst,
     332                                rc = copy_to_uspace((void *) dst,
    322333                                    answer->buffer, size);
    323334                                if (rc)
     
    330341                answer->buffer = NULL;
    331342        }
    332        
    333343        return 0;
    334344}
     
    342352                mutex_lock(&p2->lock);
    343353                mutex_lock(&p1->lock);
    344         } else
     354        } else {
    345355                mutex_lock(&p1->lock);
     356        }
    346357}
    347358
     
    355366/** Called before the request is sent.
    356367 *
    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  *
     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.
    362372 */
    363373static int request_preprocess(call_t *call, phone_t *phone)
    364374{
     375        int newphid;
     376        size_t size;
     377        uintptr_t src;
     378        int rc;
     379
    365380        switch (IPC_GET_METHOD(call->data)) {
    366381        case IPC_M_CONNECTION_CLONE: {
    367382                phone_t *cloned_phone;
     383
    368384                if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
    369385                        return ENOENT;
    370                
    371386                phones_lock(cloned_phone, phone);
    372                
     387
    373388                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    374389                    phone->state != IPC_PHONE_CONNECTED) {
     
    376391                        return EINVAL;
    377392                }
    378                
    379393                /*
    380394                 * We can be pretty sure now that both tasks exist and we are
     
    382396                 * we are effectively preventing them from finishing their
    383397                 * potential cleanup.
    384                  *
    385398                 */
    386                 int newphid = phone_alloc(phone->callee->task);
     399                newphid = phone_alloc(phone->callee->task);
    387400                if (newphid < 0) {
    388401                        phones_unlock(cloned_phone, phone);
    389402                        return ELIMIT;
    390403                }
    391                
    392404                ipc_phone_connect(&phone->callee->task->phones[newphid],
    393405                    cloned_phone->callee);
    394406                phones_unlock(cloned_phone, phone);
    395                
    396407                /* Set the new phone for the callee. */
    397408                IPC_SET_ARG1(call->data, newphid);
     
    401412                IPC_SET_ARG5(call->data, (unative_t) phone);
    402413                break;
    403         case IPC_M_CONNECT_ME_TO: {
    404                 int newphid = phone_alloc(TASK);
     414        case IPC_M_CONNECT_ME_TO:
     415                newphid = phone_alloc(TASK);
    405416                if (newphid < 0)
    406417                        return ELIMIT;
    407                
    408418                /* Set arg5 for server */
    409419                IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
     
    411421                call->priv = newphid;
    412422                break;
    413         }
    414         case IPC_M_SHARE_OUT: {
    415                 size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
     423        case IPC_M_SHARE_OUT:
     424                size = as_area_get_size(IPC_GET_ARG1(call->data));
    416425                if (!size)
    417426                        return EPERM;
    418                
    419427                IPC_SET_ARG2(call->data, size);
    420428                break;
    421         }
    422         case IPC_M_DATA_READ: {
    423                 size_t size = IPC_GET_ARG2(call->data);
     429        case IPC_M_DATA_READ:
     430                size = IPC_GET_ARG2(call->data);
    424431                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    425432                        return ELIMIT;
    426                
    427433                break;
    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);
     434        case IPC_M_DATA_WRITE:
     435                src = IPC_GET_ARG1(call->data);
     436                size = IPC_GET_ARG2(call->data);
    432437               
    433438                if (size > DATA_XFER_LIMIT)
     
    435440               
    436441                call->buffer = (uint8_t *) malloc(size, 0);
    437                 int rc = copy_from_uspace(call->buffer, (void *) src, size);
     442                rc = copy_from_uspace(call->buffer, (void *) src, size);
    438443                if (rc != 0) {
    439444                        free(call->buffer);
    440445                        return rc;
    441446                }
    442                
    443447                break;
    444         }
    445448#ifdef CONFIG_UDEBUG
    446449        case IPC_M_DEBUG_ALL:
     
    450453                break;
    451454        }
    452        
    453455        return 0;
    454456}
     
    460462/** Do basic kernel processing of received call answer.
    461463 *
    462  * @param call Call structure with the answer.
    463  *
     464 * @param call          Call structure with the answer.
    464465 */
    465466static void process_answer(call_t *call)
     
    468469            (call->flags & IPC_CALL_FORWARDED))
    469470                IPC_SET_RETVAL(call->data, EFORWARD);
    470        
     471
    471472        if (call->flags & IPC_CALL_CONN_ME_TO) {
    472473                if (IPC_GET_RETVAL(call->data))
     
    475476                        IPC_SET_ARG5(call->data, call->priv);
    476477        }
    477        
     478
    478479        if (call->buffer) {
    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                  */
     480                /* This must be an affirmative answer to IPC_M_DATA_READ. */
     481                /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
    484482                uintptr_t dst = IPC_GET_ARG1(call->data);
    485483                size_t size = IPC_GET_ARG2(call->data);
     
    494492/** Do basic kernel processing of received call request.
    495493 *
    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  *
     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.
    502499 */
    503500static int process_request(answerbox_t *box, call_t *call)
    504501{
     502        int phoneid;
     503
    505504        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    506                 int phoneid = phone_alloc(TASK);
     505                phoneid = phone_alloc(TASK);
    507506                if (phoneid < 0) { /* Failed to allocate phone */
    508507                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    510509                        return -1;
    511510                }
    512                
    513511                IPC_SET_ARG5(call->data, phoneid);
    514512        }
    515        
    516513        switch (IPC_GET_METHOD(call->data)) {
    517514        case IPC_M_DEBUG_ALL:
     
    520517                break;
    521518        }
    522        
    523519        return 0;
    524520}
     
    529525 * the generic function (i.e. sys_ipc_call_sync_slow()).
    530526 *
    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  *
     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.
    542537 */
    543538unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
    544539    unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    545540{
     541        call_t *call;
    546542        phone_t *phone;
     543        int res;
     544        int rc;
     545
    547546        if (phone_get(phoneid, &phone) != EOK)
    548547                return ENOENT;
    549548
    550         call_t *call = ipc_call_alloc(0);
     549        call = ipc_call_alloc(0);
    551550        IPC_SET_METHOD(call->data, method);
    552551        IPC_SET_ARG1(call->data, arg1);
    553552        IPC_SET_ARG2(call->data, arg2);
    554553        IPC_SET_ARG3(call->data, arg3);
    555        
    556554        /*
    557555         * To achieve deterministic behavior, zero out arguments that are beyond
     
    560558        IPC_SET_ARG4(call->data, 0);
    561559        IPC_SET_ARG5(call->data, 0);
    562        
    563         int res = request_preprocess(call, phone);
    564         int rc;
    565        
    566         if (!res) {
     560
     561        if (!(res = request_preprocess(call, phone))) {
    567562#ifdef CONFIG_UDEBUG
    568563                udebug_stoppable_begin();
     
    572567                udebug_stoppable_end();
    573568#endif
    574                
    575569                if (rc != EOK) {
    576570                        /* The call will be freed by ipc_cleanup(). */
    577571                        return rc;
    578572                }
    579                
    580573                process_answer(call);
    581                
    582         } else
     574
     575        } else {
    583576                IPC_SET_RETVAL(call->data, res);
    584        
     577        }
    585578        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
    586579        ipc_call_free(call);
    587580        if (rc != 0)
    588581                return rc;
    589        
     582
    590583        return 0;
    591584}
     
    593586/** Make a synchronous IPC call allowing to transmit the entire payload.
    594587 *
    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  *
     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.
    602594 */
    603595unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
    604596    ipc_data_t *reply)
    605597{
     598        call_t *call;
    606599        phone_t *phone;
     600        int res;
     601        int rc;
     602
    607603        if (phone_get(phoneid, &phone) != EOK)
    608604                return ENOENT;
    609605
    610         call_t *call = ipc_call_alloc(0);
    611         int rc = copy_from_uspace(&call->data.args, &question->args,
     606        call = ipc_call_alloc(0);
     607        rc = copy_from_uspace(&call->data.args, &question->args,
    612608            sizeof(call->data.args));
    613609        if (rc != 0) {
     
    615611                return (unative_t) rc;
    616612        }
    617        
    618         int res = request_preprocess(call, phone);
    619        
    620         if (!res) {
     613
     614
     615        if (!(res = request_preprocess(call, phone))) {
    621616#ifdef CONFIG_UDEBUG
    622617                udebug_stoppable_begin();
     
    626621                udebug_stoppable_end();
    627622#endif
    628                
    629623                if (rc != EOK) {
    630624                        /* The call will be freed by ipc_cleanup(). */
    631625                        return rc;
    632626                }
    633                
    634627                process_answer(call);
    635         } else
     628        } else 
    636629                IPC_SET_RETVAL(call->data, res);
    637        
     630
    638631        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
    639632        ipc_call_free(call);
    640633        if (rc != 0)
    641634                return rc;
    642        
     635
    643636        return 0;
    644637}
     
    646639/** Check that the task did not exceed the allowed limit of asynchronous calls.
    647640 *
    648  * @return 0 if limit not reached or -1 if limit exceeded.
    649  *
     641 * @return              Return 0 if limit not reached or -1 if limit exceeded.
    650642 */
    651643static int check_call_limit(void)
     
    655647                return -1;
    656648        }
    657        
    658649        return 0;
    659650}
     
    664655 * the generic function sys_ipc_call_async_slow().
    665656 *
    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  *
     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.
    678668 */
    679669unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
    680670    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    681671{
     672        call_t *call;
     673        phone_t *phone;
     674        int res;
     675
    682676        if (check_call_limit())
    683677                return IPC_CALLRET_TEMPORARY;
    684        
    685         phone_t *phone;
     678
    686679        if (phone_get(phoneid, &phone) != EOK)
    687680                return IPC_CALLRET_FATAL;
    688        
    689         call_t *call = ipc_call_alloc(0);
     681
     682        call = ipc_call_alloc(0);
    690683        IPC_SET_METHOD(call->data, method);
    691684        IPC_SET_ARG1(call->data, arg1);
     
    693686        IPC_SET_ARG3(call->data, arg3);
    694687        IPC_SET_ARG4(call->data, arg4);
    695        
    696688        /*
    697689         * To achieve deterministic behavior, zero out arguments that are beyond
     
    699691         */
    700692        IPC_SET_ARG5(call->data, 0);
    701        
    702         int res = request_preprocess(call, phone);
    703        
    704         if (!res)
     693
     694        if (!(res = request_preprocess(call, phone)))
    705695                ipc_call(phone, call);
    706696        else
    707697                ipc_backsend_err(phone, call, res);
    708        
     698
    709699        return (unative_t) call;
    710700}
     
    712702/** Make an asynchronous IPC call allowing to transmit the entire payload.
    713703 *
    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  *
     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().
    719708 */
    720709unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
    721710{
     711        call_t *call;
     712        phone_t *phone;
     713        int res;
     714        int rc;
     715
    722716        if (check_call_limit())
    723717                return IPC_CALLRET_TEMPORARY;
    724        
    725         phone_t *phone;
     718
    726719        if (phone_get(phoneid, &phone) != EOK)
    727720                return IPC_CALLRET_FATAL;
    728721
    729         call_t *call = ipc_call_alloc(0);
    730         int rc = copy_from_uspace(&call->data.args, &data->args,
     722        call = ipc_call_alloc(0);
     723        rc = copy_from_uspace(&call->data.args, &data->args,
    731724            sizeof(call->data.args));
    732725        if (rc != 0) {
     
    734727                return (unative_t) rc;
    735728        }
    736        
    737         int res = request_preprocess(call, phone);
    738        
    739         if (!res)
     729        if (!(res = request_preprocess(call, phone)))
    740730                ipc_call(phone, call);
    741731        else
    742732                ipc_backsend_err(phone, call, res);
    743        
     733
    744734        return (unative_t) call;
    745735}
    746736
    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  *
     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
    768756 */
    769757static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
    770758    unative_t method, unative_t arg1, unative_t arg2, unative_t arg3,
    771     unative_t arg4, unative_t arg5, unsigned int mode, bool slow)
    772 {
    773         call_t *call = get_call(callid);
     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);
    774765        if (!call)
    775766                return ENOENT;
    776767       
    777768        call->flags |= IPC_CALL_FORWARDED;
    778        
    779         phone_t *phone;
     769
    780770        if (phone_get(phoneid, &phone) != EOK) {
    781771                IPC_SET_RETVAL(call->data, EFORWARD);
     
    783773                return ENOENT;
    784774        }
    785        
     775
    786776        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
    787777                IPC_SET_RETVAL(call->data, EFORWARD);
     
    789779                return EPERM;
    790780        }
    791        
     781
    792782        /*
    793783         * Userspace is not allowed to change method of system methods on
     
    800790                        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
    801791                                phone_dealloc(IPC_GET_ARG5(call->data));
    802                        
     792
    803793                        IPC_SET_ARG1(call->data, method);
    804794                        IPC_SET_ARG2(call->data, arg1);
    805795                        IPC_SET_ARG3(call->data, arg2);
    806                        
    807796                        if (slow) {
    808797                                IPC_SET_ARG4(call->data, arg3);
     
    823812                }
    824813        }
    825        
     814
    826815        return ipc_forward(call, phone, &TASK->answerbox, mode);
    827816}
    828817
    829818/** 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.
    830828 *
    831829 * In case the original method is a system method, ARG1, ARG2 and ARG3 are
     
    835833 * is a set of immutable methods, for which the new method and arguments are not
    836834 * 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  *
    847835 */
    848836unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
    849     unative_t method, unative_t arg1, unative_t arg2, unsigned int mode)
     837    unative_t method, unative_t arg1, unative_t arg2, int mode)
    850838{
    851839        return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
     
    854842
    855843/** 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.
    856851 *
    857852 * This function is the slow verision of the sys_ipc_forward_fast interface.
     
    861856 * methods, it additionally stores the new value of arg3, arg4 and arg5,
    862857 * 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  *
    871858 */
    872859unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    873     ipc_data_t *data, unsigned int mode)
     860    ipc_data_t *data, int mode)
    874861{
    875862        ipc_data_t newdata;
    876         int rc = copy_from_uspace(&newdata.args, &data->args,
     863        int rc;
     864
     865        rc = copy_from_uspace(&newdata.args, &data->args,
    877866            sizeof(newdata.args));
    878         if (rc != 0)
     867        if (rc != 0) 
    879868                return (unative_t) rc;
    880        
     869
    881870        return sys_ipc_forward_common(callid, phoneid,
    882871            IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
     
    890879 * than the generic sys_ipc_answer().
    891880 *
    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  *
     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.   
    901889 */
    902890unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    903891    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    904892{
     893        call_t *call;
     894        ipc_data_t saved_data;
     895        int saveddata = 0;
     896        int rc;
     897
    905898        /* Do not answer notification callids */
    906899        if (callid & IPC_CALLID_NOTIFICATION)
    907900                return 0;
    908        
    909         call_t *call = get_call(callid);
     901
     902        call = get_call(callid);
    910903        if (!call)
    911904                return ENOENT;
    912        
    913         ipc_data_t saved_data;
    914         bool saved;
    915        
     905
    916906        if (answer_need_old(call)) {
    917907                memcpy(&saved_data, &call->data, sizeof(call->data));
    918                 saved = true;
    919         } else
    920                 saved = false;
    921        
     908                saveddata = 1;
     909        }
     910
    922911        IPC_SET_RETVAL(call->data, retval);
    923912        IPC_SET_ARG1(call->data, arg1);
     
    925914        IPC_SET_ARG3(call->data, arg3);
    926915        IPC_SET_ARG4(call->data, arg4);
    927        
    928916        /*
    929917         * To achieve deterministic behavior, zero out arguments that are beyond
     
    931919         */
    932920        IPC_SET_ARG5(call->data, 0);
    933         int rc = answer_preprocess(call, saved ? &saved_data : NULL);
    934        
     921        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     922
    935923        ipc_answer(&TASK->answerbox, call);
    936924        return rc;
     
    939927/** Answer an IPC call.
    940928 *
    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  *
     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.
    946933 */
    947934unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data)
    948935{
     936        call_t *call;
     937        ipc_data_t saved_data;
     938        int saveddata = 0;
     939        int rc;
     940
    949941        /* Do not answer notification callids */
    950942        if (callid & IPC_CALLID_NOTIFICATION)
    951943                return 0;
    952        
    953         call_t *call = get_call(callid);
     944
     945        call = get_call(callid);
    954946        if (!call)
    955947                return ENOENT;
    956        
    957         ipc_data_t saved_data;
    958         bool saved;
    959        
     948
    960949        if (answer_need_old(call)) {
    961950                memcpy(&saved_data, &call->data, sizeof(call->data));
    962                 saved = true;
    963         } else
    964                 saved = false;
    965        
    966         int rc = copy_from_uspace(&call->data.args, &data->args,
     951                saveddata = 1;
     952        }
     953        rc = copy_from_uspace(&call->data.args, &data->args,
    967954            sizeof(call->data.args));
    968955        if (rc != 0)
    969956                return rc;
    970        
    971         rc = answer_preprocess(call, saved ? &saved_data : NULL);
     957
     958        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    972959       
    973960        ipc_answer(&TASK->answerbox, call);
     961
    974962        return rc;
    975963}
     
    977965/** Hang up a phone.
    978966 *
    979  * @param Phone handle of the phone to be hung up.
    980  *
    981  * @return 0 on success or an error code.
    982  *
     967 * @param               Phone handle of the phone to be hung up.
     968 *
     969 * @return              Return 0 on success or an error code.
    983970 */
    984971unative_t sys_ipc_hangup(unative_t phoneid)
    985972{
    986973        phone_t *phone;
    987        
     974
    988975        if (phone_get(phoneid, &phone) != EOK)
    989976                return ENOENT;
    990        
     977
    991978        if (ipc_phone_hangup(phone))
    992979                return -1;
    993        
     980
    994981        return 0;
    995982}
     
    997984/** Wait for an incoming IPC call or an answer.
    998985 *
    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  */
    1010 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
    1011     unsigned int flags)
     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 */
     996unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
    1012997{
    1013998        call_t *call;
    1014        
     999
    10151000restart:
    1016        
     1001
    10171002#ifdef CONFIG_UDEBUG
    10181003        udebug_stoppable_begin();
    1019 #endif
    1020        
     1004#endif 
    10211005        call = ipc_wait_for_call(&TASK->answerbox, usec,
    10221006            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    1023        
     1007
    10241008#ifdef CONFIG_UDEBUG
    10251009        udebug_stoppable_end();
    10261010#endif
    1027        
    10281011        if (!call)
    10291012                return 0;
    1030        
     1013
    10311014        if (call->flags & IPC_CALL_NOTIF) {
    10321015                /* Set in_phone_hash to the interrupt counter */
     
    10341017               
    10351018                STRUCT_TO_USPACE(calldata, &call->data);
    1036                
     1019
    10371020                ipc_call_free(call);
    10381021               
    10391022                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    10401023        }
    1041        
     1024
    10421025        if (call->flags & IPC_CALL_ANSWERED) {
    10431026                process_answer(call);
    1044                
     1027
    10451028                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10461029                        ipc_call_free(call);
     
    10541037                        atomic_dec(&TASK->active_calls);
    10551038                }
    1056                
     1039
    10571040                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10581041                ipc_call_free(call);
    1059                
     1042
    10601043                return ((unative_t) call) | IPC_CALLID_ANSWERED;
    10611044        }
    1062        
     1045
    10631046        if (process_request(&TASK->answerbox, call))
    10641047                goto restart;
    1065        
     1048
    10661049        /* Include phone address('id') of the caller in the request,
    10671050         * copy whole call->data, not only call->data.args */
     
    10721055                 */
    10731056                ipc_data_t saved_data;
    1074                 bool saved;
    1075                
     1057                int saveddata = 0;
     1058
    10761059                if (answer_need_old(call)) {
    10771060                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1078                         saved = true;
    1079                 } else
    1080                         saved = false;
     1061                        saveddata = 1;
     1062                }
    10811063               
    10821064                IPC_SET_RETVAL(call->data, EPARTY);
    1083                 (void) answer_preprocess(call, saved ? &saved_data : NULL);
     1065                (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
    10841066                ipc_answer(&TASK->answerbox, call);
    10851067                return 0;
    10861068        }
    1087        
    1088         return (unative_t) call;
    1089 }
    1090 
    1091 /** Interrupt one thread from sys_ipc_wait_for_call().
    1092  *
    1093  */
     1069        return (unative_t)call;
     1070}
     1071
     1072/** Interrupt one thread from sys_ipc_wait_for_call(). */
    10941073unative_t sys_ipc_poke(void)
    10951074{
    1096         waitq_unsleep(&TASK->answerbox.wq);
     1075        waitq_unsleep(&TASK->answerbox.wq);     
    10971076        return EOK;
    10981077}
     
    11001079/** Connect an IRQ handler to a task.
    11011080 *
    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  *
     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().
    11091087 */
    11101088unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     
    11131091        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11141092                return EPERM;
    1115        
     1093
    11161094        return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
    11171095}
     
    11191097/** Disconnect an IRQ handler from a task.
    11201098 *
    1121  * @param inr   IRQ number.
    1122  * @param devno Device number.
    1123  *
    1124  * @return Zero on success or EPERM on error.
    1125  *
     1099 * @param inr           IRQ number.
     1100 * @param devno         Device number.
     1101 *
     1102 * @return              Zero on success or EPERM on error..
    11261103 */
    11271104unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
     
    11291106        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11301107                return EPERM;
    1131        
     1108
    11321109        ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1133        
     1110
    11341111        return 0;
    11351112}
     
    11371114#include <console/console.h>
    11381115
    1139 /** Syscall connect to a task by id.
    1140  *
    1141  * @return Phone id on success, or negative error code.
    1142  *
     1116/**
     1117 * Syscall connect to a task by id.
     1118 *
     1119 * @return              Phone id on success, or negative error code.
    11431120 */
    11441121unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     
    11461123#ifdef CONFIG_UDEBUG
    11471124        sysarg64_t taskid_arg;
    1148         int rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
     1125        int rc;
     1126       
     1127        rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    11491128        if (rc != 0)
    11501129                return (unative_t) rc;
    1151        
    1152         LOG("sys_ipc_connect_kbox(%" PRIu64 ")", taskid_arg.value);
    1153        
     1130
     1131        LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
     1132
    11541133        return ipc_connect_kbox(taskid_arg.value);
    11551134#else
Note: See TracChangeset for help on using the changeset viewer.