Changeset da1bafb in mainline for kernel/generic/src/ipc/ipc.c
- Timestamp:
- 2010-05-24T18:57:31Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0095368
- Parents:
- 666f492
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r666f492 rda1bafb 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 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 ipl_t ipl; 221 219 222 220 /* Count sent answer */ 223 ipl = interrupts_disable(); 224 spinlock_lock(&TASK->lock); 221 irq_spinlock_lock(&TASK->lock, true); 225 222 TASK->ipc_info.answer_sent++; 226 spinlock_unlock(&TASK->lock); 227 interrupts_restore(ipl); 228 223 irq_spinlock_unlock(&TASK->lock, true); 224 229 225 call->flags |= IPC_CALL_ANSWERED; 230 226 231 227 if (call->flags & IPC_CALL_FORWARDED) { 232 228 if (call->caller_phone) { … … 235 231 } 236 232 } 237 233 238 234 if (do_lock) 239 spinlock_lock(&callerbox->lock); 235 irq_spinlock_lock(&callerbox->lock, true); 236 240 237 list_append(&call->link, &callerbox->answers); 238 241 239 if (do_lock) 242 spinlock_unlock(&callerbox->lock); 240 irq_spinlock_unlock(&callerbox->lock, true); 241 243 242 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 244 243 } … … 246 245 /** Answer a message which is in a callee queue. 247 246 * 248 * @param box Answerbox that is answering the message. 249 * @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 * 250 250 */ 251 251 void ipc_answer(answerbox_t *box, call_t *call) 252 252 { 253 253 /* Remove from active box */ 254 spinlock_lock(&box->lock);254 irq_spinlock_lock(&box->lock, true); 255 255 list_remove(&call->link); 256 spinlock_unlock(&box->lock); 256 irq_spinlock_unlock(&box->lock, true); 257 257 258 /* Send back answer */ 258 259 _ipc_answer_free_call(call, false); … … 264 265 * message and sending it as a normal answer. 265 266 * 266 * @param phone Phone structure the call should appear to come from. 267 * @param call Call structure to be answered. 268 * @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 * 269 271 */ 270 272 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) … … 278 280 /** Unsafe unchecking version of ipc_call. 279 281 * 280 * @param phone Phone structure the call comes from. 281 * @param box Destination answerbox structure. 282 * @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 * 283 286 */ 284 287 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 285 288 { 286 ipl_t ipl;287 288 289 /* Count sent ipc call */ 289 ipl = interrupts_disable(); 290 spinlock_lock(&TASK->lock); 290 irq_spinlock_lock(&TASK->lock, true); 291 291 TASK->ipc_info.call_sent++; 292 spinlock_unlock(&TASK->lock); 293 interrupts_restore(ipl); 294 292 irq_spinlock_unlock(&TASK->lock, true); 293 295 294 if (!(call->flags & IPC_CALL_FORWARDED)) { 296 295 atomic_inc(&phone->active_calls); 297 296 call->data.phone = phone; 298 297 } 299 300 spinlock_lock(&box->lock);298 299 irq_spinlock_lock(&box->lock, true); 301 300 list_append(&call->link, &box->calls); 302 spinlock_unlock(&box->lock); 301 irq_spinlock_unlock(&box->lock, true); 302 303 303 waitq_wakeup(&box->wq, WAKEUP_FIRST); 304 304 } … … 306 306 /** Send an asynchronous request using a phone to an answerbox. 307 307 * 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. 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 * 313 314 */ 314 315 int ipc_call(phone_t *phone, call_t *call) 315 316 { 316 answerbox_t *box;317 318 317 mutex_lock(&phone->lock); 319 318 if (phone->state != IPC_PHONE_CONNECTED) { … … 328 327 ipc_backsend_err(phone, call, ENOENT); 329 328 } 329 330 330 return ENOENT; 331 331 } 332 box = phone->callee; 332 333 answerbox_t *box = phone->callee; 333 334 _ipc_call(phone, box, call); 334 335 … … 342 343 * lazily later. 343 344 * 344 * @param phone Phone structure to be hung up. 345 * 346 * @return Return 0 if the phone is disconnected. 347 * 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 * 348 350 */ 349 351 int ipc_phone_hangup(phone_t *phone) 350 352 { 351 answerbox_t *box;352 call_t *call;353 354 353 mutex_lock(&phone->lock); 355 354 if (phone->state == IPC_PHONE_FREE || … … 359 358 return -1; 360 359 } 361 box = phone->callee; 360 361 answerbox_t *box = phone->callee; 362 362 if (phone->state != IPC_PHONE_SLAMMED) { 363 363 /* Remove myself from answerbox */ 364 spinlock_lock(&box->lock);364 irq_spinlock_lock(&box->lock, true); 365 365 list_remove(&phone->link); 366 spinlock_unlock(&box->lock);367 368 call = ipc_call_alloc(0);366 irq_spinlock_unlock(&box->lock, true); 367 368 call_t *call = ipc_call_alloc(0); 369 369 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 370 370 call->flags |= IPC_CALL_DISCARD_ANSWER; 371 371 _ipc_call(phone, box, call); 372 372 } 373 373 374 374 phone->state = IPC_PHONE_HUNGUP; 375 375 mutex_unlock(&phone->lock); 376 376 377 377 return 0; 378 378 } … … 380 380 /** Forwards call from one answerbox to another one. 381 381 * 382 * @param call 383 * @param newphone 384 * @param oldbox 385 * @param mode 386 * 387 * @return Return0 if forwarding succeeded or an error code if388 * there waserror.389 * 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 * 390 390 * The return value serves only as an information for the forwarder, 391 391 * the original caller is notified automatically with EFORWARD. 392 * /393 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 394 { 395 ipl_t ipl; 396 392 * 393 */ 394 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, 395 unsigned int mode) 396 { 397 397 /* Count forwarded calls */ 398 ipl = interrupts_disable(); 399 spinlock_lock(&TASK->lock); 398 irq_spinlock_lock(&TASK->lock, true); 400 399 TASK->ipc_info.forwarded++; 401 spinlock_unlock(&TASK->lock); 402 interrupts_restore(ipl); 403 404 spinlock_lock(&oldbox->lock); 400 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 405 401 list_remove(&call->link); 406 spinlock_unlock(&oldbox->lock);407 402 irq_spinlock_unlock(&oldbox->lock, true); 403 408 404 if (mode & IPC_FF_ROUTE_FROM_ME) { 409 405 if (!call->caller_phone) … … 411 407 call->data.phone = newphone; 412 408 } 413 409 414 410 return ipc_call(newphone, call); 415 411 } … … 418 414 /** Wait for a phone call. 419 415 * 420 * @param box Answerbox expecting the call. 421 * @param usec Timeout in microseconds. See documentation for 422 * waitq_sleep_timeout() for decription of its special 423 * meaning. 424 * @param flags Select mode of sleep operation. See documentation for 425 * waitq_sleep_timeout() for description of its special 426 * meaning. 427 * @return Recived call structure or NULL. 428 * 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 * 429 426 * To distinguish between a call and an answer, have a look at call->flags. 430 */ 431 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) 432 430 { 433 431 call_t *request; 434 ipl_t ipl;435 432 uint64_t irq_cnt = 0; 436 433 uint64_t answer_cnt = 0; 437 434 uint64_t call_cnt = 0; 438 435 int rc; 439 436 440 437 restart: 441 438 rc = waitq_sleep_timeout(&box->wq, usec, flags); … … 443 440 return NULL; 444 441 445 spinlock_lock(&box->lock);442 irq_spinlock_lock(&box->lock, true); 446 443 if (!list_empty(&box->irq_notifs)) { 447 444 /* Count recieved IRQ notification */ 448 irq_cnt++; 449 450 ipl = interrupts_disable(); 451 spinlock_lock(&box->irq_lock); 452 445 irq_cnt++; 446 447 irq_spinlock_lock(&box->irq_lock, false); 448 453 449 request = list_get_instance(box->irq_notifs.next, call_t, link); 454 450 list_remove(&request->link); 455 456 spinlock_unlock(&box->irq_lock); 457 interrupts_restore(ipl); 451 452 irq_spinlock_unlock(&box->irq_lock, false); 458 453 } else if (!list_empty(&box->answers)) { 459 454 /* Count recieved answer */ 460 455 answer_cnt++; 461 456 462 457 /* Handle asynchronous answers */ 463 458 request = list_get_instance(box->answers.next, call_t, link); … … 467 462 /* Count recieved call */ 468 463 call_cnt++; 469 464 470 465 /* Handle requests */ 471 466 request = list_get_instance(box->calls.next, call_t, link); 472 467 list_remove(&request->link); 468 473 469 /* Append request to dispatch queue */ 474 470 list_append(&request->link, &box->dispatched_calls); 475 471 } else { 476 472 /* This can happen regularly after ipc_cleanup */ 477 spinlock_unlock(&box->lock);473 irq_spinlock_unlock(&box->lock, true); 478 474 goto restart; 479 475 } 480 spinlock_unlock(&box->lock); 481 482 ipl = interrupts_disable(); 483 spinlock_lock(&TASK->lock); 476 477 irq_spinlock_pass(&box->lock, &TASK->lock); 478 484 479 TASK->ipc_info.irq_notif_recieved += irq_cnt; 485 480 TASK->ipc_info.answer_recieved += answer_cnt; 486 481 TASK->ipc_info.call_recieved += call_cnt; 487 spinlock_unlock(&TASK->lock);488 i nterrupts_restore(ipl);489 482 483 irq_spinlock_unlock(&TASK->lock, true); 484 490 485 return request; 491 486 } … … 493 488 /** Answer all calls from list with EHANGUP answer. 494 489 * 495 * @param lst Head of the list to be cleaned up. 490 * @param lst Head of the list to be cleaned up. 491 * 496 492 */ 497 493 void ipc_cleanup_call_list(link_t *lst) 498 494 { 499 call_t *call;500 501 495 while (!list_empty(lst)) { 502 call = list_get_instance(lst->next, call_t, link);496 call_t *call = list_get_instance(lst->next, call_t, link); 503 497 if (call->buffer) 504 498 free(call->buffer); 499 505 500 list_remove(&call->link); 506 501 507 502 IPC_SET_RETVAL(call->data, EHANGUP); 508 503 _ipc_answer_free_call(call, true); … … 512 507 /** Disconnects all phones connected to an answerbox. 513 508 * 514 * @param box Answerbox to disconnect phones from. 515 * @param notify_box If true, the answerbox will get a hangup message for 516 * 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 * 517 513 */ 518 514 void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) … … 520 516 phone_t *phone; 521 517 DEADLOCK_PROBE_INIT(p_phonelck); 522 ipl_t ipl; 523 call_t *call; 524 525 call = notify_box ? ipc_call_alloc(0) : NULL; 526 518 519 call_t *call = notify_box ? ipc_call_alloc(0) : NULL; 520 527 521 /* Disconnect all phones connected to our answerbox */ 528 522 restart_phones: 529 ipl = interrupts_disable(); 530 spinlock_lock(&box->lock); 523 irq_spinlock_lock(&box->lock, true); 531 524 while (!list_empty(&box->connected_phones)) { 532 525 phone = list_get_instance(box->connected_phones.next, 533 526 phone_t, link); 534 527 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 535 spinlock_unlock(&box->lock); 536 interrupts_restore(ipl); 528 irq_spinlock_unlock(&box->lock, true); 537 529 DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); 538 530 goto restart_phones; … … 541 533 /* Disconnect phone */ 542 534 ASSERT(phone->state == IPC_PHONE_CONNECTED); 543 535 544 536 list_remove(&phone->link); 545 537 phone->state = IPC_PHONE_SLAMMED; 546 538 547 539 if (notify_box) { 548 540 mutex_unlock(&phone->lock); 549 spinlock_unlock(&box->lock); 550 interrupts_restore(ipl); 551 541 irq_spinlock_unlock(&box->lock, true); 542 552 543 /* 553 544 * Send one message to the answerbox for each … … 559 550 call->flags |= IPC_CALL_DISCARD_ANSWER; 560 551 _ipc_call(phone, box, call); 561 552 562 553 /* Allocate another call in advance */ 563 554 call = ipc_call_alloc(0); 564 555 565 556 /* Must start again */ 566 557 goto restart_phones; 567 558 } 568 559 569 560 mutex_unlock(&phone->lock); 570 561 } 571 572 spinlock_unlock(&box->lock); 573 interrupts_restore(ipl); 574 562 563 irq_spinlock_unlock(&box->lock, true); 564 575 565 /* Free unused call */ 576 566 if (call) … … 578 568 } 579 569 580 /** Clean sup all IPC communication of the current task.570 /** Clean up all IPC communication of the current task. 581 571 * 582 572 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 583 573 * have to change it as well if you want to cleanup other tasks than TASK. 574 * 584 575 */ 585 576 void ipc_cleanup(void) 586 577 { 587 int i;588 call_t *call;589 ipl_t ipl;590 591 578 /* Disconnect all our phones ('ipc_phone_hangup') */ 579 size_t i; 592 580 for (i = 0; i < IPC_MAX_PHONES; i++) 593 581 ipc_phone_hangup(&TASK->phones[i]); 594 582 595 583 /* Unsubscribe from any event notifications. */ 596 584 event_cleanup_answerbox(&TASK->answerbox); 597 585 598 586 /* Disconnect all connected irqs */ 599 587 ipc_irq_cleanup(&TASK->answerbox); 600 588 601 589 /* Disconnect all phones connected to our regular answerbox */ 602 590 ipc_answerbox_slam_phones(&TASK->answerbox, false); 603 591 604 592 #ifdef CONFIG_UDEBUG 605 593 /* Clean up kbox thread and communications */ 606 594 ipc_kbox_cleanup(); 607 595 #endif 608 596 609 597 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 610 spinlock_lock(&TASK->answerbox.lock);598 irq_spinlock_lock(&TASK->answerbox.lock, true); 611 599 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 612 600 ipc_cleanup_call_list(&TASK->answerbox.calls); 613 spinlock_unlock(&TASK->answerbox.lock);601 irq_spinlock_unlock(&TASK->answerbox.lock, true); 614 602 615 603 /* Wait for all answers to interrupted synchronous calls to arrive */ 616 ipl = interrupts_disable();604 ipl_t ipl = interrupts_disable(); 617 605 while (!list_empty(&TASK->sync_box_head)) { 618 606 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 619 607 answerbox_t, sync_box_link); 620 608 621 609 list_remove(&box->sync_box_link); 622 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,610 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 623 611 SYNCH_FLAGS_NONE); 624 612 ipc_call_free(call); … … 626 614 } 627 615 interrupts_restore(ipl); 628 616 629 617 /* Wait for all answers to asynchronous calls to arrive */ 630 while (1) { 631 /* Go through all phones, until all are FREE... */ 632 /* Locking not needed, no one else should modify 633 * 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 */ 634 624 for (i = 0; i < IPC_MAX_PHONES; i++) { 635 625 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && … … 639 629 } 640 630 641 /* Just for sure, we might have had some 642 * IPC_PHONE_CONNECTING phones */ 631 /* 632 * Just for sure, we might have had some 633 * IPC_PHONE_CONNECTING phones 634 */ 643 635 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 644 636 ipc_phone_hangup(&TASK->phones[i]); 645 /* If the hangup succeeded, it has sent a HANGUP 637 638 /* 639 * If the hangup succeeded, it has sent a HANGUP 646 640 * message, the IPC is now in HUNGUP state, we 647 * wait for the reply to come */ 641 * wait for the reply to come 642 */ 648 643 649 644 if (TASK->phones[i].state != IPC_PHONE_FREE) 650 645 break; 651 646 } 652 /* Voila, got into cleanup */ 647 648 /* Got into cleanup */ 653 649 if (i == IPC_MAX_PHONES) 654 650 break; 655 651 656 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,652 call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 657 653 SYNCH_FLAGS_NONE); 658 654 ASSERT((call->flags & IPC_CALL_ANSWERED) || … … 666 662 if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) 667 663 atomic_dec(&TASK->active_calls); 664 668 665 ipc_call_free(call); 669 666 } 670 667 } 671 668 672 673 /** Initilize IPC subsystem */ 669 /** Initilize IPC subsystem 670 * 671 */ 674 672 void ipc_init(void) 675 673 { … … 680 678 } 681 679 682 683 680 /** List answerbox contents. 684 681 * 685 * @param taskid Task ID. 682 * @param taskid Task ID. 683 * 686 684 */ 687 685 void ipc_print_task(task_id_t taskid) 688 686 { 689 task_t *task; 690 int i; 691 call_t *call; 692 link_t *tmp; 693 ipl_t ipl; 694 695 ipl = interrupts_disable(); 696 spinlock_lock(&tasks_lock); 697 task = task_find_by_id(taskid); 698 if (task) 699 spinlock_lock(&task->lock); 700 spinlock_unlock(&tasks_lock); 687 irq_spinlock_lock(&tasks_lock, true); 688 task_t *task = task_find_by_id(taskid); 689 701 690 if (!task) { 702 i nterrupts_restore(ipl);691 irq_spinlock_unlock(&tasks_lock, true); 703 692 return; 704 693 } 705 694 695 /* Hand-over-hand locking */ 696 irq_spinlock_exchange(&tasks_lock, &task->lock); 697 706 698 /* Print opened phones & details */ 707 699 printf("PHONE:\n"); 700 701 size_t i; 708 702 for (i = 0; i < IPC_MAX_PHONES; i++) { 709 703 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { … … 711 705 continue; 712 706 } 707 713 708 if (task->phones[i].state != IPC_PHONE_FREE) { 714 printf("%d: ", i); 709 printf("%" PRIs ": ", i); 710 715 711 switch (task->phones[i].state) { 716 712 case IPC_PHONE_CONNECTING: … … 718 714 break; 719 715 case IPC_PHONE_CONNECTED: 720 printf("connected to: %p ", 721 716 printf("connected to: %p ", 717 task->phones[i].callee); 722 718 break; 723 719 case IPC_PHONE_SLAMMED: 724 720 printf("slammed by: %p ", 725 721 task->phones[i].callee); 726 722 break; 727 723 case IPC_PHONE_HUNGUP: 728 724 printf("hung up - was: %p ", 729 725 task->phones[i].callee); 730 726 break; 731 727 default: 732 728 break; 733 729 } 734 printf("active: %ld\n", 730 731 printf("active: %" PRIun "\n", 735 732 atomic_get(&task->phones[i].active_calls)); 736 733 } 734 737 735 mutex_unlock(&task->phones[i].lock); 738 736 } 739 740 737 738 irq_spinlock_lock(&task->answerbox.lock, false); 739 740 link_t *cur; 741 741 742 /* Print answerbox - calls */ 742 spinlock_lock(&task->answerbox.lock);743 743 printf("ABOX - CALLS:\n"); 744 for ( tmp = task->answerbox.calls.next; tmp!= &task->answerbox.calls;745 tmp = tmp->next) {746 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); 747 747 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 748 748 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 754 754 call->flags); 755 755 } 756 /* Print answerbox - calls */ 756 757 /* Print answerbox - dispatched calls */ 757 758 printf("ABOX - DISPATCHED CALLS:\n"); 758 for ( tmp= task->answerbox.dispatched_calls.next;759 tmp != &task->answerbox.dispatched_calls;760 tmp = tmp->next) {761 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); 762 763 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 763 764 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 769 770 call->flags); 770 771 } 771 /* Print answerbox - calls */ 772 773 /* Print answerbox - answers */ 772 774 printf("ABOX - ANSWERS:\n"); 773 for ( tmp= task->answerbox.answers.next;774 tmp!= &task->answerbox.answers;775 tmp = tmp->next) {776 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); 777 779 printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun 778 780 " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", … … 782 784 call->flags); 783 785 } 784 785 spinlock_unlock(&task->answerbox.lock); 786 spinlock_unlock(&task->lock); 787 interrupts_restore(ipl); 786 787 irq_spinlock_unlock(&task->answerbox.lock, false); 788 irq_spinlock_unlock(&task->lock, true); 788 789 } 789 790
Note:
See TracChangeset
for help on using the changeset viewer.