Changeset da1bafb in mainline for kernel/generic/src/ipc/sysipc.c


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

major code revision

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

Legend:

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

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