Changes in kernel/generic/src/ipc/sysipc.c [cde999a:706b4de] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/sysipc.c
rcde999a r706b4de 53 53 #include <print.h> 54 54 #include <macros.h> 55 #include <cap/cap.h>56 55 57 56 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src))) … … 155 154 * @param olddata Saved data of the request. 156 155 * 157 * @return Return EOK on success or a nerror code.156 * @return Return EOK on success or a negative error code. 158 157 * 159 158 */ … … 194 193 spinlock_unlock(&answer->forget_lock); 195 194 196 if (( int) IPC_GET_RETVAL(answer->data) == EHANGUP) {195 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 197 196 phone_t *phone = answer->caller_phone; 198 197 mutex_lock(&phone->lock); … … 239 238 static void process_answer(call_t *call) 240 239 { 241 if ((( int) IPC_GET_RETVAL(call->data) == EHANGUP) &&240 if (((native_t) IPC_GET_RETVAL(call->data) == EHANGUP) && 242 241 (call->flags & IPC_CALL_FORWARDED)) 243 242 IPC_SET_RETVAL(call->data, EFORWARD); … … 287 286 #endif 288 287 289 kobject_add_ref(call->kobject);288 ipc_call_hold(call); 290 289 rc = ipc_call_sync(kobj->phone, call); 291 290 spinlock_lock(&call->forget_lock); 292 291 bool forgotten = call->forget; 293 292 spinlock_unlock(&call->forget_lock); 294 kobject_put(call->kobject);293 ipc_call_release(call); 295 294 296 295 #ifdef CONFIG_UDEBUG … … 307 306 * deallocation. 308 307 */ 309 kobject_put(call->kobject);308 ipc_call_free(call); 310 309 } else { 311 310 /* … … 324 323 325 324 memcpy(data->args, call->data.args, sizeof(data->args)); 326 kobject_put(call->kobject);325 ipc_call_free(call); 327 326 kobject_put(kobj); 328 327 … … 348 347 /** Make a fast asynchronous call over IPC. 349 348 * 350 * This function can only handle threearguments of payload, but is faster than349 * This function can only handle four arguments of payload, but is faster than 351 350 * the generic function sys_ipc_call_async_slow(). 352 351 * … … 356 355 * @param arg2 Service-defined payload argument. 357 356 * @param arg3 Service-defined payload argument. 358 * @param label User-defined label.359 * 360 * @return EOKon success.361 * @return An error code onerror.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. 362 361 * 363 362 */ 364 363 sysarg_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) 366 365 { 367 366 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 368 367 if (!kobj) 369 return ENOENT;368 return IPC_CALLRET_FATAL; 370 369 371 370 if (check_call_limit(kobj->phone)) { 372 371 kobject_put(kobj); 373 return ELIMIT;372 return IPC_CALLRET_FATAL; 374 373 } 375 374 … … 379 378 IPC_SET_ARG2(call->data, arg2); 380 379 IPC_SET_ARG3(call->data, arg3); 380 IPC_SET_ARG4(call->data, arg4); 381 381 382 382 /* … … 385 385 */ 386 386 IPC_SET_ARG5(call->data, 0); 387 388 /* Set the user-defined label */389 call->data.label = label;390 387 391 388 int res = request_preprocess(call, kobj->phone); … … 397 394 398 395 kobject_put(kobj); 399 return EOK;396 return (sysarg_t) call; 400 397 } 401 398 … … 404 401 * @param handle Phone capability for the call. 405 402 * @param data Userspace address of call data with the request. 406 * @param label User-defined label.407 403 * 408 404 * @return See sys_ipc_call_async_fast(). 409 405 * 410 406 */ 411 sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data, 412 sysarg_t label) 407 sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data) 413 408 { 414 409 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 415 410 if (!kobj) 416 return ENOENT;411 return IPC_CALLRET_FATAL; 417 412 418 413 if (check_call_limit(kobj->phone)) { 419 414 kobject_put(kobj); 420 return ELIMIT;415 return IPC_CALLRET_FATAL; 421 416 } 422 417 … … 425 420 sizeof(call->data.args)); 426 421 if (rc != 0) { 427 kobject_put(call->kobject);422 ipc_call_free(call); 428 423 kobject_put(kobj); 429 424 return (sysarg_t) rc; 430 425 } 431 432 /* Set the user-defined label */433 call->data.label = label;434 426 435 427 int res = request_preprocess(call, kobj->phone); … … 441 433 442 434 kobject_put(kobj); 443 return EOK;435 return (sysarg_t) call; 444 436 } 445 437 … … 448 440 * Common code for both the fast and the slow version. 449 441 * 450 * @param c handle Call handle of the forwarded call.451 * @param phandle Phone handleto use for forwarding.442 * @param callid Hash of the call to forward. 443 * @param handle Phone capability to use for forwarding. 452 444 * @param imethod New interface and method to use for the forwarded call. 453 445 * @param arg1 New value of the first argument for the forwarded call. … … 466 458 * 467 459 */ 468 static sysarg_t sys_ipc_forward_common(sysarg_t c handle, sysarg_t phandle,460 static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t handle, 469 461 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 470 462 sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow) 471 463 { 472 kobject_t *ckobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);473 if (!c kobj)464 call_t *call = get_call(callid); 465 if (!call) 474 466 return ENOENT; 475 467 476 call_t *call = ckobj->call;477 478 468 ipc_data_t old; 479 469 bool need_old = answer_need_old(call); … … 484 474 int rc; 485 475 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) { 488 478 rc = ENOENT; 489 479 goto error; … … 531 521 } 532 522 533 rc = ipc_forward(call, pkobj->phone, &TASK->answerbox, mode);523 rc = ipc_forward(call, kobj->phone, &TASK->answerbox, mode); 534 524 if (rc != EOK) { 535 525 after_forward = true; … … 537 527 } 538 528 539 cap_free(TASK, chandle); 540 kobject_put(ckobj); 541 kobject_put(pkobj); 529 kobject_put(kobj); 542 530 return EOK; 543 531 … … 550 538 ipc_answer(&TASK->answerbox, call); 551 539 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); 557 542 return rc; 558 543 } … … 567 552 * arguments are not set and these values are ignored. 568 553 * 569 * @param c handle Call handleof the call to forward.570 * @param phandlePhone handle to use for forwarding.554 * @param callid Hash of the call to forward. 555 * @param handle Phone handle to use for forwarding. 571 556 * @param imethod New interface and method to use for the forwarded call. 572 557 * @param arg1 New value of the first argument for the forwarded call. … … 577 562 * 578 563 */ 579 sysarg_t sys_ipc_forward_fast(sysarg_t c handle, sysarg_t phandle,564 sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t handle, 580 565 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode) 581 566 { 582 return sys_ipc_forward_common(c handle, 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); 584 569 } 585 570 … … 593 578 * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively. 594 579 * 595 * @param c handle Call handleof the call to forward.596 * @param phandle Phone handle to use for forwarding.597 * @param data 598 * @param mode 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. 599 584 * 600 585 * @return 0 on succes, otherwise an error code. 601 586 * 602 587 */ 603 sysarg_t sys_ipc_forward_slow(sysarg_t c handle, sysarg_t phandle,588 sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t handle, 604 589 ipc_data_t *data, unsigned int mode) 605 590 { … … 610 595 return (sysarg_t) rc; 611 596 612 return sys_ipc_forward_common(c handle, phandle,597 return sys_ipc_forward_common(callid, handle, 613 598 IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata), 614 599 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); 616 601 } 617 602 … … 621 606 * than the generic sys_ipc_answer(). 622 607 * 623 * @param c handle Call handleto be answered.624 * @param retval 625 * @param arg1 626 * @param arg2 627 * @param arg3 628 * @param arg4 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. 629 614 * 630 615 * @return 0 on success, otherwise an error code. 631 616 * 632 617 */ 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) 618 sysarg_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) 638 627 return ENOENT; 639 628 640 call_t *call = kobj->call;641 642 629 ipc_data_t saved_data; 643 630 bool saved; … … 663 650 664 651 ipc_answer(&TASK->answerbox, call); 665 666 kobject_put(kobj);667 cap_free(TASK, chandle);668 669 652 return rc; 670 653 } … … 672 655 /** Answer an IPC call. 673 656 * 674 * @param c handle Call handleto be answered.675 * @param data 657 * @param callid Hash of the call to be answered. 658 * @param data Userspace address of call data with the answer. 676 659 * 677 660 * @return 0 on success, otherwise an error code. 678 661 * 679 662 */ 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) 663 sysarg_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) 684 671 return ENOENT; 685 672 686 call_t *call = kobj->call;687 688 673 ipc_data_t saved_data; 689 674 bool saved; … … 697 682 int rc = copy_from_uspace(&call->data.args, &data->args, 698 683 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) 704 685 return rc; 705 }706 686 707 687 rc = answer_preprocess(call, saved ? &saved_data : NULL); 708 688 709 689 ipc_answer(&TASK->answerbox, call); 710 711 kobject_put(kobj);712 cap_free(TASK, chandle);713 714 690 return rc; 715 691 } … … 728 704 return ENOENT; 729 705 730 int rc = ipc_phone_hangup(kobj->phone); 706 if (ipc_phone_hangup(kobj->phone)) { 707 kobject_put(kobj); 708 return -1; 709 } 710 731 711 kobject_put(kobj); 732 return rc;712 return 0; 733 713 } 734 714 … … 740 720 * for explanation. 741 721 * 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 * 743 727 */ 744 728 sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, … … 759 743 udebug_stoppable_end(); 760 744 #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 770 749 if (call->flags & IPC_CALL_NOTIF) { 771 750 /* Set in_phone_hash to the interrupt counter */ 772 751 call->data.phone = (void *) call->priv; 773 752 774 call->data.cap_handle = CAP_NIL;775 776 753 STRUCT_TO_USPACE(calldata, &call->data); 777 kobject_put(call->kobject);778 754 779 return EOK; 755 ipc_call_free(call); 756 757 return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION; 780 758 } 781 759 … … 784 762 785 763 if (call->flags & IPC_CALL_DISCARD_ANSWER) { 786 kobject_put(call->kobject);764 ipc_call_free(call); 787 765 goto restart; 788 766 } 789 790 call->data.cap_handle = CAP_NIL;791 767 792 768 STRUCT_TO_USPACE(calldata, &call->data); 793 kobject_put(call->kobject);769 ipc_call_free(call); 794 770 795 return EOK;771 return ((sysarg_t) call) | IPC_CALLID_ANSWERED; 796 772 } 797 773 … … 799 775 goto restart; 800 776 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; 845 800 } 846 801 … … 860 815 * @param ucode Uspace pointer to the top-half pseudocode. 861 816 * 862 * @param[out] uspace_handle Uspace pointer to IRQ kernel object capability 863 * 817 * @return IRQ kernel object capability 864 818 * @return EPERM 865 819 * @return Error code returned by ipc_irq_subscribe(). 866 820 * 867 821 */ 868 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode, 869 cap_handle_t *uspace_handle) 822 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode) 870 823 { 871 824 if (!(perm_get(TASK) & PERM_IRQ_REG)) 872 825 return EPERM; 873 826 874 return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode , uspace_handle);827 return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode); 875 828 } 876 829 … … 893 846 } 894 847 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 */ 855 sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid) 901 856 { 902 857 #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); 920 864 #else 921 865 return (sysarg_t) ENOTSUP; … … 923 867 } 924 868 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 */ 878 sysarg_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 925 889 /** @} 926 890 */
Note:
See TracChangeset
for help on using the changeset viewer.