Ignore:
File:
1 edited

Legend:

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

    rcde999a r706b4de  
    5353#include <print.h>
    5454#include <macros.h>
    55 #include <cap/cap.h>
    5655
    5756#define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
     
    155154 * @param olddata Saved data of the request.
    156155 *
    157  * @return Return EOK on success or an error code.
     156 * @return Return EOK on success or a negative error code.
    158157 *
    159158 */
     
    194193        spinlock_unlock(&answer->forget_lock);
    195194
    196         if ((int) IPC_GET_RETVAL(answer->data) == EHANGUP) {
     195        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    197196                phone_t *phone = answer->caller_phone;
    198197                mutex_lock(&phone->lock);
     
    239238static void process_answer(call_t *call)
    240239{
    241         if (((int) IPC_GET_RETVAL(call->data) == EHANGUP) &&
     240        if (((native_t) IPC_GET_RETVAL(call->data) == EHANGUP) &&
    242241            (call->flags & IPC_CALL_FORWARDED))
    243242                IPC_SET_RETVAL(call->data, EFORWARD);
     
    287286#endif
    288287
    289                 kobject_add_ref(call->kobject);
     288                ipc_call_hold(call);
    290289                rc = ipc_call_sync(kobj->phone, call);
    291290                spinlock_lock(&call->forget_lock);
    292291                bool forgotten = call->forget;
    293292                spinlock_unlock(&call->forget_lock);
    294                 kobject_put(call->kobject);
     293                ipc_call_release(call);
    295294
    296295#ifdef CONFIG_UDEBUG
     
    307306                                 * deallocation.
    308307                                 */
    309                                 kobject_put(call->kobject);
     308                                ipc_call_free(call);
    310309                        } else {
    311310                                /*
     
    324323       
    325324        memcpy(data->args, call->data.args, sizeof(data->args));
    326         kobject_put(call->kobject);
     325        ipc_call_free(call);
    327326        kobject_put(kobj);
    328327       
     
    348347/** Make a fast asynchronous call over IPC.
    349348 *
    350  * This function can only handle three arguments of payload, but is faster than
     349 * This function can only handle four arguments of payload, but is faster than
    351350 * the generic function sys_ipc_call_async_slow().
    352351 *
     
    356355 * @param arg2     Service-defined payload argument.
    357356 * @param arg3     Service-defined payload argument.
    358  * @param label    User-defined label.
    359  *
    360  * @return EOK on success.
    361  * @return An error code on error.
     357 * @param arg4     Service-defined payload argument.
     358 *
     359 * @return Call hash on success.
     360 * @return IPC_CALLRET_FATAL in case of a fatal error.
    362361 *
    363362 */
    364363sysarg_t sys_ipc_call_async_fast(sysarg_t handle, sysarg_t imethod,
    365     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t label)
     364    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
    366365{
    367366        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
    368367        if (!kobj)
    369                 return ENOENT;
     368                return IPC_CALLRET_FATAL;
    370369       
    371370        if (check_call_limit(kobj->phone)) {
    372371                kobject_put(kobj);
    373                 return ELIMIT;
     372                return IPC_CALLRET_FATAL;
    374373        }
    375374       
     
    379378        IPC_SET_ARG2(call->data, arg2);
    380379        IPC_SET_ARG3(call->data, arg3);
     380        IPC_SET_ARG4(call->data, arg4);
    381381       
    382382        /*
     
    385385         */
    386386        IPC_SET_ARG5(call->data, 0);
    387 
    388         /* Set the user-defined label */
    389         call->data.label = label;
    390387       
    391388        int res = request_preprocess(call, kobj->phone);
     
    397394       
    398395        kobject_put(kobj);
    399         return EOK;
     396        return (sysarg_t) call;
    400397}
    401398
     
    404401 * @param handle  Phone capability for the call.
    405402 * @param data    Userspace address of call data with the request.
    406  * @param label   User-defined label.
    407403 *
    408404 * @return See sys_ipc_call_async_fast().
    409405 *
    410406 */
    411 sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data,
    412     sysarg_t label)
     407sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data)
    413408{
    414409        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
    415410        if (!kobj)
    416                 return ENOENT;
     411                return IPC_CALLRET_FATAL;
    417412
    418413        if (check_call_limit(kobj->phone)) {
    419414                kobject_put(kobj);
    420                 return ELIMIT;
     415                return IPC_CALLRET_FATAL;
    421416        }
    422417
     
    425420            sizeof(call->data.args));
    426421        if (rc != 0) {
    427                 kobject_put(call->kobject);
     422                ipc_call_free(call);
    428423                kobject_put(kobj);
    429424                return (sysarg_t) rc;
    430425        }
    431 
    432         /* Set the user-defined label */
    433         call->data.label = label;
    434426       
    435427        int res = request_preprocess(call, kobj->phone);
     
    441433       
    442434        kobject_put(kobj);
    443         return EOK;
     435        return (sysarg_t) call;
    444436}
    445437
     
    448440 * Common code for both the fast and the slow version.
    449441 *
    450  * @param chandle  Call handle of the forwarded call.
    451  * @param phandle  Phone handle to use for forwarding.
     442 * @param callid   Hash of the call to forward.
     443 * @param handle   Phone capability to use for forwarding.
    452444 * @param imethod  New interface and method to use for the forwarded call.
    453445 * @param arg1     New value of the first argument for the forwarded call.
     
    466458 *
    467459 */
    468 static sysarg_t sys_ipc_forward_common(sysarg_t chandle, sysarg_t phandle,
     460static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t handle,
    469461    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    470462    sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
    471463{
    472         kobject_t *ckobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
    473         if (!ckobj)
     464        call_t *call = get_call(callid);
     465        if (!call)
    474466                return ENOENT;
    475467       
    476         call_t *call = ckobj->call;
    477 
    478468        ipc_data_t old;
    479469        bool need_old = answer_need_old(call);
     
    484474        int rc;
    485475
    486         kobject_t *pkobj = kobject_get(TASK, phandle, KOBJECT_TYPE_PHONE);
    487         if (!pkobj) {
     476        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     477        if (!kobj) {
    488478                rc = ENOENT;
    489479                goto error;
     
    531521        }
    532522       
    533         rc = ipc_forward(call, pkobj->phone, &TASK->answerbox, mode);
     523        rc = ipc_forward(call, kobj->phone, &TASK->answerbox, mode);
    534524        if (rc != EOK) {
    535525                after_forward = true;
     
    537527        }
    538528
    539         cap_free(TASK, chandle);
    540         kobject_put(ckobj);
    541         kobject_put(pkobj);
     529        kobject_put(kobj);
    542530        return EOK;
    543531
     
    550538                ipc_answer(&TASK->answerbox, call);
    551539
    552         /* Republish the capability so that the call does not get lost. */
    553         cap_publish(TASK, chandle, ckobj);
    554 
    555         if (pkobj)
    556                 kobject_put(pkobj);
     540        if (kobj)
     541                kobject_put(kobj);
    557542        return rc;
    558543}
     
    567552 * arguments are not set and these values are ignored.
    568553 *
    569  * @param chandle  Call handle of the call to forward.
    570  * @param phandle  Phone handle to use for forwarding.
     554 * @param callid   Hash of the call to forward.
     555 * @param handle   Phone handle to use for forwarding.
    571556 * @param imethod  New interface and method to use for the forwarded call.
    572557 * @param arg1     New value of the first argument for the forwarded call.
     
    577562 *
    578563 */
    579 sysarg_t sys_ipc_forward_fast(sysarg_t chandle, sysarg_t phandle,
     564sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t handle,
    580565    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    581566{
    582         return sys_ipc_forward_common(chandle, phandle, imethod, arg1, arg2, 0,
    583             0, 0, mode, false);
     567        return sys_ipc_forward_common(callid, handle, imethod, arg1, arg2, 0, 0,
     568            0, mode, false);
    584569}
    585570
     
    593578 * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively.
    594579 *
    595  * @param chandle  Call handle of the call to forward.
    596  * @param phandle  Phone handle to use for forwarding.
    597  * @param data     Userspace address of the new IPC data.
    598  * @param mode     Flags that specify mode of the forward operation.
     580 * @param callid  Hash of the call to forward.
     581 * @param handle  Phone handle to use for forwarding.
     582 * @param data    Userspace address of the new IPC data.
     583 * @param mode    Flags that specify mode of the forward operation.
    599584 *
    600585 * @return 0 on succes, otherwise an error code.
    601586 *
    602587 */
    603 sysarg_t sys_ipc_forward_slow(sysarg_t chandle, sysarg_t phandle,
     588sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t handle,
    604589    ipc_data_t *data, unsigned int mode)
    605590{
     
    610595                return (sysarg_t) rc;
    611596       
    612         return sys_ipc_forward_common(chandle, phandle,
     597        return sys_ipc_forward_common(callid, handle,
    613598            IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
    614599            IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
    615             IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
     600            IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true); 
    616601}
    617602
     
    621606 * than the generic sys_ipc_answer().
    622607 *
    623  * @param chandle  Call handle to be answered.
    624  * @param retval   Return value of the answer.
    625  * @param arg1     Service-defined return value.
    626  * @param arg2     Service-defined return value.
    627  * @param arg3     Service-defined return value.
    628  * @param arg4     Service-defined return value.
     608 * @param callid Hash of the call to be answered.
     609 * @param retval Return value of the answer.
     610 * @param arg1   Service-defined return value.
     611 * @param arg2   Service-defined return value.
     612 * @param arg3   Service-defined return value.
     613 * @param arg4   Service-defined return value.
    629614 *
    630615 * @return 0 on success, otherwise an error code.
    631616 *
    632617 */
    633 sysarg_t sys_ipc_answer_fast(sysarg_t chandle, sysarg_t retval, sysarg_t arg1,
    634     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
    635 {
    636         kobject_t *kobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
    637         if (!kobj)
     618sysarg_t sys_ipc_answer_fast(sysarg_t callid, sysarg_t retval,
     619    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     620{
     621        /* Do not answer notification callids */
     622        if (callid & IPC_CALLID_NOTIFICATION)
     623                return 0;
     624       
     625        call_t *call = get_call(callid);
     626        if (!call)
    638627                return ENOENT;
    639628       
    640         call_t *call = kobj->call;
    641 
    642629        ipc_data_t saved_data;
    643630        bool saved;
     
    663650       
    664651        ipc_answer(&TASK->answerbox, call);
    665 
    666         kobject_put(kobj);
    667         cap_free(TASK, chandle);
    668 
    669652        return rc;
    670653}
     
    672655/** Answer an IPC call.
    673656 *
    674  * @param chandle Call handle to be answered.
    675  * @param data    Userspace address of call data with the answer.
     657 * @param callid Hash of the call to be answered.
     658 * @param data   Userspace address of call data with the answer.
    676659 *
    677660 * @return 0 on success, otherwise an error code.
    678661 *
    679662 */
    680 sysarg_t sys_ipc_answer_slow(sysarg_t chandle, ipc_data_t *data)
    681 {
    682         kobject_t *kobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
    683         if (!kobj)
     663sysarg_t sys_ipc_answer_slow(sysarg_t callid, ipc_data_t *data)
     664{
     665        /* Do not answer notification callids */
     666        if (callid & IPC_CALLID_NOTIFICATION)
     667                return 0;
     668       
     669        call_t *call = get_call(callid);
     670        if (!call)
    684671                return ENOENT;
    685672       
    686         call_t *call = kobj->call;
    687 
    688673        ipc_data_t saved_data;
    689674        bool saved;
     
    697682        int rc = copy_from_uspace(&call->data.args, &data->args,
    698683            sizeof(call->data.args));
    699         if (rc != 0) {
    700                 /*
    701                  * Republish the capability so that the call does not get lost.
    702                  */
    703                 cap_publish(TASK, chandle, kobj);
     684        if (rc != 0)
    704685                return rc;
    705         }
    706686       
    707687        rc = answer_preprocess(call, saved ? &saved_data : NULL);
    708688       
    709689        ipc_answer(&TASK->answerbox, call);
    710 
    711         kobject_put(kobj);
    712         cap_free(TASK, chandle);
    713 
    714690        return rc;
    715691}
     
    728704                return ENOENT;
    729705       
    730         int rc = ipc_phone_hangup(kobj->phone);
     706        if (ipc_phone_hangup(kobj->phone)) {
     707                kobject_put(kobj);
     708                return -1;
     709        }
     710       
    731711        kobject_put(kobj);
    732         return rc;
     712        return 0;
    733713}
    734714
     
    740720 *                 for explanation.
    741721 *
    742  * @return An error code on error.
     722 * @return Hash of the call.
     723 *         If IPC_CALLID_NOTIFICATION bit is set in the hash, the
     724 *         call is a notification. IPC_CALLID_ANSWERED denotes an
     725 *         answer.
     726 *
    743727 */
    744728sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
     
    759743        udebug_stoppable_end();
    760744#endif
    761 
    762         if (!call) {
    763                 ipc_data_t data = {};
    764                 data.cap_handle = CAP_NIL;
    765                 STRUCT_TO_USPACE(calldata, &data);
    766                 return EOK;
    767         }
    768        
    769         call->data.flags = call->flags;
     745       
     746        if (!call)
     747                return 0;
     748       
    770749        if (call->flags & IPC_CALL_NOTIF) {
    771750                /* Set in_phone_hash to the interrupt counter */
    772751                call->data.phone = (void *) call->priv;
    773752               
    774                 call->data.cap_handle = CAP_NIL;
    775 
    776753                STRUCT_TO_USPACE(calldata, &call->data);
    777                 kobject_put(call->kobject);
    778754               
    779                 return EOK;
     755                ipc_call_free(call);
     756               
     757                return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
    780758        }
    781759       
     
    784762               
    785763                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    786                         kobject_put(call->kobject);
     764                        ipc_call_free(call);
    787765                        goto restart;
    788766                }
    789 
    790                 call->data.cap_handle = CAP_NIL;
    791767               
    792768                STRUCT_TO_USPACE(calldata, &call->data);
    793                 kobject_put(call->kobject);
     769                ipc_call_free(call);
    794770               
    795                 return EOK;
     771                return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
    796772        }
    797773       
     
    799775                goto restart;
    800776       
    801         cap_handle_t handle;
    802         int rc = cap_alloc(TASK, &handle);
    803         if (rc != EOK) {
    804                 goto error;
    805         }
    806        
    807         call->data.cap_handle = handle;
    808 
    809         /*
    810          * Include phone hash of the caller in the request, copy the whole
    811          * call->data, not only call->data.args.
    812          */
    813         rc = STRUCT_TO_USPACE(calldata, &call->data);
    814         if (rc != EOK)
    815                 goto error;
    816 
    817         kobject_add_ref(call->kobject);
    818         cap_publish(TASK, handle, call->kobject);
    819         return EOK;
    820 
    821 error:
    822         if (handle >= 0)
    823                 cap_free(TASK, handle);
    824 
    825         /*
    826          * The callee will not receive this call and no one else has a chance to
    827          * answer it. Set the IPC_CALL_AUTO_REPLY flag and return the EPARTY
    828          * error code.
    829          */
    830         ipc_data_t saved_data;
    831         bool saved;
    832 
    833         if (answer_need_old(call)) {
    834                 memcpy(&saved_data, &call->data, sizeof(call->data));
    835                 saved = true;
    836         } else
    837                 saved = false;
    838 
    839         IPC_SET_RETVAL(call->data, EPARTY);
    840         (void) answer_preprocess(call, saved ? &saved_data : NULL);
    841         call->flags |= IPC_CALL_AUTO_REPLY;
    842         ipc_answer(&TASK->answerbox, call);
    843 
    844         return rc;
     777        /* Include phone address('id') of the caller in the request,
     778         * copy whole call->data, not only call->data.args */
     779        if (STRUCT_TO_USPACE(calldata, &call->data)) {
     780                /*
     781                 * The callee will not receive this call and no one else has
     782                 * a chance to answer it. Reply with the EPARTY error code.
     783                 */
     784                ipc_data_t saved_data;
     785                bool saved;
     786               
     787                if (answer_need_old(call)) {
     788                        memcpy(&saved_data, &call->data, sizeof(call->data));
     789                        saved = true;
     790                } else
     791                        saved = false;
     792               
     793                IPC_SET_RETVAL(call->data, EPARTY);
     794                (void) answer_preprocess(call, saved ? &saved_data : NULL);
     795                ipc_answer(&TASK->answerbox, call);
     796                return 0;
     797        }
     798       
     799        return (sysarg_t) call;
    845800}
    846801
     
    860815 * @param ucode   Uspace pointer to the top-half pseudocode.
    861816 *
    862  * @param[out] uspace_handle  Uspace pointer to IRQ kernel object capability
    863  *
     817 * @return IRQ kernel object capability
    864818 * @return EPERM
    865819 * @return Error code returned by ipc_irq_subscribe().
    866820 *
    867821 */
    868 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode,
    869         cap_handle_t *uspace_handle)
     822sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode)
    870823{
    871824        if (!(perm_get(TASK) & PERM_IRQ_REG))
    872825                return EPERM;
    873826       
    874         return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode, uspace_handle);
     827        return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode);
    875828}
    876829
     
    893846}
    894847
    895 /** Syscall connect to a task by ID
    896  *
    897  * @return Error code.
    898  *
    899  */
    900 sysarg_t sys_ipc_connect_kbox(task_id_t *uspace_taskid, cap_handle_t *uspace_phone)
     848#ifdef __32_BITS__
     849
     850/** Syscall connect to a task by ID (32 bits)
     851 *
     852 * @return Phone id on success, or negative error code.
     853 *
     854 */
     855sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid)
    901856{
    902857#ifdef CONFIG_UDEBUG
    903         task_id_t taskid;
    904         cap_handle_t phone;
    905        
    906         int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(task_id_t));
    907         if (rc == EOK) {
    908                 rc = ipc_connect_kbox((task_id_t) taskid, &phone);
    909         }
    910        
    911         if (rc == EOK) {
    912                 rc = copy_to_uspace(uspace_phone, &phone, sizeof(cap_handle_t));
    913                 if (rc != EOK) {
    914                         // Clean up the phone on failure.
    915                         sys_ipc_hangup(phone);
    916                 }
    917         }
    918        
    919         return (sysarg_t) rc;
     858        sysarg64_t taskid;
     859        int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
     860        if (rc != 0)
     861                return (sysarg_t) rc;
     862       
     863        return ipc_connect_kbox((task_id_t) taskid);
    920864#else
    921865        return (sysarg_t) ENOTSUP;
     
    923867}
    924868
     869#endif  /* __32_BITS__ */
     870
     871#ifdef __64_BITS__
     872
     873/** Syscall connect to a task by ID (64 bits)
     874 *
     875 * @return Phone id on success, or negative error code.
     876 *
     877 */
     878sysarg_t sys_ipc_connect_kbox(sysarg_t taskid)
     879{
     880#ifdef CONFIG_UDEBUG
     881        return ipc_connect_kbox((task_id_t) taskid);
     882#else
     883        return (sysarg_t) ENOTSUP;
     884#endif
     885}
     886
     887#endif  /* __64_BITS__ */
     888
    925889/** @}
    926890 */
Note: See TracChangeset for help on using the changeset viewer.