Changeset 3b3e776 in mainline for kernel/generic/src/ipc/ipc.c
- Timestamp:
- 2010-02-05T10:57:50Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0358da0
- Parents:
- 3f085132 (diff), b4cbef1 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r3f085132 r3b3e776 62 62 63 63 static slab_cache_t *ipc_call_slab; 64 static slab_cache_t *ipc_answerbox_slab; 64 65 65 66 /** Initialize a call structure. … … 96 97 } 97 98 98 /** Initialize a statically allocated call structure.99 *100 * @param call Statically allocated kernel call structure to be101 * 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 109 99 /** Deallocate a call structure. 110 100 * … … 113 103 void ipc_call_free(call_t *call) 114 104 { 115 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));116 105 /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */ 117 106 if (call->buffer) … … 130 119 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); 131 120 waitq_initialize(&box->wq); 121 link_initialize(&box->sync_box_link); 132 122 list_initialize(&box->connected_phones); 133 123 list_initialize(&box->calls); … … 179 169 int ipc_call_sync(phone_t *phone, call_t *request) 180 170 { 181 answerbox_t sync_box; 182 183 ipc_answerbox_init(&sync_box, TASK); 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); 184 186 185 187 /* We will receive data in a special box. */ 186 request->callerbox = &sync_box;188 request->callerbox = sync_box; 187 189 188 190 ipc_call(phone, request); 189 if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, 190 SYNCH_FLAGS_INTERRUPTIBLE)) 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(). */ 191 194 return EINTR; 195 } 196 197 /* 198 * The answer arrived without interruption so we can remove the 199 * 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); 192 208 return EOK; 193 209 } … … 196 212 * 197 213 * @param call Call structure to be answered. 198 */ 199 static void _ipc_answer_free_call(call_t *call) 214 * @param selflocked If true, then TASK->answebox is locked. 215 */ 216 static void _ipc_answer_free_call(call_t *call, bool selflocked) 200 217 { 201 218 answerbox_t *callerbox = call->callerbox; 219 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 202 220 203 221 call->flags |= IPC_CALL_ANSWERED; … … 210 228 } 211 229 212 spinlock_lock(&callerbox->lock); 230 if (do_lock) 231 spinlock_lock(&callerbox->lock); 213 232 list_append(&call->link, &callerbox->answers); 214 spinlock_unlock(&callerbox->lock); 233 if (do_lock) 234 spinlock_unlock(&callerbox->lock); 215 235 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 216 236 } … … 228 248 spinlock_unlock(&box->lock); 229 249 /* Send back answer */ 230 _ipc_answer_free_call(call );250 _ipc_answer_free_call(call, false); 231 251 } 232 252 … … 245 265 atomic_inc(&phone->active_calls); 246 266 IPC_SET_RETVAL(call->data, err); 247 _ipc_answer_free_call(call );267 _ipc_answer_free_call(call, false); 248 268 } 249 269 … … 284 304 if (call->flags & IPC_CALL_FORWARDED) { 285 305 IPC_SET_RETVAL(call->data, EFORWARD); 286 _ipc_answer_free_call(call );306 _ipc_answer_free_call(call, false); 287 307 } else { 288 308 if (phone->state == IPC_PHONE_HUNGUP) … … 439 459 440 460 IPC_SET_RETVAL(call->data, EHANGUP); 441 _ipc_answer_free_call(call );461 _ipc_answer_free_call(call, true); 442 462 } 443 463 } … … 520 540 int i; 521 541 call_t *call; 542 ipl_t ipl; 522 543 523 544 /* Disconnect all our phones ('ipc_phone_hangup') */ … … 545 566 spinlock_unlock(&TASK->answerbox.lock); 546 567 547 /* Wait for all async answers to arrive */ 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 */ 548 583 while (1) { 549 584 /* Go through all phones, until all are FREE... */ … … 552 587 for (i = 0; i < IPC_MAX_PHONES; i++) { 553 588 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 554 atomic_get(&TASK->phones[i].active_calls) == 0) 589 atomic_get(&TASK->phones[i].active_calls) == 0) { 555 590 TASK->phones[i].state = IPC_PHONE_FREE; 591 TASK->phones[i].callee = NULL; 592 } 556 593 557 594 /* Just for sure, we might have had some … … 574 611 ASSERT((call->flags & IPC_CALL_ANSWERED) || 575 612 (call->flags & IPC_CALL_NOTIF)); 576 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));577 613 578 614 /* … … 593 629 ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, 594 630 NULL, 0); 631 ipc_answerbox_slab = slab_cache_create("ipc_answerbox", 632 sizeof(answerbox_t), 0, NULL, NULL, 0); 595 633 } 596 634
Note:
See TracChangeset
for help on using the changeset viewer.