Ignore:
File:
1 edited

Legend:

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

    rfa3b8e4 r20c7c40  
    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)))
    61 
    62 /** Get phone from the current task by ID.
    63  *
    64  * @param phoneid Phone ID.
    65  * @param phone   Place to store pointer to phone.
    66  *
    67  * @return EOK on success, EINVAL if ID is invalid.
    68  *
    69  */
    70 static int phone_get(unative_t phoneid, phone_t **phone)
    71 {
    72         if (phoneid >= IPC_MAX_PHONES)
    73                 return EINVAL;
    74        
    75         *phone = &TASK->phones[phoneid];
    76         return EOK;
    77 }
     58#define DATA_XFER_LIMIT         (64 * 1024)
     59
     60#define GET_CHECK_PHONE(phone, phoneid, err) \
     61{ \
     62        if (phoneid > IPC_MAX_PHONES) { \
     63                err \
     64        } \
     65        phone = &TASK->phones[phoneid]; \
     66}
     67
     68#define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
    7869
    7970/** Decide if the method is a system method.
    8071 *
    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)
     72 * @param method        Method to be decided.
     73 *
     74 * @return              Return 1 if the method is a system method.
     75 *                      Otherwise return 0.
     76 */
     77static inline int method_is_system(unative_t method)
    8778{
    8879        if (method <= IPC_M_LAST_SYSTEM)
    89                 return true;
    90        
    91         return false;
     80                return 1;
     81        return 0;
    9282}
    9383
     
    9787 *   it is useless
    9888 *
    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)
     89 * @param method        Method to be decided.
     90 *
     91 * @return              Return 1 if the method is forwardable.
     92 *                      Otherwise return 0.
     93 */
     94static inline int method_is_forwardable(unative_t method)
    10595{
    10696        switch (method) {
     
    10999        case IPC_M_PHONE_HUNGUP:
    110100                /* This message is meant only for the original recipient. */
    111                 return false;
     101                return 0;
    112102        default:
    113                 return true;
     103                return 1;
    114104        }
    115105}
     
    119109 * - some system messages may be forwarded but their content cannot be altered
    120110 *
    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)
     111 * @param method        Method to be decided.
     112 *
     113 * @return              Return 1 if the method is immutable on forward.
     114 *                      Otherwise return 0.
     115 */
     116static inline int method_is_immutable(unative_t method)
    127117{
    128118        switch (method) {
     
    131121        case IPC_M_DATA_WRITE:
    132122        case IPC_M_DATA_READ:
    133                 return true;
     123                return 1;
    134124        default:
    135                 return false;
     125                return 0;
    136126        }
    137127}
     
    145135 * for answer_preprocess().
    146136 *
    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)
     137 * @param call          Call structure to be decided.
     138 *
     139 * @return              Return 1 if the old call contents should be saved.
     140 *                      Return 0 otherwise.
     141 */
     142static inline int answer_need_old(call_t *call)
    153143{
    154144        switch (IPC_GET_METHOD(call->data)) {
     
    161151        case IPC_M_DATA_WRITE:
    162152        case IPC_M_DATA_READ:
    163                 return true;
     153                return 1;
    164154        default:
    165                 return false;
     155                return 0;
    166156        }
    167157}
     
    171161 * This function is called directly after sys_ipc_answer().
    172162 *
    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  *
     163 * @param answer        Call structure with the answer.
     164 * @param olddata       Saved data of the request.
     165 *
     166 * @return              Return 0 on success or an error code.
    178167 */
    179168static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    180169{
     170        int phoneid;
     171
    181172        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    182173                /* In case of forward, hangup the forwared phone,
     
    184175                 */
    185176                mutex_lock(&answer->data.phone->lock);
    186                 irq_spinlock_lock(&TASK->answerbox.lock, true);
     177                spinlock_lock(&TASK->answerbox.lock);
    187178                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    188179                        list_remove(&answer->data.phone->link);
    189180                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    190181                }
    191                 irq_spinlock_unlock(&TASK->answerbox.lock, true);
     182                spinlock_unlock(&TASK->answerbox.lock);
    192183                mutex_unlock(&answer->data.phone->lock);
    193184        }
    194        
     185
    195186        if (!olddata)
    196187                return 0;
    197        
     188
    198189        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
    199                 int phoneid = IPC_GET_ARG1(*olddata);
    200                 phone_t *phone = &TASK->phones[phoneid];
    201                
     190                phoneid = IPC_GET_ARG1(*olddata);
     191                phone_t *phone = &TASK->phones[phoneid];
    202192                if (IPC_GET_RETVAL(answer->data) != EOK) {
    203193                        /*
     
    211201                        mutex_lock(&phone->lock);
    212202                        if (phone->state == IPC_PHONE_CONNECTED) {
    213                                 irq_spinlock_lock(&phone->callee->lock, true);
     203                                spinlock_lock(&phone->callee->lock);
    214204                                list_remove(&phone->link);
    215205                                phone->state = IPC_PHONE_SLAMMED;
    216                                 irq_spinlock_unlock(&phone->callee->lock, true);
     206                                spinlock_unlock(&phone->callee->lock);
    217207                        }
    218208                        mutex_unlock(&phone->lock);
    219209                }
    220210        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
    221                 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
    222                
     211                phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
    223212                if (IPC_GET_RETVAL(answer->data) != EOK) {
    224213                        /*
     
    230219                        mutex_lock(&phone->lock);
    231220                        if (phone->state == IPC_PHONE_CONNECTED) {
    232                                 irq_spinlock_lock(&phone->callee->lock, true);
     221                                spinlock_lock(&phone->callee->lock);
    233222                                list_remove(&phone->link);
    234223                                phone->state = IPC_PHONE_SLAMMED;
    235                                 irq_spinlock_unlock(&phone->callee->lock, true);
     224                                spinlock_unlock(&phone->callee->lock);
    236225                        }
    237226                        mutex_unlock(&phone->lock);
    238227                }
    239228        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    240                 int phoneid = IPC_GET_ARG5(*olddata);
    241                
     229                phoneid = IPC_GET_ARG5(*olddata);
    242230                if (IPC_GET_RETVAL(answer->data) != EOK) {
    243231                        /* The connection was not accepted */
     
    259247                if (!IPC_GET_RETVAL(answer->data)) {
    260248                        /* Accepted, handle as_area receipt */
     249                        ipl_t ipl;
     250                        int rc;
     251                        as_t *as;
    261252                       
    262                         irq_spinlock_lock(&answer->sender->lock, true);
    263                         as_t *as = answer->sender->as;
    264                         irq_spinlock_unlock(&answer->sender->lock, true);
     253                        ipl = interrupts_disable();
     254                        spinlock_lock(&answer->sender->lock);
     255                        as = answer->sender->as;
     256                        spinlock_unlock(&answer->sender->lock);
     257                        interrupts_restore(ipl);
    265258                       
    266                         int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     259                        rc = as_area_share(as, IPC_GET_ARG1(*olddata),
    267260                            IPC_GET_ARG2(*olddata), AS,
    268261                            IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
     
    272265        } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) {
    273266                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);
     267                        ipl_t ipl;
     268                        as_t *as;
     269                        int rc;
    277270                       
    278                         int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     271                        ipl = interrupts_disable();
     272                        spinlock_lock(&answer->sender->lock);
     273                        as = answer->sender->as;
     274                        spinlock_unlock(&answer->sender->lock);
     275                        interrupts_restore(ipl);
     276                       
     277                        rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
    279278                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    280279                            IPC_GET_ARG2(answer->data));
     
    295294                                 */
    296295                                IPC_SET_ARG1(answer->data, dst);
    297                                
     296
    298297                                answer->buffer = malloc(size, 0);
    299298                                int rc = copy_from_uspace(answer->buffer,
     
    314313                if (!IPC_GET_RETVAL(answer->data)) {
    315314                        /* 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                        
     315                        int rc;
     316                        uintptr_t dst;
     317                        size_t size;
     318                        size_t max_size;
     319
     320                        dst = (uintptr_t)IPC_GET_ARG1(answer->data);
     321                        size = (size_t)IPC_GET_ARG2(answer->data);
     322                        max_size = (size_t)IPC_GET_ARG2(*olddata);
     323
    320324                        if (size <= max_size) {
    321                                 int rc = copy_to_uspace((void *) dst,
     325                                rc = copy_to_uspace((void *) dst,
    322326                                    answer->buffer, size);
    323327                                if (rc)
     
    330334                answer->buffer = NULL;
    331335        }
    332        
    333336        return 0;
    334337}
     
    342345                mutex_lock(&p2->lock);
    343346                mutex_lock(&p1->lock);
    344         } else
     347        } else {
    345348                mutex_lock(&p1->lock);
     349        }
    346350}
    347351
     
    355359/** Called before the request is sent.
    356360 *
    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  *
     361 * @param call          Call structure with the request.
     362 * @param phone         Phone that the call will be sent through.
     363 *
     364 * @return              Return 0 on success, ELIMIT or EPERM on error.
    362365 */
    363366static int request_preprocess(call_t *call, phone_t *phone)
    364367{
     368        int newphid;
     369        size_t size;
     370        uintptr_t src;
     371        int rc;
     372
    365373        switch (IPC_GET_METHOD(call->data)) {
    366374        case IPC_M_CONNECTION_CLONE: {
    367375                phone_t *cloned_phone;
    368                 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
    369                         return ENOENT;
    370                
     376                GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
     377                    return ENOENT;);
    371378                phones_lock(cloned_phone, phone);
    372                
    373379                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    374380                    phone->state != IPC_PHONE_CONNECTED) {
     
    376382                        return EINVAL;
    377383                }
    378                
    379384                /*
    380385                 * We can be pretty sure now that both tasks exist and we are
     
    382387                 * we are effectively preventing them from finishing their
    383388                 * potential cleanup.
    384                  *
    385389                 */
    386                 int newphid = phone_alloc(phone->callee->task);
     390                newphid = phone_alloc(phone->callee->task);
    387391                if (newphid < 0) {
    388392                        phones_unlock(cloned_phone, phone);
    389393                        return ELIMIT;
    390394                }
    391                
    392395                ipc_phone_connect(&phone->callee->task->phones[newphid],
    393396                    cloned_phone->callee);
    394397                phones_unlock(cloned_phone, phone);
    395                
    396398                /* Set the new phone for the callee. */
    397399                IPC_SET_ARG1(call->data, newphid);
     
    401403                IPC_SET_ARG5(call->data, (unative_t) phone);
    402404                break;
    403         case IPC_M_CONNECT_ME_TO: {
    404                 int newphid = phone_alloc(TASK);
     405        case IPC_M_CONNECT_ME_TO:
     406                newphid = phone_alloc(TASK);
    405407                if (newphid < 0)
    406408                        return ELIMIT;
    407                
    408409                /* Set arg5 for server */
    409410                IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
     
    411412                call->priv = newphid;
    412413                break;
    413         }
    414         case IPC_M_SHARE_OUT: {
    415                 size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
     414        case IPC_M_SHARE_OUT:
     415                size = as_area_get_size(IPC_GET_ARG1(call->data));
    416416                if (!size)
    417417                        return EPERM;
    418                
    419418                IPC_SET_ARG2(call->data, size);
    420419                break;
    421         }
    422         case IPC_M_DATA_READ: {
    423                 size_t size = IPC_GET_ARG2(call->data);
     420        case IPC_M_DATA_READ:
     421                size = IPC_GET_ARG2(call->data);
    424422                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    425423                        return ELIMIT;
    426                
    427424                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);
     425        case IPC_M_DATA_WRITE:
     426                src = IPC_GET_ARG1(call->data);
     427                size = IPC_GET_ARG2(call->data);
    432428               
    433429                if (size > DATA_XFER_LIMIT)
     
    435431               
    436432                call->buffer = (uint8_t *) malloc(size, 0);
    437                 int rc = copy_from_uspace(call->buffer, (void *) src, size);
     433                rc = copy_from_uspace(call->buffer, (void *) src, size);
    438434                if (rc != 0) {
    439435                        free(call->buffer);
    440436                        return rc;
    441437                }
    442                
    443438                break;
    444         }
    445439#ifdef CONFIG_UDEBUG
    446440        case IPC_M_DEBUG_ALL:
     
    450444                break;
    451445        }
    452        
    453446        return 0;
    454447}
     
    460453/** Do basic kernel processing of received call answer.
    461454 *
    462  * @param call Call structure with the answer.
    463  *
     455 * @param call          Call structure with the answer.
    464456 */
    465457static void process_answer(call_t *call)
     
    468460            (call->flags & IPC_CALL_FORWARDED))
    469461                IPC_SET_RETVAL(call->data, EFORWARD);
    470        
     462
    471463        if (call->flags & IPC_CALL_CONN_ME_TO) {
    472464                if (IPC_GET_RETVAL(call->data))
     
    475467                        IPC_SET_ARG5(call->data, call->priv);
    476468        }
    477        
     469
    478470        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                  */
     471                /* This must be an affirmative answer to IPC_M_DATA_READ. */
     472                /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
    484473                uintptr_t dst = IPC_GET_ARG1(call->data);
    485474                size_t size = IPC_GET_ARG2(call->data);
     
    494483/** Do basic kernel processing of received call request.
    495484 *
    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  *
     485 * @param box           Destination answerbox structure.
     486 * @param call          Call structure with the request.
     487 *
     488 * @return              Return 0 if the call should be passed to userspace.
     489 *                      Return -1 if the call should be ignored.
    502490 */
    503491static int process_request(answerbox_t *box, call_t *call)
    504492{
     493        int phoneid;
     494
    505495        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    506                 int phoneid = phone_alloc(TASK);
     496                phoneid = phone_alloc(TASK);
    507497                if (phoneid < 0) { /* Failed to allocate phone */
    508498                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    510500                        return -1;
    511501                }
    512                
    513502                IPC_SET_ARG5(call->data, phoneid);
    514503        }
    515        
    516504        switch (IPC_GET_METHOD(call->data)) {
    517505        case IPC_M_DEBUG_ALL:
     
    520508                break;
    521509        }
    522        
    523510        return 0;
    524511}
     
    529516 * the generic function (i.e. sys_ipc_call_sync_slow()).
    530517 *
    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  *
     518 * @param phoneid       Phone handle for the call.
     519 * @param method        Method of the call.
     520 * @param arg1          Service-defined payload argument.
     521 * @param arg2          Service-defined payload argument.
     522 * @param arg3          Service-defined payload argument.
     523 * @param data          Address of userspace structure where the reply call will
     524 *                      be stored.
     525 *
     526 * @return              Returns 0 on success.
     527 *                      Return ENOENT if there is no such phone handle.
    542528 */
    543529unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
    544530    unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    545531{
     532        call_t *call;
    546533        phone_t *phone;
    547         if (phone_get(phoneid, &phone) != EOK)
    548                 return ENOENT;
    549 
    550         call_t *call = ipc_call_alloc(0);
     534        int res;
     535        int rc;
     536       
     537        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     538
     539        call = ipc_call_alloc(0);
    551540        IPC_SET_METHOD(call->data, method);
    552541        IPC_SET_ARG1(call->data, arg1);
    553542        IPC_SET_ARG2(call->data, arg2);
    554543        IPC_SET_ARG3(call->data, arg3);
    555        
    556544        /*
    557545         * To achieve deterministic behavior, zero out arguments that are beyond
     
    560548        IPC_SET_ARG4(call->data, 0);
    561549        IPC_SET_ARG5(call->data, 0);
    562        
    563         int res = request_preprocess(call, phone);
    564         int rc;
    565        
    566         if (!res) {
     550
     551        if (!(res = request_preprocess(call, phone))) {
    567552#ifdef CONFIG_UDEBUG
    568553                udebug_stoppable_begin();
     
    572557                udebug_stoppable_end();
    573558#endif
    574                
    575559                if (rc != EOK) {
    576560                        /* The call will be freed by ipc_cleanup(). */
    577561                        return rc;
    578562                }
    579                
    580563                process_answer(call);
    581                
    582         } else
     564
     565        } else {
    583566                IPC_SET_RETVAL(call->data, res);
    584        
     567        }
    585568        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
    586569        ipc_call_free(call);
    587570        if (rc != 0)
    588571                return rc;
    589        
     572
    590573        return 0;
    591574}
     
    593576/** Make a synchronous IPC call allowing to transmit the entire payload.
    594577 *
    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  *
     578 * @param phoneid       Phone handle for the call.
     579 * @param question      Userspace address of call data with the request.
     580 * @param reply         Userspace address of call data where to store the
     581 *                      answer.
     582 *
     583 * @return              Zero on success or an error code.
    602584 */
    603585unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
    604586    ipc_data_t *reply)
    605587{
     588        call_t *call;
    606589        phone_t *phone;
    607         if (phone_get(phoneid, &phone) != EOK)
    608                 return ENOENT;
    609 
    610         call_t *call = ipc_call_alloc(0);
    611         int rc = copy_from_uspace(&call->data.args, &question->args,
     590        int res;
     591        int rc;
     592
     593        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     594
     595        call = ipc_call_alloc(0);
     596        rc = copy_from_uspace(&call->data.args, &question->args,
    612597            sizeof(call->data.args));
    613598        if (rc != 0) {
     
    615600                return (unative_t) rc;
    616601        }
    617        
    618         int res = request_preprocess(call, phone);
    619        
    620         if (!res) {
     602
     603
     604        if (!(res = request_preprocess(call, phone))) {
    621605#ifdef CONFIG_UDEBUG
    622606                udebug_stoppable_begin();
     
    626610                udebug_stoppable_end();
    627611#endif
    628                
    629612                if (rc != EOK) {
    630613                        /* The call will be freed by ipc_cleanup(). */
    631614                        return rc;
    632615                }
    633                
    634616                process_answer(call);
    635         } else
     617        } else 
    636618                IPC_SET_RETVAL(call->data, res);
    637        
     619
    638620        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
    639621        ipc_call_free(call);
    640622        if (rc != 0)
    641623                return rc;
    642        
     624
    643625        return 0;
    644626}
     
    646628/** Check that the task did not exceed the allowed limit of asynchronous calls.
    647629 *
    648  * @return 0 if limit not reached or -1 if limit exceeded.
    649  *
     630 * @return              Return 0 if limit not reached or -1 if limit exceeded.
    650631 */
    651632static int check_call_limit(void)
     
    655636                return -1;
    656637        }
    657        
    658638        return 0;
    659639}
     
    664644 * the generic function sys_ipc_call_async_slow().
    665645 *
    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  *
     646 * @param phoneid       Phone handle for the call.
     647 * @param method        Method of the call.
     648 * @param arg1          Service-defined payload argument.
     649 * @param arg2          Service-defined payload argument.
     650 * @param arg3          Service-defined payload argument.
     651 * @param arg4          Service-defined payload argument.
     652 *
     653 * @return              Return call hash on success.
     654 *                      Return IPC_CALLRET_FATAL in case of a fatal error and
     655 *                      IPC_CALLRET_TEMPORARY if there are too many pending
     656 *                      asynchronous requests; answers should be handled first.
    678657 */
    679658unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
    680659    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    681660{
     661        call_t *call;
     662        phone_t *phone;
     663        int res;
     664
    682665        if (check_call_limit())
    683666                return IPC_CALLRET_TEMPORARY;
    684        
    685         phone_t *phone;
    686         if (phone_get(phoneid, &phone) != EOK)
    687                 return IPC_CALLRET_FATAL;
    688        
    689         call_t *call = ipc_call_alloc(0);
     667
     668        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
     669
     670        call = ipc_call_alloc(0);
    690671        IPC_SET_METHOD(call->data, method);
    691672        IPC_SET_ARG1(call->data, arg1);
     
    693674        IPC_SET_ARG3(call->data, arg3);
    694675        IPC_SET_ARG4(call->data, arg4);
    695        
    696676        /*
    697677         * To achieve deterministic behavior, zero out arguments that are beyond
     
    699679         */
    700680        IPC_SET_ARG5(call->data, 0);
    701        
    702         int res = request_preprocess(call, phone);
    703        
    704         if (!res)
     681
     682        if (!(res = request_preprocess(call, phone)))
    705683                ipc_call(phone, call);
    706684        else
    707685                ipc_backsend_err(phone, call, res);
    708        
     686
    709687        return (unative_t) call;
    710688}
     
    712690/** Make an asynchronous IPC call allowing to transmit the entire payload.
    713691 *
    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  *
     692 * @param phoneid       Phone handle for the call.
     693 * @param data          Userspace address of call data with the request.
     694 *
     695 * @return              See sys_ipc_call_async_fast().
    719696 */
    720697unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
    721698{
     699        call_t *call;
     700        phone_t *phone;
     701        int res;
     702        int rc;
     703
    722704        if (check_call_limit())
    723705                return IPC_CALLRET_TEMPORARY;
    724        
    725         phone_t *phone;
    726         if (phone_get(phoneid, &phone) != EOK)
    727                 return IPC_CALLRET_FATAL;
    728 
    729         call_t *call = ipc_call_alloc(0);
    730         int rc = copy_from_uspace(&call->data.args, &data->args,
     706
     707        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
     708
     709        call = ipc_call_alloc(0);
     710        rc = copy_from_uspace(&call->data.args, &data->args,
    731711            sizeof(call->data.args));
    732712        if (rc != 0) {
     
    734714                return (unative_t) rc;
    735715        }
    736        
    737         int res = request_preprocess(call, phone);
    738        
    739         if (!res)
     716        if (!(res = request_preprocess(call, phone)))
    740717                ipc_call(phone, call);
    741718        else
    742719                ipc_backsend_err(phone, call, res);
    743        
     720
    744721        return (unative_t) call;
    745722}
    746723
    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  *
     724/** Forward a received call to another destination - common code for both the
     725 * fast and the slow version.
     726 *
     727 * @param callid        Hash of the call to forward.
     728 * @param phoneid       Phone handle to use for forwarding.
     729 * @param method        New method to use for the forwarded call.
     730 * @param arg1          New value of the first argument for the forwarded call.
     731 * @param arg2          New value of the second argument for the forwarded call.
     732 * @param arg3          New value of the third argument for the forwarded call.
     733 * @param arg4          New value of the fourth argument for the forwarded call.
     734 * @param arg5          New value of the fifth argument for the forwarded call.
     735 * @param mode          Flags that specify mode of the forward operation.
     736 * @param slow          If true, arg3, arg4 and arg5 are considered. Otherwise
     737 *                      the function considers only the fast version arguments:
     738 *                      i.e. arg1 and arg2.
     739 *
     740 * @return              Return 0 on succes, otherwise return an error code.
     741 *
     742 * Warning:     Make sure that ARG5 is not rewritten for certain system IPC
    768743 */
    769744static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
    770745    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);
     746    unative_t arg4, unative_t arg5, int mode, bool slow)
     747{
     748        call_t *call;
     749        phone_t *phone;
     750
     751        call = get_call(callid);
    774752        if (!call)
    775753                return ENOENT;
    776754       
    777755        call->flags |= IPC_CALL_FORWARDED;
    778        
    779         phone_t *phone;
    780         if (phone_get(phoneid, &phone) != EOK) {
     756
     757        GET_CHECK_PHONE(phone, phoneid, {
    781758                IPC_SET_RETVAL(call->data, EFORWARD);
    782759                ipc_answer(&TASK->answerbox, call);
    783760                return ENOENT;
    784         }
    785        
     761        });
     762
    786763        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
    787764                IPC_SET_RETVAL(call->data, EFORWARD);
     
    789766                return EPERM;
    790767        }
    791        
     768
    792769        /*
    793770         * Userspace is not allowed to change method of system methods on
     
    800777                        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
    801778                                phone_dealloc(IPC_GET_ARG5(call->data));
    802                        
     779
    803780                        IPC_SET_ARG1(call->data, method);
    804781                        IPC_SET_ARG2(call->data, arg1);
    805782                        IPC_SET_ARG3(call->data, arg2);
    806                        
    807783                        if (slow) {
    808784                                IPC_SET_ARG4(call->data, arg3);
     
    823799                }
    824800        }
    825        
     801
    826802        return ipc_forward(call, phone, &TASK->answerbox, mode);
    827803}
    828804
    829805/** Forward a received call to another destination - fast version.
     806 *
     807 * @param callid        Hash of the call to forward.
     808 * @param phoneid       Phone handle to use for forwarding.
     809 * @param method        New method to use for the forwarded call.
     810 * @param arg1          New value of the first argument for the forwarded call.
     811 * @param arg2          New value of the second argument for the forwarded call.
     812 * @param mode          Flags that specify mode of the forward operation.
     813 *
     814 * @return              Return 0 on succes, otherwise return an error code.
    830815 *
    831816 * In case the original method is a system method, ARG1, ARG2 and ARG3 are
     
    835820 * is a set of immutable methods, for which the new method and arguments are not
    836821 * 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  *
    847822 */
    848823unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
    849     unative_t method, unative_t arg1, unative_t arg2, unsigned int mode)
     824    unative_t method, unative_t arg1, unative_t arg2, int mode)
    850825{
    851826        return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
     
    854829
    855830/** Forward a received call to another destination - slow version.
     831 *
     832 * @param callid        Hash of the call to forward.
     833 * @param phoneid       Phone handle to use for forwarding.
     834 * @param data          Userspace address of the new IPC data.
     835 * @param mode          Flags that specify mode of the forward operation.
     836 *
     837 * @return              Return 0 on succes, otherwise return an error code.
    856838 *
    857839 * This function is the slow verision of the sys_ipc_forward_fast interface.
     
    861843 * methods, it additionally stores the new value of arg3, arg4 and arg5,
    862844 * 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  *
    871845 */
    872846unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    873     ipc_data_t *data, unsigned int mode)
     847    ipc_data_t *data, int mode)
    874848{
    875849        ipc_data_t newdata;
    876         int rc = copy_from_uspace(&newdata.args, &data->args,
     850        int rc;
     851
     852        rc = copy_from_uspace(&newdata.args, &data->args,
    877853            sizeof(newdata.args));
    878         if (rc != 0)
     854        if (rc != 0) 
    879855                return (unative_t) rc;
    880        
     856
    881857        return sys_ipc_forward_common(callid, phoneid,
    882858            IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
     
    890866 * than the generic sys_ipc_answer().
    891867 *
    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  *
     868 * @param callid        Hash of the call to be answered.
     869 * @param retval        Return value of the answer.
     870 * @param arg1          Service-defined return value.
     871 * @param arg2          Service-defined return value.
     872 * @param arg3          Service-defined return value.
     873 * @param arg4          Service-defined return value.
     874 *
     875 * @return              Return 0 on success, otherwise return an error code.   
    901876 */
    902877unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    903878    unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    904879{
     880        call_t *call;
     881        ipc_data_t saved_data;
     882        int saveddata = 0;
     883        int rc;
     884
    905885        /* Do not answer notification callids */
    906886        if (callid & IPC_CALLID_NOTIFICATION)
    907887                return 0;
    908        
    909         call_t *call = get_call(callid);
     888
     889        call = get_call(callid);
    910890        if (!call)
    911891                return ENOENT;
    912        
    913         ipc_data_t saved_data;
    914         bool saved;
    915        
     892
    916893        if (answer_need_old(call)) {
    917894                memcpy(&saved_data, &call->data, sizeof(call->data));
    918                 saved = true;
    919         } else
    920                 saved = false;
    921        
     895                saveddata = 1;
     896        }
     897
    922898        IPC_SET_RETVAL(call->data, retval);
    923899        IPC_SET_ARG1(call->data, arg1);
     
    925901        IPC_SET_ARG3(call->data, arg3);
    926902        IPC_SET_ARG4(call->data, arg4);
    927        
    928903        /*
    929904         * To achieve deterministic behavior, zero out arguments that are beyond
     
    931906         */
    932907        IPC_SET_ARG5(call->data, 0);
    933         int rc = answer_preprocess(call, saved ? &saved_data : NULL);
    934        
     908        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     909
    935910        ipc_answer(&TASK->answerbox, call);
    936911        return rc;
     
    939914/** Answer an IPC call.
    940915 *
    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  *
     916 * @param callid        Hash of the call to be answered.
     917 * @param data          Userspace address of call data with the answer.
     918 *
     919 * @return              Return 0 on success, otherwise return an error code.
    946920 */
    947921unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data)
    948922{
     923        call_t *call;
     924        ipc_data_t saved_data;
     925        int saveddata = 0;
     926        int rc;
     927
    949928        /* Do not answer notification callids */
    950929        if (callid & IPC_CALLID_NOTIFICATION)
    951930                return 0;
    952        
    953         call_t *call = get_call(callid);
     931
     932        call = get_call(callid);
    954933        if (!call)
    955934                return ENOENT;
    956        
    957         ipc_data_t saved_data;
    958         bool saved;
    959        
     935
    960936        if (answer_need_old(call)) {
    961937                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,
     938                saveddata = 1;
     939        }
     940        rc = copy_from_uspace(&call->data.args, &data->args,
    967941            sizeof(call->data.args));
    968942        if (rc != 0)
    969943                return rc;
    970        
    971         rc = answer_preprocess(call, saved ? &saved_data : NULL);
     944
     945        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    972946       
    973947        ipc_answer(&TASK->answerbox, call);
     948
    974949        return rc;
    975950}
     
    977952/** Hang up a phone.
    978953 *
    979  * @param Phone handle of the phone to be hung up.
    980  *
    981  * @return 0 on success or an error code.
    982  *
    983  */
    984 unative_t sys_ipc_hangup(unative_t phoneid)
     954 * @param               Phone handle of the phone to be hung up.
     955 *
     956 * @return              Return 0 on success or an error code.
     957 */
     958unative_t sys_ipc_hangup(int phoneid)
    985959{
    986960        phone_t *phone;
    987        
    988         if (phone_get(phoneid, &phone) != EOK)
    989                 return ENOENT;
    990        
     961
     962        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     963
    991964        if (ipc_phone_hangup(phone))
    992965                return -1;
    993        
     966
    994967        return 0;
    995968}
     
    997970/** Wait for an incoming IPC call or an answer.
    998971 *
    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)
     972 * @param calldata      Pointer to buffer where the call/answer data is stored.
     973 * @param usec          Timeout. See waitq_sleep_timeout() for explanation.
     974 * @param flags         Select mode of sleep operation. See waitq_sleep_timeout()
     975 *                      for explanation.
     976 *
     977 * @return              Hash of the call.
     978 *                      If IPC_CALLID_NOTIFICATION bit is set in the hash, the
     979 *                      call is a notification. IPC_CALLID_ANSWERED denotes an
     980 *                      answer.
     981 */
     982unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
    1012983{
    1013984        call_t *call;
    1014        
     985
    1015986restart:
    1016        
     987
    1017988#ifdef CONFIG_UDEBUG
    1018989        udebug_stoppable_begin();
    1019 #endif
    1020        
     990#endif 
    1021991        call = ipc_wait_for_call(&TASK->answerbox, usec,
    1022992            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    1023        
     993
    1024994#ifdef CONFIG_UDEBUG
    1025995        udebug_stoppable_end();
    1026996#endif
    1027        
    1028997        if (!call)
    1029998                return 0;
    1030        
     999
    10311000        if (call->flags & IPC_CALL_NOTIF) {
    10321001                /* Set in_phone_hash to the interrupt counter */
     
    10341003               
    10351004                STRUCT_TO_USPACE(calldata, &call->data);
    1036                
     1005
    10371006                ipc_call_free(call);
    10381007               
    10391008                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    10401009        }
    1041        
     1010
    10421011        if (call->flags & IPC_CALL_ANSWERED) {
    10431012                process_answer(call);
    1044                
     1013
    10451014                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10461015                        ipc_call_free(call);
     
    10541023                        atomic_dec(&TASK->active_calls);
    10551024                }
    1056                
     1025
    10571026                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10581027                ipc_call_free(call);
    1059                
     1028
    10601029                return ((unative_t) call) | IPC_CALLID_ANSWERED;
    10611030        }
    1062        
     1031
    10631032        if (process_request(&TASK->answerbox, call))
    10641033                goto restart;
    1065        
     1034
    10661035        /* Include phone address('id') of the caller in the request,
    10671036         * copy whole call->data, not only call->data.args */
     
    10721041                 */
    10731042                ipc_data_t saved_data;
    1074                 bool saved;
    1075                
     1043                int saveddata = 0;
     1044
    10761045                if (answer_need_old(call)) {
    10771046                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1078                         saved = true;
    1079                 } else
    1080                         saved = false;
     1047                        saveddata = 1;
     1048                }
    10811049               
    10821050                IPC_SET_RETVAL(call->data, EPARTY);
    1083                 (void) answer_preprocess(call, saved ? &saved_data : NULL);
     1051                (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
    10841052                ipc_answer(&TASK->answerbox, call);
    10851053                return 0;
    10861054        }
    1087        
    1088         return (unative_t) call;
    1089 }
    1090 
    1091 /** Interrupt one thread from sys_ipc_wait_for_call().
    1092  *
    1093  */
     1055        return (unative_t)call;
     1056}
     1057
     1058/** Interrupt one thread from sys_ipc_wait_for_call(). */
    10941059unative_t sys_ipc_poke(void)
    10951060{
    1096         waitq_unsleep(&TASK->answerbox.wq);
     1061        waitq_unsleep(&TASK->answerbox.wq);     
    10971062        return EOK;
    10981063}
     
    11001065/** Connect an IRQ handler to a task.
    11011066 *
    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  *
     1067 * @param inr           IRQ number.
     1068 * @param devno         Device number.
     1069 * @param method        Method to be associated with the notification.
     1070 * @param ucode         Uspace pointer to the top-half pseudocode.
     1071 *
     1072 * @return              EPERM or a return code returned by ipc_irq_register().
    11091073 */
    11101074unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     
    11131077        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11141078                return EPERM;
    1115        
     1079
    11161080        return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
    11171081}
     
    11191083/** Disconnect an IRQ handler from a task.
    11201084 *
    1121  * @param inr   IRQ number.
    1122  * @param devno Device number.
    1123  *
    1124  * @return Zero on success or EPERM on error.
    1125  *
     1085 * @param inr           IRQ number.
     1086 * @param devno         Device number.
     1087 *
     1088 * @return              Zero on success or EPERM on error..
    11261089 */
    11271090unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
     
    11291092        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11301093                return EPERM;
    1131        
     1094
    11321095        ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1133        
     1096
    11341097        return 0;
    11351098}
     
    11371100#include <console/console.h>
    11381101
    1139 /** Syscall connect to a task by id.
    1140  *
    1141  * @return Phone id on success, or negative error code.
    1142  *
     1102/**
     1103 * Syscall connect to a task by id.
     1104 *
     1105 * @return              Phone id on success, or negative error code.
    11431106 */
    11441107unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     
    11461109#ifdef CONFIG_UDEBUG
    11471110        sysarg64_t taskid_arg;
    1148         int rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
     1111        int rc;
     1112       
     1113        rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    11491114        if (rc != 0)
    11501115                return (unative_t) rc;
    1151        
    1152         LOG("sys_ipc_connect_kbox(%" PRIu64 ")", taskid_arg.value);
    1153        
     1116
     1117        LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
     1118
    11541119        return ipc_connect_kbox(taskid_arg.value);
    11551120#else
Note: See TracChangeset for help on using the changeset viewer.