Changeset 67f11a0 in mainline for kernel/generic/src/ipc/ipc.c
- Timestamp:
- 2018-03-15T17:40:20Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 530f2de, e9e4068
- Parents:
- 30f1a25 (diff), a36f442 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jakub Jermar <jakub@…> (2018-03-15 17:25:56)
- git-committer:
- Jakub Jermar <jakub@…> (2018-03-15 17:40:20)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r30f1a25 r67f11a0 63 63 static void ipc_forget_call(call_t *); 64 64 65 /** Open channel that is assigned automatically to new tasks*/66 answerbox_t *ipc_ phone_0 = NULL;65 /** Answerbox that new tasks are automatically connected to */ 66 answerbox_t *ipc_box_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); 149 150 box->task = task; 150 151 } … … 160 161 bool ipc_phone_connect(phone_t *phone, answerbox_t *box) 161 162 { 162 bool active;163 bool connected; 163 164 164 165 mutex_lock(&phone->lock); 165 166 irq_spinlock_lock(&box->lock, true); 166 167 167 active = box->active;168 if ( active) {168 connected = box->active && (phone->state == IPC_PHONE_CONNECTING); 169 if (connected) { 169 170 phone->state = IPC_PHONE_CONNECTED; 170 171 phone->callee = box; … … 176 177 mutex_unlock(&phone->lock); 177 178 178 if (! active) {179 if (!connected) { 179 180 /* We still have phone->kobject's reference; drop it */ 180 181 kobject_put(phone->kobject); 181 182 } 182 183 183 return active;184 return connected; 184 185 } 185 186 … … 350 351 } else { 351 352 atomic_inc(&phone->active_calls); 353 if (call->callerbox) 354 atomic_inc(&call->callerbox->active_calls); 355 else 356 atomic_inc(&caller->answerbox.active_calls); 357 kobject_add_ref(phone->kobject); 352 358 call->sender = caller; 353 359 call->active = true; … … 439 445 /** Disconnect phone from answerbox. 440 446 * 441 * This call leaves the phone in the HUNGUP state. The change to 'free' is done442 * lazily later.447 * This call leaves the phone in the hung-up state. The phone is destroyed when 448 * its last active call is answered and there are no references to it. 443 449 * 444 450 * @param phone Phone structure to be hung up. … … 563 569 list_remove(&request->ab_link); 564 570 atomic_dec(&request->caller_phone->active_calls); 571 atomic_dec(&box->active_calls); 572 kobject_put(request->caller_phone->kobject); 565 573 } else if (!list_empty(&box->calls)) { 566 574 /* Count received call */ … … 707 715 708 716 atomic_dec(&call->caller_phone->active_calls); 717 atomic_dec(&TASK->answerbox.active_calls); 718 kobject_put(call->caller_phone->kobject); 709 719 710 720 SYSIPC_OP(request_forget, call); … … 746 756 } 747 757 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 beginning762 * of ipc_cleanup(). Depending on whether these were forgotten or763 * answered, they will eventually enter the IPC_PHONE_FREE or764 * IPC_PHONE_CONNECTED states, respectively. In the latter case, the765 * other side may slam the open phones at any time, in which case we766 * 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 be774 * 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 now783 * in HUNGUP state, we wait for the reply to come784 */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 824 758 static bool phone_cap_cleanup_cb(cap_t *cap, void *arg) 825 759 { … … 830 764 cap_free(cap->task, cap->handle); 831 765 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 to 782 * 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 } 832 788 } 833 789 … … 869 825 irq_spinlock_unlock(&TASK->answerbox.lock, true); 870 826 871 /* Disconnect all our phones ('ipc_phone_hangup')*/827 /* Hangup all phones and destroy all phone capabilities */ 872 828 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 873 829 phone_cap_cleanup_cb, NULL); 874 830 875 /* Unsubscribe from any event notifications .*/831 /* Unsubscribe from any event notifications */ 876 832 event_cleanup_answerbox(&TASK->answerbox); 877 833 … … 899 855 ipc_forget_all_active_calls(); 900 856 ipc_wait_for_all_answered_calls(); 857 858 assert(atomic_get(&TASK->answerbox.active_calls) == 0); 901 859 } 902 860 … … 968 926 break; 969 927 case IPC_PHONE_HUNGUP: 970 printf("hung up by%p", phone->callee);928 printf("hung up to %p", phone->callee); 971 929 break; 972 930 default: … … 1004 962 irq_spinlock_lock(&task->lock, true); 1005 963 irq_spinlock_lock(&task->answerbox.lock, false); 964 965 printf("Active calls: %" PRIun "\n", 966 atomic_get(&task->answerbox.active_calls)); 1006 967 1007 968 #ifdef __32_BITS__
Note:
See TracChangeset
for help on using the changeset viewer.