Ignore:
File:
1 edited

Legend:

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

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