Ignore:
File:
1 edited

Legend:

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

    r0016674 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)))
     
    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 Negative 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}
     
    744720 *                 for explanation.
    745721 *
    746  * @return Negative 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 *
    747727 */
    748728sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
     
    763743        udebug_stoppable_end();
    764744#endif
    765 
    766         if (!call) {
    767                 ipc_data_t data = {0};
    768                 data.cap_handle = CAP_NIL;
    769                 STRUCT_TO_USPACE(calldata, &data);
    770                 return EOK;
    771         }
     745       
     746        if (!call)
     747                return 0;
    772748       
    773749        if (call->flags & IPC_CALL_NOTIF) {
     
    775751                call->data.phone = (void *) call->priv;
    776752               
    777                 call->data.flags = IPC_CALL_NOTIF;
    778                 call->data.cap_handle = CAP_NIL;
    779 
    780753                STRUCT_TO_USPACE(calldata, &call->data);
    781                 kobject_put(call->kobject);
    782754               
    783                 return EOK;
     755                ipc_call_free(call);
     756               
     757                return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
    784758        }
    785759       
     
    788762               
    789763                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    790                         kobject_put(call->kobject);
     764                        ipc_call_free(call);
    791765                        goto restart;
    792766                }
    793 
    794                 call->data.flags = IPC_CALL_ANSWERED;
    795                 call->data.cap_handle = CAP_NIL;
    796767               
    797768                STRUCT_TO_USPACE(calldata, &call->data);
    798                 kobject_put(call->kobject);
     769                ipc_call_free(call);
    799770               
    800                 return EOK;
     771                return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
    801772        }
    802773       
     
    804775                goto restart;
    805776       
    806         int rc;
    807         cap_handle_t handle = cap_alloc(TASK);
    808         if (handle < 0) {
    809                 rc = handle;
    810                 goto error;
    811         }
    812        
    813         call->data.cap_handle = handle;
    814 
    815         /*
    816          * Include phone hash of the caller in the request, copy the whole
    817          * call->data, not only call->data.args.
    818          */
    819         rc = STRUCT_TO_USPACE(calldata, &call->data);
    820         if (rc != EOK)
    821                 goto error;
    822 
    823         kobject_add_ref(call->kobject);
    824         cap_publish(TASK, handle, call->kobject);
    825         return EOK;
    826 
    827 error:
    828         if (handle >= 0)
    829                 cap_free(TASK, handle);
    830 
    831         /*
    832          * The callee will not receive this call and no one else has a chance to
    833          * answer it. Reply with the EPARTY error code.
    834          */
    835         ipc_data_t saved_data;
    836         bool saved;
    837 
    838         if (answer_need_old(call)) {
    839                 memcpy(&saved_data, &call->data, sizeof(call->data));
    840                 saved = true;
    841         } else
    842                 saved = false;
    843 
    844         IPC_SET_RETVAL(call->data, EPARTY);
    845         (void) answer_preprocess(call, saved ? &saved_data : NULL);
    846         ipc_answer(&TASK->answerbox, call);
    847 
    848         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;
    849800}
    850801
     
    864815 * @param ucode   Uspace pointer to the top-half pseudocode.
    865816 *
    866  * @param[out] uspace_handle  Uspace pointer to IRQ kernel object capability
    867  *
     817 * @return IRQ kernel object capability
    868818 * @return EPERM
    869819 * @return Error code returned by ipc_irq_subscribe().
    870820 *
    871821 */
    872 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode,
    873         cap_handle_t *uspace_handle)
     822sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode)
    874823{
    875824        if (!(perm_get(TASK) & PERM_IRQ_REG))
    876825                return EPERM;
    877826       
    878         return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode, uspace_handle);
     827        return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode);
    879828}
    880829
     
    897846}
    898847
    899 /** Syscall connect to a task by ID
    900  *
    901  * @return Error code.
    902  *
    903  */
    904 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)
    905856{
    906857#ifdef CONFIG_UDEBUG
    907         task_id_t taskid;
    908         cap_handle_t phone;
    909        
    910         int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(task_id_t));
    911         if (rc == EOK) {
    912                 rc = ipc_connect_kbox((task_id_t) taskid, &phone);
    913         }
    914        
    915         if (rc == EOK) {
    916                 rc = copy_to_uspace(uspace_phone, &phone, sizeof(cap_handle_t));
    917                 if (rc != EOK) {
    918                         // Clean up the phone on failure.
    919                         sys_ipc_hangup(phone);
    920                 }
    921         }
    922        
    923         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);
    924864#else
    925865        return (sysarg_t) ENOTSUP;
     
    927867}
    928868
     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
    929889/** @}
    930890 */
Note: See TracChangeset for help on using the changeset viewer.