Changes in kernel/generic/src/ipc/ipc.c [c713aa56:287e83f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
rc713aa56 r287e83f 62 62 63 63 static slab_cache_t *ipc_call_slab; 64 static slab_cache_t *ipc_answerbox_slab;65 64 66 65 /** Initialize a call structure. … … 97 96 } 98 97 98 /** Initialize a statically allocated call structure. 99 * 100 * @param call Statically allocated kernel call structure to be 101 * initialized. 102 */ 103 void ipc_call_static_init(call_t *call) 104 { 105 _ipc_call_init(call); 106 call->flags |= IPC_CALL_STATIC_ALLOC; 107 } 108 99 109 /** Deallocate a call structure. 100 110 * … … 103 113 void ipc_call_free(call_t *call) 104 114 { 115 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 105 116 /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */ 106 117 if (call->buffer) … … 119 130 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); 120 131 waitq_initialize(&box->wq); 121 link_initialize(&box->sync_box_link);122 132 list_initialize(&box->connected_phones); 123 133 list_initialize(&box->calls); … … 169 179 int ipc_call_sync(phone_t *phone, call_t *request) 170 180 { 171 answerbox_t *sync_box; 172 ipl_t ipl; 173 174 sync_box = slab_alloc(ipc_answerbox_slab, 0); 175 ipc_answerbox_init(sync_box, TASK); 176 177 /* 178 * Put the answerbox on the TASK's list of synchronous answerboxes so 179 * that it can be cleaned up if the call is interrupted. 180 */ 181 ipl = interrupts_disable(); 182 spinlock_lock(&TASK->lock); 183 list_append(&sync_box->sync_box_link, &TASK->sync_box_head); 184 spinlock_unlock(&TASK->lock); 185 interrupts_restore(ipl); 181 answerbox_t sync_box; 182 183 ipc_answerbox_init(&sync_box, TASK); 186 184 187 185 /* We will receive data in a special box. */ 188 request->callerbox = sync_box;186 request->callerbox = &sync_box; 189 187 190 188 ipc_call(phone, request); 191 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT, 192 SYNCH_FLAGS_INTERRUPTIBLE)) { 193 /* The answerbox and the call will be freed by ipc_cleanup(). */ 189 if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, 190 SYNCH_FLAGS_INTERRUPTIBLE)) 194 191 return EINTR; 195 }196 197 /*198 * The answer arrived without interruption so we can remove the199 * answerbox from the TASK's list of synchronous answerboxes.200 */201 (void) interrupts_disable();202 spinlock_lock(&TASK->lock);203 list_remove(&sync_box->sync_box_link);204 spinlock_unlock(&TASK->lock);205 interrupts_restore(ipl);206 207 slab_free(ipc_answerbox_slab, sync_box);208 192 return EOK; 209 193 } … … 212 196 * 213 197 * @param call Call structure to be answered. 214 * @param selflocked If true, then TASK->answebox is locked. 215 */ 216 static void _ipc_answer_free_call(call_t *call, bool selflocked) 198 */ 199 static void _ipc_answer_free_call(call_t *call) 217 200 { 218 201 answerbox_t *callerbox = call->callerbox; 219 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));220 202 221 203 call->flags |= IPC_CALL_ANSWERED; … … 228 210 } 229 211 230 if (do_lock) 231 spinlock_lock(&callerbox->lock); 212 spinlock_lock(&callerbox->lock); 232 213 list_append(&call->link, &callerbox->answers); 233 if (do_lock) 234 spinlock_unlock(&callerbox->lock); 214 spinlock_unlock(&callerbox->lock); 235 215 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 236 216 } … … 248 228 spinlock_unlock(&box->lock); 249 229 /* Send back answer */ 250 _ipc_answer_free_call(call , false);230 _ipc_answer_free_call(call); 251 231 } 252 232 … … 265 245 atomic_inc(&phone->active_calls); 266 246 IPC_SET_RETVAL(call->data, err); 267 _ipc_answer_free_call(call , false);247 _ipc_answer_free_call(call); 268 248 } 269 249 … … 304 284 if (call->flags & IPC_CALL_FORWARDED) { 305 285 IPC_SET_RETVAL(call->data, EFORWARD); 306 _ipc_answer_free_call(call , false);286 _ipc_answer_free_call(call); 307 287 } else { 308 288 if (phone->state == IPC_PHONE_HUNGUP) … … 459 439 460 440 IPC_SET_RETVAL(call->data, EHANGUP); 461 _ipc_answer_free_call(call , true);441 _ipc_answer_free_call(call); 462 442 } 463 443 } … … 540 520 int i; 541 521 call_t *call; 542 ipl_t ipl;543 522 544 523 /* Disconnect all our phones ('ipc_phone_hangup') */ … … 566 545 spinlock_unlock(&TASK->answerbox.lock); 567 546 568 /* Wait for all answers to interrupted synchronous calls to arrive */ 569 ipl = interrupts_disable(); 570 while (!list_empty(&TASK->sync_box_head)) { 571 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 572 answerbox_t, sync_box_link); 573 574 list_remove(&box->sync_box_link); 575 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 576 SYNCH_FLAGS_NONE); 577 ipc_call_free(call); 578 slab_free(ipc_answerbox_slab, box); 579 } 580 interrupts_restore(ipl); 581 582 /* Wait for all answers to asynchronous calls to arrive */ 547 /* Wait for all async answers to arrive */ 583 548 while (1) { 584 549 /* Go through all phones, until all are FREE... */ … … 587 552 for (i = 0; i < IPC_MAX_PHONES; i++) { 588 553 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 589 atomic_get(&TASK->phones[i].active_calls) == 0) {554 atomic_get(&TASK->phones[i].active_calls) == 0) 590 555 TASK->phones[i].state = IPC_PHONE_FREE; 591 TASK->phones[i].callee = NULL;592 }593 556 594 557 /* Just for sure, we might have had some … … 611 574 ASSERT((call->flags & IPC_CALL_ANSWERED) || 612 575 (call->flags & IPC_CALL_NOTIF)); 576 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 613 577 614 578 /* … … 629 593 ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, 630 594 NULL, 0); 631 ipc_answerbox_slab = slab_cache_create("ipc_answerbox",632 sizeof(answerbox_t), 0, NULL, NULL, 0);633 595 } 634 596
Note:
See TracChangeset
for help on using the changeset viewer.