Changes in kernel/generic/src/ipc/ipc.c [a36f442:a35b458] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
ra36f442 ra35b458 63 63 static void ipc_forget_call(call_t *); 64 64 65 /** Answerbox that new tasks are automatically connected to*/66 answerbox_t *ipc_ box_0 = NULL;65 /** Open channel that is assigned automatically to new tasks */ 66 answerbox_t *ipc_phone_0 = NULL; 67 67 68 68 static slab_cache_t *call_cache; … … 147 147 list_initialize(&box->answers); 148 148 list_initialize(&box->irq_notifs); 149 atomic_set(&box->active_calls, 0);150 149 box->task = task; 151 150 } … … 161 160 bool ipc_phone_connect(phone_t *phone, answerbox_t *box) 162 161 { 163 bool connected;162 bool active; 164 163 165 164 mutex_lock(&phone->lock); 166 165 irq_spinlock_lock(&box->lock, true); 167 166 168 connected = box->active && (phone->state == IPC_PHONE_CONNECTING);169 if ( connected) {167 active = box->active; 168 if (active) { 170 169 phone->state = IPC_PHONE_CONNECTED; 171 170 phone->callee = box; … … 177 176 mutex_unlock(&phone->lock); 178 177 179 if (! connected) {178 if (!active) { 180 179 /* We still have phone->kobject's reference; drop it */ 181 180 kobject_put(phone->kobject); 182 181 } 183 182 184 return connected;183 return active; 185 184 } 186 185 … … 351 350 } else { 352 351 atomic_inc(&phone->active_calls); 353 if (call->callerbox)354 atomic_inc(&call->callerbox->active_calls);355 else356 atomic_inc(&caller->answerbox.active_calls);357 kobject_add_ref(phone->kobject);358 352 call->sender = caller; 359 353 call->active = true; … … 445 439 /** Disconnect phone from answerbox. 446 440 * 447 * This call leaves the phone in the hung-up state. The phone is destroyed when448 * its last active call is answered and there are no references to it.441 * This call leaves the phone in the HUNGUP state. The change to 'free' is done 442 * lazily later. 449 443 * 450 444 * @param phone Phone structure to be hung up. … … 569 563 list_remove(&request->ab_link); 570 564 atomic_dec(&request->caller_phone->active_calls); 571 atomic_dec(&box->active_calls);572 kobject_put(request->caller_phone->kobject);573 565 } else if (!list_empty(&box->calls)) { 574 566 /* Count received call */ … … 715 707 716 708 atomic_dec(&call->caller_phone->active_calls); 717 atomic_dec(&TASK->answerbox.active_calls);718 kobject_put(call->caller_phone->kobject);719 709 720 710 SYSIPC_OP(request_forget, call); … … 756 746 } 757 747 748 static bool phone_cap_wait_cb(cap_t *cap, void *arg) 749 { 750 phone_t *phone = cap->kobject->phone; 751 bool *restart = (bool *) arg; 752 753 mutex_lock(&phone->lock); 754 if ((phone->state == IPC_PHONE_HUNGUP) && 755 (atomic_get(&phone->active_calls) == 0)) { 756 phone->state = IPC_PHONE_FREE; 757 phone->callee = NULL; 758 } 759 760 /* 761 * We might have had some IPC_PHONE_CONNECTING phones at the beginning 762 * of ipc_cleanup(). Depending on whether these were forgotten or 763 * answered, they will eventually enter the IPC_PHONE_FREE or 764 * IPC_PHONE_CONNECTED states, respectively. In the latter case, the 765 * other side may slam the open phones at any time, in which case we 766 * will get an IPC_PHONE_SLAMMED phone. 767 */ 768 if ((phone->state == IPC_PHONE_CONNECTED) || 769 (phone->state == IPC_PHONE_SLAMMED)) { 770 mutex_unlock(&phone->lock); 771 ipc_phone_hangup(phone); 772 /* 773 * Now there may be one extra active call, which needs to be 774 * forgotten. 775 */ 776 ipc_forget_all_active_calls(); 777 *restart = true; 778 return false; 779 } 780 781 /* 782 * If the hangup succeeded, it has sent a HANGUP message, the IPC is now 783 * in HUNGUP state, we wait for the reply to come 784 */ 785 if (phone->state != IPC_PHONE_FREE) { 786 mutex_unlock(&phone->lock); 787 return false; 788 } 789 790 mutex_unlock(&phone->lock); 791 return true; 792 } 793 794 /** Wait for all answers to asynchronous calls to arrive. */ 795 static void ipc_wait_for_all_answered_calls(void) 796 { 797 call_t *call; 798 bool restart; 799 800 restart: 801 /* 802 * Go through all phones, until they are all free. 803 * Locking is needed as there may be connection handshakes in progress. 804 */ 805 restart = false; 806 if (caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 807 phone_cap_wait_cb, &restart)) { 808 /* Got into cleanup */ 809 return; 810 } 811 if (restart) 812 goto restart; 813 814 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 815 SYNCH_FLAGS_NONE); 816 assert(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF)); 817 818 SYSIPC_OP(answer_process, call); 819 820 kobject_put(call->kobject); 821 goto restart; 822 } 823 758 824 static bool phone_cap_cleanup_cb(cap_t *cap, void *arg) 759 825 { … … 764 830 cap_free(cap->task, cap->handle); 765 831 return true; 766 }767 768 /** Wait for all answers to asynchronous calls to arrive. */769 static void ipc_wait_for_all_answered_calls(void)770 {771 while (atomic_get(&TASK->answerbox.active_calls) != 0) {772 call_t *call = ipc_wait_for_call(&TASK->answerbox,773 SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);774 assert(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF));775 776 SYSIPC_OP(answer_process, call);777 778 kobject_put(call->kobject);779 780 /*781 * Now there may be some new phones and new hangup calls to782 * immediately forget.783 */784 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,785 phone_cap_cleanup_cb, NULL);786 ipc_forget_all_active_calls();787 }788 832 } 789 833 … … 825 869 irq_spinlock_unlock(&TASK->answerbox.lock, true); 826 870 827 /* Hangup all phones and destroy all phone capabilities*/871 /* Disconnect all our phones ('ipc_phone_hangup') */ 828 872 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 829 873 phone_cap_cleanup_cb, NULL); 830 874 831 /* Unsubscribe from any event notifications */875 /* Unsubscribe from any event notifications. */ 832 876 event_cleanup_answerbox(&TASK->answerbox); 833 877 … … 855 899 ipc_forget_all_active_calls(); 856 900 ipc_wait_for_all_answered_calls(); 857 858 assert(atomic_get(&TASK->answerbox.active_calls) == 0);859 901 } 860 902 … … 926 968 break; 927 969 case IPC_PHONE_HUNGUP: 928 printf("hung up to%p", phone->callee);970 printf("hung up by %p", phone->callee); 929 971 break; 930 972 default: … … 962 1004 irq_spinlock_lock(&task->lock, true); 963 1005 irq_spinlock_lock(&task->answerbox.lock, false); 964 965 printf("Active calls: %" PRIun "\n",966 atomic_get(&task->answerbox.active_calls));967 1006 968 1007 #ifdef __32_BITS__
Note:
See TracChangeset
for help on using the changeset viewer.