Rev 3386 | Rev 4263 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3386 | Rev 4153 | ||
|---|---|---|---|
| Line 41... | Line 41... | ||
| 41 | #include <synch/spinlock.h> |
41 | #include <synch/spinlock.h> |
| 42 | #include <synch/mutex.h> |
42 | #include <synch/mutex.h> |
| 43 | #include <synch/waitq.h> |
43 | #include <synch/waitq.h> |
| 44 | #include <synch/synch.h> |
44 | #include <synch/synch.h> |
| 45 | #include <ipc/ipc.h> |
45 | #include <ipc/ipc.h> |
| - | 46 | #include <ipc/kbox.h> |
|
| 46 | #include <errno.h> |
47 | #include <errno.h> |
| 47 | #include <mm/slab.h> |
48 | #include <mm/slab.h> |
| 48 | #include <arch.h> |
49 | #include <arch.h> |
| 49 | #include <proc/task.h> |
50 | #include <proc/task.h> |
| 50 | #include <memstr.h> |
51 | #include <memstr.h> |
| 51 | #include <debug.h> |
52 | #include <debug.h> |
| 52 | 53 | ||
| 53 | #include <print.h> |
54 | #include <print.h> |
| - | 55 | #include <console/console.h> |
|
| 54 | #include <proc/thread.h> |
56 | #include <proc/thread.h> |
| 55 | #include <arch/interrupt.h> |
57 | #include <arch/interrupt.h> |
| 56 | #include <ipc/irq.h> |
58 | #include <ipc/irq.h> |
| 57 | 59 | ||
| 58 | /** Open channel that is assigned automatically to new tasks */ |
60 | /** Open channel that is assigned automatically to new tasks */ |
| Line 199... | Line 201... | ||
| 199 | answerbox_t *callerbox = call->callerbox; |
201 | answerbox_t *callerbox = call->callerbox; |
| 200 | 202 | ||
| 201 | call->flags |= IPC_CALL_ANSWERED; |
203 | call->flags |= IPC_CALL_ANSWERED; |
| 202 | 204 | ||
| 203 | if (call->flags & IPC_CALL_FORWARDED) { |
205 | if (call->flags & IPC_CALL_FORWARDED) { |
| 204 | if (call->data.caller_phone) { |
206 | if (call->caller_phone) { |
| 205 | /* Demasquerade the caller phone. */ |
207 | /* Demasquerade the caller phone. */ |
| 206 | call->data.phone = call->data.caller_phone; |
208 | call->data.phone = call->caller_phone; |
| 207 | } |
209 | } |
| 208 | } |
210 | } |
| 209 | 211 | ||
| 210 | spinlock_lock(&callerbox->lock); |
212 | spinlock_lock(&callerbox->lock); |
| 211 | list_append(&call->link, &callerbox->answers); |
213 | list_append(&call->link, &callerbox->answers); |
| Line 358... | Line 360... | ||
| 358 | spinlock_lock(&oldbox->lock); |
360 | spinlock_lock(&oldbox->lock); |
| 359 | list_remove(&call->link); |
361 | list_remove(&call->link); |
| 360 | spinlock_unlock(&oldbox->lock); |
362 | spinlock_unlock(&oldbox->lock); |
| 361 | 363 | ||
| 362 | if (mode & IPC_FF_ROUTE_FROM_ME) { |
364 | if (mode & IPC_FF_ROUTE_FROM_ME) { |
| 363 | if (!call->data.caller_phone) |
365 | if (!call->caller_phone) |
| 364 | call->data.caller_phone = call->data.phone; |
366 | call->caller_phone = call->data.phone; |
| 365 | call->data.phone = newphone; |
367 | call->data.phone = newphone; |
| 366 | } |
368 | } |
| 367 | 369 | ||
| 368 | return ipc_call(newphone, call); |
370 | return ipc_call(newphone, call); |
| 369 | } |
371 | } |
| Line 425... | Line 427... | ||
| 425 | 427 | ||
| 426 | /** Answer all calls from list with EHANGUP answer. |
428 | /** Answer all calls from list with EHANGUP answer. |
| 427 | * |
429 | * |
| 428 | * @param lst Head of the list to be cleaned up. |
430 | * @param lst Head of the list to be cleaned up. |
| 429 | */ |
431 | */ |
| 430 | static void ipc_cleanup_call_list(link_t *lst) |
432 | void ipc_cleanup_call_list(link_t *lst) |
| 431 | { |
433 | { |
| 432 | call_t *call; |
434 | call_t *call; |
| 433 | 435 | ||
| 434 | while (!list_empty(lst)) { |
436 | while (!list_empty(lst)) { |
| 435 | call = list_get_instance(lst->next, call_t, link); |
437 | call = list_get_instance(lst->next, call_t, link); |
| Line 440... | Line 442... | ||
| 440 | IPC_SET_RETVAL(call->data, EHANGUP); |
442 | IPC_SET_RETVAL(call->data, EHANGUP); |
| 441 | _ipc_answer_free_call(call); |
443 | _ipc_answer_free_call(call); |
| 442 | } |
444 | } |
| 443 | } |
445 | } |
| 444 | 446 | ||
| 445 | /** Cleans up all IPC communication of the current task. |
447 | /** Disconnects all phones connected to an answerbox. |
| 446 | * |
448 | * |
| 447 | * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
449 | * @param box Answerbox to disconnect phones from. |
| 448 | * have to change it as well if you want to cleanup other tasks than TASK. |
450 | * @param notify_box If true, the answerbox will get a hangup message for |
| - | 451 | * each disconnected phone. |
|
| 449 | */ |
452 | */ |
| 450 | void ipc_cleanup(void) |
453 | void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) |
| 451 | { |
454 | { |
| 452 | int i; |
- | |
| 453 | call_t *call; |
- | |
| 454 | phone_t *phone; |
455 | phone_t *phone; |
| 455 | DEADLOCK_PROBE_INIT(p_phonelck); |
456 | DEADLOCK_PROBE_INIT(p_phonelck); |
| - | 457 | ipl_t ipl; |
|
| - | 458 | call_t *call; |
|
| 456 | 459 | ||
| 457 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
- | |
| 458 | for (i = 0; i < IPC_MAX_PHONES; i++) |
- | |
| 459 | ipc_phone_hangup(&TASK->phones[i]); |
- | |
| 460 | - | ||
| 461 | /* Disconnect all connected irqs */ |
460 | call = notify_box ? ipc_call_alloc(0) : NULL; |
| 462 | ipc_irq_cleanup(&TASK->answerbox); |
- | |
| 463 | 461 | ||
| 464 | /* Disconnect all phones connected to our answerbox */ |
462 | /* Disconnect all phones connected to our answerbox */ |
| 465 | restart_phones: |
463 | restart_phones: |
| - | 464 | ipl = interrupts_disable(); |
|
| 466 | spinlock_lock(&TASK->answerbox.lock); |
465 | spinlock_lock(&box->lock); |
| 467 | while (!list_empty(&TASK->answerbox.connected_phones)) { |
466 | while (!list_empty(&box->connected_phones)) { |
| 468 | phone = list_get_instance(TASK->answerbox.connected_phones.next, |
467 | phone = list_get_instance(box->connected_phones.next, |
| 469 | phone_t, link); |
468 | phone_t, link); |
| 470 | if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
469 | if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
| 471 | spinlock_unlock(&TASK->answerbox.lock); |
470 | spinlock_unlock(&box->lock); |
| - | 471 | interrupts_restore(ipl); |
|
| 472 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
472 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
| 473 | goto restart_phones; |
473 | goto restart_phones; |
| 474 | } |
474 | } |
| 475 | 475 | ||
| 476 | /* Disconnect phone */ |
476 | /* Disconnect phone */ |
| 477 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
477 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
| 478 | phone->state = IPC_PHONE_SLAMMED; |
- | |
| - | 478 | ||
| 479 | list_remove(&phone->link); |
479 | list_remove(&phone->link); |
| - | 480 | phone->state = IPC_PHONE_SLAMMED; |
|
| - | 481 | ||
| - | 482 | if (notify_box) { |
|
| - | 483 | mutex_unlock(&phone->lock); |
|
| - | 484 | spinlock_unlock(&box->lock); |
|
| - | 485 | interrupts_restore(ipl); |
|
| - | 486 | ||
| - | 487 | /* |
|
| - | 488 | * Send one message to the answerbox for each |
|
| - | 489 | * phone. Used to make sure the kbox thread |
|
| - | 490 | * wakes up after the last phone has been |
|
| - | 491 | * disconnected. |
|
| - | 492 | */ |
|
| - | 493 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
|
| - | 494 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
|
| - | 495 | _ipc_call(phone, box, call); |
|
| - | 496 | ||
| - | 497 | /* Allocate another call in advance */ |
|
| - | 498 | call = ipc_call_alloc(0); |
|
| - | 499 | ||
| - | 500 | /* Must start again */ |
|
| - | 501 | goto restart_phones; |
|
| - | 502 | } |
|
| 480 | 503 | ||
| 481 | mutex_unlock(&phone->lock); |
504 | mutex_unlock(&phone->lock); |
| 482 | } |
505 | } |
| 483 | 506 | ||
| - | 507 | spinlock_unlock(&box->lock); |
|
| - | 508 | interrupts_restore(ipl); |
|
| - | 509 | ||
| - | 510 | /* Free unused call */ |
|
| - | 511 | if (call) |
|
| - | 512 | ipc_call_free(call); |
|
| - | 513 | } |
|
| - | 514 | ||
| - | 515 | /** Cleans up all IPC communication of the current task. |
|
| - | 516 | * |
|
| - | 517 | * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
|
| - | 518 | * have to change it as well if you want to cleanup other tasks than TASK. |
|
| - | 519 | */ |
|
| - | 520 | void ipc_cleanup(void) |
|
| - | 521 | { |
|
| - | 522 | int i; |
|
| - | 523 | call_t *call; |
|
| - | 524 | ||
| - | 525 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
|
| - | 526 | for (i = 0; i < IPC_MAX_PHONES; i++) |
|
| - | 527 | ipc_phone_hangup(&TASK->phones[i]); |
|
| - | 528 | ||
| - | 529 | /* Disconnect all connected irqs */ |
|
| - | 530 | ipc_irq_cleanup(&TASK->answerbox); |
|
| - | 531 | ||
| - | 532 | /* Disconnect all phones connected to our regular answerbox */ |
|
| - | 533 | ipc_answerbox_slam_phones(&TASK->answerbox, false); |
|
| - | 534 | ||
| - | 535 | #ifdef CONFIG_UDEBUG |
|
| - | 536 | /* Clean up kbox thread and communications */ |
|
| - | 537 | ipc_kbox_cleanup(); |
|
| - | 538 | #endif |
|
| - | 539 | ||
| 484 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
540 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
| - | 541 | spinlock_lock(&TASK->answerbox.lock); |
|
| 485 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
542 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
| 486 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
543 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
| 487 | spinlock_unlock(&TASK->answerbox.lock); |
544 | spinlock_unlock(&TASK->answerbox.lock); |
| 488 | 545 | ||
| 489 | /* Wait for all async answers to arrive */ |
546 | /* Wait for all async answers to arrive */ |
| Line 515... | Line 572... | ||
| 515 | SYNCH_FLAGS_NONE); |
572 | SYNCH_FLAGS_NONE); |
| 516 | ASSERT((call->flags & IPC_CALL_ANSWERED) || |
573 | ASSERT((call->flags & IPC_CALL_ANSWERED) || |
| 517 | (call->flags & IPC_CALL_NOTIF)); |
574 | (call->flags & IPC_CALL_NOTIF)); |
| 518 | ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); |
575 | ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); |
| 519 | 576 | ||
| - | 577 | /* |
|
| - | 578 | * Record the receipt of this call in the current task's counter |
|
| - | 579 | * of active calls. IPC_M_PHONE_HUNGUP calls do not contribute |
|
| - | 580 | * to this counter so do not record answers to them either. |
|
| - | 581 | */ |
|
| - | 582 | if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) |
|
| 520 | atomic_dec(&TASK->active_calls); |
583 | atomic_dec(&TASK->active_calls); |
| 521 | ipc_call_free(call); |
584 | ipc_call_free(call); |
| 522 | } |
585 | } |
| 523 | } |
586 | } |
| 524 | 587 | ||
| 525 | 588 | ||
| Line 590... | Line 653... | ||
| 590 | printf("ABOX - CALLS:\n"); |
653 | printf("ABOX - CALLS:\n"); |
| 591 | for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; |
654 | for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; |
| 592 | tmp = tmp->next) { |
655 | tmp = tmp->next) { |
| 593 | call = list_get_instance(tmp, call_t, link); |
656 | call = list_get_instance(tmp, call_t, link); |
| 594 | printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
657 | printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
| 595 | " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
658 | " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
| 596 | " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
659 | " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
| - | 660 | call->sender->taskid, |
|
| 597 | IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
661 | IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
| 598 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
662 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
| 599 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
663 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
| 600 | call->flags); |
664 | call->flags); |
| 601 | } |
665 | } |
| Line 604... | Line 668... | ||
| 604 | for (tmp = task->answerbox.dispatched_calls.next; |
668 | for (tmp = task->answerbox.dispatched_calls.next; |
| 605 | tmp != &task->answerbox.dispatched_calls; |
669 | tmp != &task->answerbox.dispatched_calls; |
| 606 | tmp = tmp->next) { |
670 | tmp = tmp->next) { |
| 607 | call = list_get_instance(tmp, call_t, link); |
671 | call = list_get_instance(tmp, call_t, link); |
| 608 | printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
672 | printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
| 609 | " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
673 | " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
| 610 | " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
674 | " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
| - | 675 | call->sender->taskid, |
|
| 611 | IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
676 | IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
| 612 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
677 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
| 613 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
678 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
| 614 | call->flags); |
679 | call->flags); |
| 615 | } |
680 | } |
| 616 | /* Print answerbox - calls */ |
681 | /* Print answerbox - calls */ |
| 617 | printf("ABOX - ANSWERS:\n"); |
682 | printf("ABOX - ANSWERS:\n"); |
| 618 | for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers; |
683 | for (tmp = task->answerbox.answers.next; |
| - | 684 | tmp != &task->answerbox.answers; |
|
| 619 | tmp = tmp->next) { |
685 | tmp = tmp->next) { |
| 620 | call = list_get_instance(tmp, call_t, link); |
686 | call = list_get_instance(tmp, call_t, link); |
| 621 | printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun |
687 | printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun |
| 622 | " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
688 | " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
| 623 | call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
689 | call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
| 624 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
690 | IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
| 625 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
691 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
| 626 | call->flags); |
692 | call->flags); |
| 627 | } |
693 | } |