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