Changes in kernel/generic/src/ipc/sysipc.c [0016674:706b4de] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/sysipc.c
r0016674 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))) … … 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 Negative 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 } … … 744 720 * for explanation. 745 721 * 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 * 747 727 */ 748 728 sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, … … 763 743 udebug_stoppable_end(); 764 744 #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; 772 748 773 749 if (call->flags & IPC_CALL_NOTIF) { … … 775 751 call->data.phone = (void *) call->priv; 776 752 777 call->data.flags = IPC_CALL_NOTIF;778 call->data.cap_handle = CAP_NIL;779 780 753 STRUCT_TO_USPACE(calldata, &call->data); 781 kobject_put(call->kobject);782 754 783 return EOK; 755 ipc_call_free(call); 756 757 return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION; 784 758 } 785 759 … … 788 762 789 763 if (call->flags & IPC_CALL_DISCARD_ANSWER) { 790 kobject_put(call->kobject);764 ipc_call_free(call); 791 765 goto restart; 792 766 } 793 794 call->data.flags = IPC_CALL_ANSWERED;795 call->data.cap_handle = CAP_NIL;796 767 797 768 STRUCT_TO_USPACE(calldata, &call->data); 798 kobject_put(call->kobject);769 ipc_call_free(call); 799 770 800 return EOK;771 return ((sysarg_t) call) | IPC_CALLID_ANSWERED; 801 772 } 802 773 … … 804 775 goto restart; 805 776 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; 849 800 } 850 801 … … 864 815 * @param ucode Uspace pointer to the top-half pseudocode. 865 816 * 866 * @param[out] uspace_handle Uspace pointer to IRQ kernel object capability 867 * 817 * @return IRQ kernel object capability 868 818 * @return EPERM 869 819 * @return Error code returned by ipc_irq_subscribe(). 870 820 * 871 821 */ 872 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode, 873 cap_handle_t *uspace_handle) 822 sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode) 874 823 { 875 824 if (!(perm_get(TASK) & PERM_IRQ_REG)) 876 825 return EPERM; 877 826 878 return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode , uspace_handle);827 return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode); 879 828 } 880 829 … … 897 846 } 898 847 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 */ 855 sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid) 905 856 { 906 857 #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); 924 864 #else 925 865 return (sysarg_t) ENOTSUP; … … 927 867 } 928 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 929 889 /** @} 930 890 */
Note:
See TracChangeset
for help on using the changeset viewer.