Changes in kernel/generic/src/ipc/ipc.c [cd529c4:f97f1e51] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
rcd529c4 rf97f1e51 71 71 { 72 72 memsetb(call, sizeof(*call), 0); 73 call->callerbox = &TASK->answerbox; 73 74 call->sender = TASK; 74 75 call->buffer = NULL; … … 119 120 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock"); 120 121 waitq_initialize(&box->wq); 122 link_initialize(&box->sync_box_link); 121 123 list_initialize(&box->connected_phones); 122 124 list_initialize(&box->calls); … … 161 163 } 162 164 165 /** Helper function to facilitate synchronous calls. 166 * 167 * @param phone Destination kernel phone structure. 168 * @param request Call structure with request. 169 * 170 * @return EOK on success or EINTR if the sleep was interrupted. 171 * 172 */ 173 int ipc_call_sync(phone_t *phone, call_t *request) 174 { 175 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0); 176 ipc_answerbox_init(sync_box, TASK); 177 178 /* 179 * Put the answerbox on the TASK's list of synchronous answerboxes so 180 * that it can be cleaned up if the call is interrupted. 181 */ 182 irq_spinlock_lock(&TASK->lock, true); 183 list_append(&sync_box->sync_box_link, &TASK->sync_boxes); 184 irq_spinlock_unlock(&TASK->lock, true); 185 186 /* We will receive data in a special box. */ 187 request->callerbox = sync_box; 188 189 ipc_call(phone, request); 190 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT, 191 SYNCH_FLAGS_INTERRUPTIBLE)) { 192 /* The answerbox and the call will be freed by ipc_cleanup(). */ 193 return EINTR; 194 } 195 196 /* 197 * The answer arrived without interruption so we can remove the 198 * answerbox from the TASK's list of synchronous answerboxes. 199 */ 200 irq_spinlock_lock(&TASK->lock, true); 201 list_remove(&sync_box->sync_box_link); 202 irq_spinlock_unlock(&TASK->lock, true); 203 204 slab_free(ipc_answerbox_slab, sync_box); 205 return EOK; 206 } 207 163 208 /** Answer a message which was not dispatched and is not listed in any queue. 164 209 * … … 169 214 static void _ipc_answer_free_call(call_t *call, bool selflocked) 170 215 { 171 answerbox_t *callerbox = &call->sender->answerbox;216 answerbox_t *callerbox = call->callerbox; 172 217 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 173 218 … … 561 606 ipc_cleanup_call_list(&TASK->answerbox.calls); 562 607 irq_spinlock_unlock(&TASK->answerbox.lock, true); 608 609 /* Wait for all answers to interrupted synchronous calls to arrive */ 610 ipl_t ipl = interrupts_disable(); 611 while (!list_empty(&TASK->sync_boxes)) { 612 answerbox_t *box = list_get_instance( 613 list_first(&TASK->sync_boxes), answerbox_t, sync_box_link); 614 615 list_remove(&box->sync_box_link); 616 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 617 SYNCH_FLAGS_NONE); 618 ipc_call_free(call); 619 slab_free(ipc_answerbox_slab, box); 620 } 621 interrupts_restore(ipl); 563 622 564 623 /* Wait for all answers to asynchronous calls to arrive */
Note:
See TracChangeset
for help on using the changeset viewer.