Changeset 9e87562 in mainline for kernel/generic/src/ipc/ipc.c
- Timestamp:
- 2017-09-18T20:52:12Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6abfd250
- Parents:
- e5f5ce0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
re5f5ce0 r9e87562 710 710 * Nota bene: there may still be answers waiting for pick up. 711 711 */ 712 spinlock_unlock(&TASK->active_calls_lock); 712 spinlock_unlock(&TASK->active_calls_lock); 713 713 return; 714 714 } … … 723 723 * call on the list. 724 724 */ 725 spinlock_unlock(&TASK->active_calls_lock); 725 spinlock_unlock(&TASK->active_calls_lock); 726 726 goto restart; 727 727 } … … 730 730 731 731 goto restart; 732 } 733 734 static bool phone_cap_wait_cb(cap_t *cap, void *arg) 735 { 736 phone_t *phone = (phone_t *) cap->kobject; 737 bool *restart = (bool *) arg; 738 739 mutex_lock(&phone->lock); 740 if ((phone->state == IPC_PHONE_HUNGUP) && 741 (atomic_get(&phone->active_calls) == 0)) { 742 phone->state = IPC_PHONE_FREE; 743 phone->callee = NULL; 744 } 745 746 /* 747 * We might have had some IPC_PHONE_CONNECTING phones at the beginning 748 * of ipc_cleanup(). Depending on whether these were forgotten or 749 * answered, they will eventually enter the IPC_PHONE_FREE or 750 * IPC_PHONE_CONNECTED states, respectively. In the latter case, the 751 * other side may slam the open phones at any time, in which case we 752 * will get an IPC_PHONE_SLAMMED phone. 753 */ 754 if ((phone->state == IPC_PHONE_CONNECTED) || 755 (phone->state == IPC_PHONE_SLAMMED)) { 756 mutex_unlock(&phone->lock); 757 ipc_phone_hangup(phone); 758 /* 759 * Now there may be one extra active call, which needs to be 760 * forgotten. 761 */ 762 ipc_forget_all_active_calls(); 763 *restart = true; 764 return false; 765 } 766 767 /* 768 * If the hangup succeeded, it has sent a HANGUP message, the IPC is now 769 * in HUNGUP state, we wait for the reply to come 770 */ 771 if (phone->state != IPC_PHONE_FREE) { 772 mutex_unlock(&phone->lock); 773 return false; 774 } 775 776 mutex_unlock(&phone->lock); 777 return true; 732 778 } 733 779 … … 736 782 { 737 783 call_t *call; 738 bool all_clean;784 bool restart; 739 785 740 786 restart: … … 743 789 * Locking is needed as there may be connection handshakes in progress. 744 790 */ 745 all_clean = true; 746 for_each_cap_current(cap, CAP_TYPE_PHONE) { 747 phone_t *phone = (phone_t *) cap->kobject; 748 749 mutex_lock(&phone->lock); 750 if ((phone->state == IPC_PHONE_HUNGUP) && 751 (atomic_get(&phone->active_calls) == 0)) { 752 phone->state = IPC_PHONE_FREE; 753 phone->callee = NULL; 754 } 755 756 /* 757 * We might have had some IPC_PHONE_CONNECTING phones at the 758 * beginning of ipc_cleanup(). Depending on whether these were 759 * forgotten or answered, they will eventually enter the 760 * IPC_PHONE_FREE or IPC_PHONE_CONNECTED states, respectively. 761 * In the latter case, the other side may slam the open phones 762 * at any time, in which case we will get an IPC_PHONE_SLAMMED 763 * phone. 764 */ 765 if ((phone->state == IPC_PHONE_CONNECTED) || 766 (phone->state == IPC_PHONE_SLAMMED)) { 767 mutex_unlock(&phone->lock); 768 ipc_phone_hangup(phone); 769 /* 770 * Now there may be one extra active call, which needs 771 * to be forgotten. 772 */ 773 ipc_forget_all_active_calls(); 774 goto restart; 775 } 776 777 /* 778 * If the hangup succeeded, it has sent a HANGUP message, the 779 * IPC is now in HUNGUP state, we wait for the reply to come 780 */ 781 if (phone->state != IPC_PHONE_FREE) { 782 mutex_unlock(&phone->lock); 783 all_clean = false; 784 break; 785 } 786 787 mutex_unlock(&phone->lock); 788 } 789 790 /* Got into cleanup */ 791 if (all_clean) 791 restart = false; 792 if (caps_apply_to_all(TASK, CAP_TYPE_PHONE, phone_cap_wait_cb, 793 &restart)) { 794 /* Got into cleanup */ 792 795 return; 793 796 } 797 if (restart) 798 goto restart; 799 794 800 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 795 801 SYNCH_FLAGS_NONE); … … 800 806 ipc_call_free(call); 801 807 goto restart; 808 } 809 810 static bool phone_cap_cleanup_cb(cap_t *cap, void *arg) 811 { 812 phone_t *phone = (phone_t *) cap->kobject; 813 ipc_phone_hangup(phone); 814 return true; 815 } 816 817 static bool irq_cap_cleanup_cb(cap_t *cap, void *arg) 818 { 819 ipc_irq_unsubscribe(&TASK->answerbox, cap->handle); 820 return true; 802 821 } 803 822 … … 821 840 822 841 /* Disconnect all our phones ('ipc_phone_hangup') */ 823 for_each_cap_current(cap, CAP_TYPE_PHONE) { 824 phone_t *phone = (phone_t *) cap->kobject; 825 ipc_phone_hangup(phone); 826 } 842 caps_apply_to_all(TASK, CAP_TYPE_PHONE, phone_cap_cleanup_cb, NULL); 827 843 828 844 /* Unsubscribe from any event notifications. */ … … 830 846 831 847 /* Disconnect all connected IRQs */ 832 for_each_cap_current(cap, CAP_TYPE_IRQ) { 833 ipc_irq_unsubscribe(&TASK->answerbox, cap->handle); 834 } 848 caps_apply_to_all(TASK, CAP_TYPE_IRQ, irq_cap_cleanup_cb, NULL); 835 849 836 850 /* Disconnect all phones connected to our regular answerbox */ … … 896 910 } 897 911 912 static bool print_task_phone_cb(cap_t *cap, void *arg) 913 { 914 phone_t *phone = (phone_t *) cap->kobject; 915 916 mutex_lock(&phone->lock); 917 if (phone->state != IPC_PHONE_FREE) { 918 printf("%-11d %7" PRIun " ", cap->handle, 919 atomic_get(&phone->active_calls)); 920 921 switch (phone->state) { 922 case IPC_PHONE_CONNECTING: 923 printf("connecting"); 924 break; 925 case IPC_PHONE_CONNECTED: 926 printf("connected to %" PRIu64 " (%s)", 927 phone->callee->task->taskid, 928 phone->callee->task->name); 929 break; 930 case IPC_PHONE_SLAMMED: 931 printf("slammed by %p", phone->callee); 932 break; 933 case IPC_PHONE_HUNGUP: 934 printf("hung up by %p", phone->callee); 935 break; 936 default: 937 break; 938 } 939 940 printf("\n"); 941 } 942 mutex_unlock(&phone->lock); 943 944 return true; 945 } 946 898 947 /** List answerbox contents. 899 948 * … … 905 954 irq_spinlock_lock(&tasks_lock, true); 906 955 task_t *task = task_find_by_id(taskid); 907 908 956 if (!task) { 909 957 irq_spinlock_unlock(&tasks_lock, true); 910 958 return; 911 959 } 912 913 /* Hand-over-hand locking */ 914 irq_spinlock_exchange(&tasks_lock, &task->lock); 960 task_hold(task); 961 irq_spinlock_unlock(&tasks_lock, true); 915 962 916 963 printf("[phone cap] [calls] [state\n"); 917 964 918 for_each_cap(task, cap, CAP_TYPE_PHONE) { 919 phone_t *phone = (phone_t *) cap->kobject; 920 921 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 922 printf("%-11d (mutex busy)\n", cap->handle); 923 continue; 924 } 925 926 if (phone->state != IPC_PHONE_FREE) { 927 printf("%-11d %7" PRIun " ", cap->handle, 928 atomic_get(&phone->active_calls)); 929 930 switch (phone->state) { 931 case IPC_PHONE_CONNECTING: 932 printf("connecting"); 933 break; 934 case IPC_PHONE_CONNECTED: 935 printf("connected to %" PRIu64 " (%s)", 936 phone->callee->task->taskid, 937 phone->callee->task->name); 938 break; 939 case IPC_PHONE_SLAMMED: 940 printf("slammed by %p", phone->callee); 941 break; 942 case IPC_PHONE_HUNGUP: 943 printf("hung up by %p", phone->callee); 944 break; 945 default: 946 break; 947 } 948 949 printf("\n"); 950 } 951 952 mutex_unlock(&phone->lock); 953 } 954 965 caps_apply_to_all(task, CAP_TYPE_PHONE, print_task_phone_cb, NULL); 966 967 irq_spinlock_lock(&task->lock, true); 955 968 irq_spinlock_lock(&task->answerbox.lock, false); 956 969 … … 974 987 irq_spinlock_unlock(&task->answerbox.lock, false); 975 988 irq_spinlock_unlock(&task->lock, true); 989 990 task_release(task); 976 991 } 977 992
Note:
See TracChangeset
for help on using the changeset viewer.