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