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 | } |