Changeset c621f4aa in mainline for kernel/generic/src/ipc/ipc.c
- Timestamp:
- 2010-07-25T10:11:13Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 377cce8
- Parents:
- 24a2517 (diff), a2da43c (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
-
kernel/generic/src/ipc/ipc.c (modified) (37 diffs)
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r24a2517 rc621f4aa 66 66 /** Initialize a call structure. 67 67 * 68 * @param call Call structure to be initialized. 68 * @param call Call structure to be initialized. 69 * 69 70 */ 70 71 static void _ipc_call_init(call_t *call) … … 77 78 78 79 /** Allocate and initialize a call structure. 79 * 80 * 80 81 * The call is initialized, so that the reply will be directed to 81 82 * TASK->answerbox. 82 83 * 83 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 84 * 85 * @return If flags permit it, return NULL, or initialized kernel 86 * call structure. 87 */ 88 call_t *ipc_call_alloc(int flags) 89 { 90 call_t *call; 91 92 call = slab_alloc(ipc_call_slab, flags); 84 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 85 * 86 * @return If flags permit it, return NULL, or initialized kernel 87 * call structure. 88 * 89 */ 90 call_t *ipc_call_alloc(unsigned int flags) 91 { 92 call_t *call = slab_alloc(ipc_call_slab, flags); 93 93 if (call) 94 94 _ipc_call_init(call); 95 95 96 96 return call; 97 97 } … … 99 99 /** Deallocate a call structure. 100 100 * 101 * @param call Call structure to be freed. 101 * @param call Call structure to be freed. 102 * 102 103 */ 103 104 void ipc_call_free(call_t *call) … … 111 112 /** Initialize an answerbox structure. 112 113 * 113 * @param box Answerbox structure to be initialized. 114 * @param task Task to which the answerbox belongs. 114 * @param box Answerbox structure to be initialized. 115 * @param task Task to which the answerbox belongs. 116 * 115 117 */ 116 118 void ipc_answerbox_init(answerbox_t *box, task_t *task) 117 119 { 118 spinlock_initialize(&box->lock, "ipc_box_lock");119 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");120 irq_spinlock_initialize(&box->lock, "ipc.box.lock"); 121 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock"); 120 122 waitq_initialize(&box->wq); 121 123 link_initialize(&box->sync_box_link); … … 131 133 /** Connect a phone to an answerbox. 132 134 * 133 * @param phone Initialized phone structure. 134 * @param box Initialized answerbox structure. 135 * @param phone Initialized phone structure. 136 * @param box Initialized answerbox structure. 137 * 135 138 */ 136 139 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 137 140 { 138 141 mutex_lock(&phone->lock); 139 142 140 143 phone->state = IPC_PHONE_CONNECTED; 141 144 phone->callee = box; 142 143 spinlock_lock(&box->lock);145 146 irq_spinlock_lock(&box->lock, true); 144 147 list_append(&phone->link, &box->connected_phones); 145 spinlock_unlock(&box->lock);146 148 irq_spinlock_unlock(&box->lock, true); 149 147 150 mutex_unlock(&phone->lock); 148 151 } … … 150 153 /** Initialize a phone structure. 151 154 * 152 * @param phone Phone structure to be initialized. 155 * @param phone Phone structure to be initialized. 156 * 153 157 */ 154 158 void ipc_phone_init(phone_t *phone) … … 162 166 /** Helper function to facilitate synchronous calls. 163 167 * 164 * @param phone Destination kernel phone structure. 165 * @param request Call structure with request. 166 * 167 * @return EOK on success or EINTR if the sleep was interrupted. 168 * @param phone Destination kernel phone structure. 169 * @param request Call structure with request. 170 * 171 * @return EOK on success or EINTR if the sleep was interrupted. 172 * 168 173 */ 169 174 int ipc_call_sync(phone_t *phone, call_t *request) 170 175 { 171 answerbox_t *sync_box; 172 ipl_t ipl; 173 174 sync_box = slab_alloc(ipc_answerbox_slab, 0); 176 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0); 175 177 ipc_answerbox_init(sync_box, TASK); 176 178 177 179 /* 178 180 * Put the answerbox on the TASK's list of synchronous answerboxes so 179 181 * that it can be cleaned up if the call is interrupted. 180 182 */ 181 ipl = interrupts_disable(); 182 spinlock_lock(&TASK->lock); 183 irq_spinlock_lock(&TASK->lock, true); 183 184 list_append(&sync_box->sync_box_link, &TASK->sync_box_head); 184 spinlock_unlock(&TASK->lock); 185 interrupts_restore(ipl); 186 185 irq_spinlock_unlock(&TASK->lock, true); 186 187 187 /* We will receive data in a special box. */ 188 188 request->callerbox = sync_box; 189 189 190 190 ipc_call(phone, request); 191 191 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT, 192 192 SYNCH_FLAGS_INTERRUPTIBLE)) { 193 /* The answerbox and the call will be freed by ipc_cleanup(). */193 /* The answerbox and the call will be freed by ipc_cleanup(). */ 194 194 return EINTR; 195 195 } 196 196 197 197 /* 198 198 * The answer arrived without interruption so we can remove the 199 199 * answerbox from the TASK's list of synchronous answerboxes. 200 200 */ 201 (void) interrupts_disable(); 202 spinlock_lock(&TASK->lock); 201 irq_spinlock_lock(&TASK->lock, true); 203 202 list_remove(&sync_box->sync_box_link); 204 spinlock_unlock(&TASK->lock); 205 interrupts_restore(ipl); 206 203 irq_spinlock_unlock(&TASK->lock, true); 204 207 205 slab_free(ipc_answerbox_slab, sync_box); 208 206 return EOK; … … 211 209 /** Answer a message which was not dispatched and is not listed in any queue. 212 210 * 213 * @param call Call structure to be answered. 214 * @param selflocked If true, then TASK->answebox is locked. 211 * @param call Call structure to be answered. 212 * @param selflocked If true, then TASK->answebox is locked. 213 * 215 214 */ 216 215 static void _ipc_answer_free_call(call_t *call, bool selflocked) … … 218 217 answerbox_t *callerbox = call->callerbox; 219 218 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 220 219 220 /* Count sent answer */ 221 irq_spinlock_lock(&TASK->lock, true); 222 TASK->ipc_info.answer_sent++; 223 irq_spinlock_unlock(&TASK->lock, true); 224 221 225 call->flags |= IPC_CALL_ANSWERED; 222 226 223 227 if (call->flags & IPC_CALL_FORWARDED) { 224 228 if (call->caller_phone) { … … 227 231 } 228 232 } 229 233 230 234 if (do_lock) 231 spinlock_lock(&callerbox->lock); 235 irq_spinlock_lock(&callerbox->lock, true); 236 232 237 list_append(&call->link, &callerbox->answers); 238 233 239 if (do_lock) 234 spinlock_unlock(&callerbox->lock); 240 irq_spinlock_unlock(&callerbox->lock, true); 241 235 242 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 236 243 } … … 238 245 /** Answer a message which is in a callee queue. 239 246 * 240 * @param box Answerbox that is answering the message. 241 * @param call Modified request that is being sent back. 247 * @param box Answerbox that is answering the message. 248 * @param call Modified request that is being sent back. 249 * 242 250 */ 243 251 void ipc_answer(answerbox_t *box, call_t *call) 244 252 { 245 253 /* Remove from active box */ 246 spinlock_lock(&box->lock);254 irq_spinlock_lock(&box->lock, true); 247 255 list_remove(&call->link); 248 spinlock_unlock(&box->lock); 256 irq_spinlock_unlock(&box->lock, true); 257 249 258 /* Send back answer */ 250 259 _ipc_answer_free_call(call, false); … … 256 265 * message and sending it as a normal answer. 257 266 * 258 * @param phone Phone structure the call should appear to come from. 259 * @param call Call structure to be answered. 260 * @param err Return value to be used for the answer. 267 * @param phone Phone structure the call should appear to come from. 268 * @param call Call structure to be answered. 269 * @param err Return value to be used for the answer. 270 * 261 271 */ 262 272 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) … … 270 280 /** Unsafe unchecking version of ipc_call. 271 281 * 272 * @param phone Phone structure the call comes from. 273 * @param box Destination answerbox structure. 274 * @param call Call structure with request. 282 * @param phone Phone structure the call comes from. 283 * @param box Destination answerbox structure. 284 * @param call Call structure with request. 285 * 275 286 */ 276 287 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 277 288 { 289 /* Count sent ipc call */ 290 irq_spinlock_lock(&TASK->lock, true); 291 TASK->ipc_info.call_sent++; 292 irq_spinlock_unlock(&TASK->lock, true); 293 278 294 if (!(call->flags & IPC_CALL_FORWARDED)) { 279 295 atomic_inc(&phone->active_calls); 280 296 call->data.phone = phone; 281 297 } 282 283 spinlock_lock(&box->lock);298 299 irq_spinlock_lock(&box->lock, true); 284 300 list_append(&call->link, &box->calls); 285 spinlock_unlock(&box->lock); 301 irq_spinlock_unlock(&box->lock, true); 302 286 303 waitq_wakeup(&box->wq, WAKEUP_FIRST); 287 304 } … … 289 306 /** Send an asynchronous request using a phone to an answerbox. 290 307 * 291 * @param phone Phone structure the call comes from and which is 292 * connected to the destination answerbox. 293 * @param call Call structure with request. 294 * 295 * @return Return 0 on success, ENOENT on error. 308 * @param phone Phone structure the call comes from and which is 309 * connected to the destination answerbox. 310 * @param call Call structure with request. 311 * 312 * @return Return 0 on success, ENOENT on error. 313 * 296 314 */ 297 315 int ipc_call(phone_t *phone, call_t *call) 298 316 { 299 answerbox_t *box;300 301 317 mutex_lock(&phone->lock); 302 318 if (phone->state != IPC_PHONE_CONNECTED) { … … 311 327 ipc_backsend_err(phone, call, ENOENT); 312 328 } 329 313 330 return ENOENT; 314 331 } 315 box = phone->callee; 332 333 answerbox_t *box = phone->callee; 316 334 _ipc_call(phone, box, call); 317 335 … … 325 343 * lazily later. 326 344 * 327 * @param phone Phone structure to be hung up. 328 * 329 * @return Return 0 if the phone is disconnected. 330 * Return -1 if the phone was already disconnected. 345 * @param phone Phone structure to be hung up. 346 * 347 * @return 0 if the phone is disconnected. 348 * @return -1 if the phone was already disconnected. 349 * 331 350 */ 332 351 int ipc_phone_hangup(phone_t *phone) 333 352 { 334 answerbox_t *box;335 call_t *call;336 337 353 mutex_lock(&phone->lock); 338 354 if (phone->state == IPC_PHONE_FREE || … … 342 358 return -1; 343 359 } 344 box = phone->callee; 360 361 answerbox_t *box = phone->callee; 345 362 if (phone->state != IPC_PHONE_SLAMMED) { 346 363 /* Remove myself from answerbox */ 347 spinlock_lock(&box->lock);364 irq_spinlock_lock(&box->lock, true); 348 365 list_remove(&phone->link); 349 spinlock_unlock(&box->lock);350 351 call = ipc_call_alloc(0);366 irq_spinlock_unlock(&box->lock, true); 367 368 call_t *call = ipc_call_alloc(0); 352 369 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 353 370 call->flags |= IPC_CALL_DISCARD_ANSWER; 354 371 _ipc_call(phone, box, call); 355 372 } 356 373 357 374 phone->state = IPC_PHONE_HUNGUP; 358 375 mutex_unlock(&phone->lock); 359 376 360 377 return 0; 361 378 } … … 363 380 /** Forwards call from one answerbox to another one. 364 381 * 365 * @param call Call structure to be redirected.366 * @param newphone Phone structure to target answerbox.367 * @param oldbox Old answerbox structure.368 * @param mode Flags that specify mode of the forward operation.369 * 370 * @return Return0 if forwarding succeeded or an error code if371 * there waserror.372 * 382 * @param call Call structure to be redirected. 383 * @param newphone Phone structure to target answerbox. 384 * @param oldbox Old answerbox structure. 385 * @param mode Flags that specify mode of the forward operation. 386 * 387 * @return 0 if forwarding succeeded or an error code if 388 * there was an error. 389 * 373 390 * The return value serves only as an information for the forwarder, 374 391 * the original caller is notified automatically with EFORWARD. 375 */ 376 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 377 { 378 spinlock_lock(&oldbox->lock); 392 * 393 */ 394 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, 395 unsigned int mode) 396 { 397 /* Count forwarded calls */ 398 irq_spinlock_lock(&TASK->lock, true); 399 TASK->ipc_info.forwarded++; 400 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 379 401 list_remove(&call->link); 380 spinlock_unlock(&oldbox->lock);381 402 irq_spinlock_unlock(&oldbox->lock, true); 403 382 404 if (mode & IPC_FF_ROUTE_FROM_ME) { 383 405 if (!call->caller_phone) … … 385 407 call->data.phone = newphone; 386 408 } 387 409 388 410 return ipc_call(newphone, call); 389 411 } … … 392 414 /** Wait for a phone call. 393 415 * 394 * @param box Answerbox expecting the call. 395 * @param usec Timeout in microseconds. See documentation for 396 * waitq_sleep_timeout() for decription of its special 397 * meaning. 398 * @param flags Select mode of sleep operation. See documentation for 399 * waitq_sleep_timeout() for description of its special 400 * meaning. 401 * @return Recived call structure or NULL. 402 * 416 * @param box Answerbox expecting the call. 417 * @param usec Timeout in microseconds. See documentation for 418 * waitq_sleep_timeout() for decription of its special 419 * meaning. 420 * @param flags Select mode of sleep operation. See documentation for 421 * waitq_sleep_timeout() for description of its special 422 * meaning. 423 * 424 * @return Recived call structure or NULL. 425 * 403 426 * To distinguish between a call and an answer, have a look at call->flags. 404 */ 405 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 427 * 428 */ 429 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags) 406 430 { 407 431 call_t *request; 408 ipl_t ipl; 432 uint64_t irq_cnt = 0; 433 uint64_t answer_cnt = 0; 434 uint64_t call_cnt = 0; 409 435 int rc; 410 436 411 437 restart: 412 438 rc = waitq_sleep_timeout(&box->wq, usec, flags); … … 414 440 return NULL; 415 441 416 spinlock_lock(&box->lock);442 irq_spinlock_lock(&box->lock, true); 417 443 if (!list_empty(&box->irq_notifs)) { 418 ipl = interrupts_disable(); 419 spinlock_lock(&box->irq_lock); 420 444 /* Count received IRQ notification */ 445 irq_cnt++; 446 447 irq_spinlock_lock(&box->irq_lock, false); 448 421 449 request = list_get_instance(box->irq_notifs.next, call_t, link); 422 450 list_remove(&request->link); 423 424 spinlock_unlock(&box->irq_lock); 425 interrupts_restore(ipl); 451 452 irq_spinlock_unlock(&box->irq_lock, false); 426 453 } else if (!list_empty(&box->answers)) { 454 /* Count received answer */ 455 answer_cnt++; 456 427 457 /* Handle asynchronous answers */ 428 458 request = list_get_instance(box->answers.next, call_t, link); … … 430 460 atomic_dec(&request->data.phone->active_calls); 431 461 } else if (!list_empty(&box->calls)) { 462 /* Count received call */ 463 call_cnt++; 464 432 465 /* Handle requests */ 433 466 request = list_get_instance(box->calls.next, call_t, link); 434 467 list_remove(&request->link); 468 435 469 /* Append request to dispatch queue */ 436 470 list_append(&request->link, &box->dispatched_calls); 437 471 } else { 438 472 /* This can happen regularly after ipc_cleanup */ 439 spinlock_unlock(&box->lock);473 irq_spinlock_unlock(&box->lock, true); 440 474 goto restart; 441 475 } 442 spinlock_unlock(&box->lock); 476 477 irq_spinlock_pass(&box->lock, &TASK->lock); 478 479 TASK->ipc_info.irq_notif_received += irq_cnt; 480 TASK->ipc_info.answer_received += answer_cnt; 481 TASK->ipc_info.call_received += call_cnt; 482 483 irq_spinlock_unlock(&TASK->lock, true); 484 443 485 return request; 444 486 } … … 446 488 /** Answer all calls from list with EHANGUP answer. 447 489 * 448 * @param lst Head of the list to be cleaned up. 490 * @param lst Head of the list to be cleaned up. 491 * 449 492 */ 450 493 void ipc_cleanup_call_list(link_t *lst) 451 494 { 452 call_t *call;453 454 495 while (!list_empty(lst)) { 455 call = list_get_instance(lst->next, call_t, link);496 call_t *call = list_get_instance(lst->next, call_t, link); 456 497 if (call->buffer) 457 498 free(call->buffer); 499 458 500 list_remove(&call->link); 459 501 460 502 IPC_SET_RETVAL(call->data, EHANGUP); 461 503 _ipc_answer_free_call(call, true); … … 465 507 /** Disconnects all phones connected to an answerbox. 466 508 * 467 * @param box Answerbox to disconnect phones from. 468 * @param notify_box If true, the answerbox will get a hangup message for 469 * each disconnected phone. 509 * @param box Answerbox to disconnect phones from. 510 * @param notify_box If true, the answerbox will get a hangup message for 511 * each disconnected phone. 512 * 470 513 */ 471 514 void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) … … 473 516 phone_t *phone; 474 517 DEADLOCK_PROBE_INIT(p_phonelck); 475 ipl_t ipl; 476 call_t *call; 477 478 call = notify_box ? ipc_call_alloc(0) : NULL; 479 518 519 call_t *call = notify_box ? ipc_call_alloc(0) : NULL; 520 480 521 /* Disconnect all phones connected to our answerbox */ 481 522 restart_phones: 482 ipl = interrupts_disable(); 483 spinlock_lock(&box->lock); 523 irq_spinlock_lock(&box->lock, true); 484 524 while (!list_empty(&box->connected_phones)) { 485 525 phone = list_get_instance(box->connected_phones.next, 486 526 phone_t, link); 487 527 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 488 spinlock_unlock(&box->lock); 489 interrupts_restore(ipl); 528 irq_spinlock_unlock(&box->lock, true); 490 529 DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); 491 530 goto restart_phones; … … 494 533 /* Disconnect phone */ 495 534 ASSERT(phone->state == IPC_PHONE_CONNECTED); 496 535 497 536 list_remove(&phone->link); 498 537 phone->state = IPC_PHONE_SLAMMED; 499 538 500 539 if (notify_box) { 501 540 mutex_unlock(&phone->lock); 502 spinlock_unlock(&box->lock); 503 interrupts_restore(ipl); 504 541 irq_spinlock_unlock(&box->lock, true); 542 505 543 /* 506 544 * Send one message to the answerbox for each … … 512 550 call->flags |= IPC_CALL_DISCARD_ANSWER; 513 551 _ipc_call(phone, box, call); 514 552 515 553 /* Allocate another call in advance */ 516 554 call = ipc_call_alloc(0); 517 555 518 556 /* Must start again */ 519 557 goto restart_phones; 520 558 } 521 559 522 560 mutex_unlock(&phone->lock); 523 561 } 524 525 spinlock_unlock(&box->lock); 526 interrupts_restore(ipl); 527 562 563 irq_spinlock_unlock(&box->lock, true); 564 528 565 /* Free unused call */ 529 566 if (call) … … 531 568 } 532 569 533 /** Clean sup all IPC communication of the current task.570 /** Clean up all IPC communication of the current task. 534 571 * 535 572 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 536 573 * have to change it as well if you want to cleanup other tasks than TASK. 574 * 537 575 */ 538 576 void ipc_cleanup(void) 539 577 { 540 int i;541 call_t *call;542 ipl_t ipl;543 544 578 /* Disconnect all our phones ('ipc_phone_hangup') */ 579 size_t i; 545 580 for (i = 0; i < IPC_MAX_PHONES; i++) 546 581 ipc_phone_hangup(&TASK->phones[i]); 547 582 548 583 /* Unsubscribe from any event notifications. */ 549 584 event_cleanup_answerbox(&TASK->answerbox); 550 585 551 586 /* Disconnect all connected irqs */ 552 587 ipc_irq_cleanup(&TASK->answerbox); 553 588 554 589 /* Disconnect all phones connected to our regular answerbox */ 555 590 ipc_answerbox_slam_phones(&TASK->answerbox, false); 556 591 557 592 #ifdef CONFIG_UDEBUG 558 593 /* Clean up kbox thread and communications */ 559 594 ipc_kbox_cleanup(); 560 595 #endif 561 596 562 597 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 563 spinlock_lock(&TASK->answerbox.lock);598 irq_spinlock_lock(&TASK->answerbox.lock, true); 564 599 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 565 600 ipc_cleanup_call_list(&TASK->answerbox.calls); 566 spinlock_unlock(&TASK->answerbox.lock);601 irq_spinlock_unlock(&TASK->answerbox.lock, true); 567 602 568 603 /* Wait for all answers to interrupted synchronous calls to arrive */ 569 ipl = interrupts_disable();604 ipl_t ipl = interrupts_disable(); 570 605 while (!list_empty(&TASK->sync_box_head)) { 571 606 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 572 607 answerbox_t, sync_box_link); 573 608 574 609 list_remove(&box->sync_box_link); 575 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,610 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 576 611 SYNCH_FLAGS_NONE); 577 612 ipc_call_free(call); … … 579 614 } 580 615 interrupts_restore(ipl); 581 616 582 617 /* Wait for all answers to asynchronous calls to arrive */ 583 while (1) { 584 /* Go through all phones, until all are FREE... */ 585 /* Locking not needed, no one else should modify 586 * it, when we are in cleanup */ 618 while (true) { 619 /* 620 * Go through all phones, until they are all FREE 621 * Locking is not needed, no one else should modify 622 * it when we are in cleanup 623 */ 587 624 for (i = 0; i < IPC_MAX_PHONES; i++) { 588 625 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && … … 592 629 } 593 630 594 /* Just for sure, we might have had some 595 * IPC_PHONE_CONNECTING phones */ 631 /* 632 * Just for sure, we might have had some 633 * IPC_PHONE_CONNECTING phones 634 */ 596 635 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 597 636 ipc_phone_hangup(&TASK->phones[i]); 598 /* If the hangup succeeded, it has sent a HANGUP 637 638 /* 639 * If the hangup succeeded, it has sent a HANGUP 599 640 * message, the IPC is now in HUNGUP state, we 600 * wait for the reply to come */ 641 * wait for the reply to come 642 */ 601 643 602 644 if (TASK->phones[i].state != IPC_PHONE_FREE) 603 645 break; 604 646 } 605 /* Voila, got into cleanup */ 647 648 /* Got into cleanup */ 606 649 if (i == IPC_MAX_PHONES) 607 650 break; 608 651 609 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,652 call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 610 653 SYNCH_FLAGS_NONE); 611 654 ASSERT((call->flags & IPC_CALL_ANSWERED) || … … 619 662 if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) 620 663 atomic_dec(&TASK->active_calls); 664 621 665 ipc_call_free(call); 622 666 } 623 667 } 624 668 625 626 /** Initilize IPC subsystem */ 669 /** Initilize IPC subsystem 670 * 671 */ 627 672 void ipc_init(void) 628 673 { … … 633 678 } 634 679 635 636 680 /** List answerbox contents. 637 681 * 638 * @param taskid Task ID. 682 * @param taskid Task ID. 683 * 639 684 */ 640 685 void ipc_print_task(task_id_t taskid) 641 686 { 642 task_t *task; 643 int i; 644 call_t *call; 645 link_t *tmp; 646 647 spinlock_lock(&tasks_lock); 648 task = task_find_by_id(taskid); 649 if (task) 650 spinlock_lock(&task->lock); 651 spinlock_unlock(&tasks_lock); 652 if (!task) 687 irq_spinlock_lock(&tasks_lock, true); 688 task_t *task = task_find_by_id(taskid); 689 690 if (!task) { 691 irq_spinlock_unlock(&tasks_lock, true); 653 692 return; 654 693 } 694 695 /* Hand-over-hand locking */ 696 irq_spinlock_exchange(&tasks_lock, &task->lock); 697 655 698 /* Print opened phones & details */ 656 699 printf("PHONE:\n"); 700 701 size_t i; 657 702 for (i = 0; i < IPC_MAX_PHONES; i++) { 658 703 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { … … 660 705 continue; 661 706 } 707 662 708 if (task->phones[i].state != IPC_PHONE_FREE) { 663 printf("%d: ", i); 709 printf("%" PRIs ": ", i); 710 664 711 switch (task->phones[i].state) { 665 712 case IPC_PHONE_CONNECTING: … … 667 714 break; 668 715 case IPC_PHONE_CONNECTED: 669 printf("connected to: %p ", 670 task->phones[i].callee);716 printf("connected to: %p ", 717 task->phones[i].callee); 671 718 break; 672 719 case IPC_PHONE_SLAMMED: 673 720 printf("slammed by: %p ", 674 task->phones[i].callee);721 task->phones[i].callee); 675 722 break; 676 723 case IPC_PHONE_HUNGUP: 677 724 printf("hung up - was: %p ", 678 task->phones[i].callee);725 task->phones[i].callee); 679 726 break; 680 727 default: 681 728 break; 682 729 } 683 printf("active: %ld\n", 730 731 printf("active: %" PRIun "\n", 684 732 atomic_get(&task->phones[i].active_calls)); 685 733 } 734 686 735 mutex_unlock(&task->phones[i].lock); 687 736 } 688 689 737 738 irq_spinlock_lock(&task->answerbox.lock, false); 739 740 link_t *cur; 741 690 742 /* Print answerbox - calls */ 691 spinlock_lock(&task->answerbox.lock);692 743 printf("ABOX - CALLS:\n"); 693 for ( tmp = task->answerbox.calls.next; tmp!= &task->answerbox.calls;694 tmp = tmp->next) {695 call = list_get_instance(tmp, call_t, link);744 for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls; 745 cur = cur->next) { 746 call_t *call = list_get_instance(cur, call_t, link); 696 747 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 697 748 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 703 754 call->flags); 704 755 } 705 /* Print answerbox - calls */ 756 757 /* Print answerbox - dispatched calls */ 706 758 printf("ABOX - DISPATCHED CALLS:\n"); 707 for ( tmp= task->answerbox.dispatched_calls.next;708 tmp != &task->answerbox.dispatched_calls;709 tmp = tmp->next) {710 call = list_get_instance(tmp, call_t, link);759 for (cur = task->answerbox.dispatched_calls.next; 760 cur != &task->answerbox.dispatched_calls; 761 cur = cur->next) { 762 call_t *call = list_get_instance(cur, call_t, link); 711 763 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 712 764 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 718 770 call->flags); 719 771 } 720 /* Print answerbox - calls */ 772 773 /* Print answerbox - answers */ 721 774 printf("ABOX - ANSWERS:\n"); 722 for ( tmp= task->answerbox.answers.next;723 tmp!= &task->answerbox.answers;724 tmp = tmp->next) {725 call = list_get_instance(tmp, call_t, link);775 for (cur = task->answerbox.answers.next; 776 cur != &task->answerbox.answers; 777 cur = cur->next) { 778 call_t *call = list_get_instance(cur, call_t, link); 726 779 printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun 727 780 " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", … … 731 784 call->flags); 732 785 } 733 734 spinlock_unlock(&task->answerbox.lock);735 spinlock_unlock(&task->lock);786 787 irq_spinlock_unlock(&task->answerbox.lock, false); 788 irq_spinlock_unlock(&task->lock, true); 736 789 } 737 790
Note:
See TracChangeset
for help on using the changeset viewer.
