Rev 3403 | Rev 3474 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3403 | Rev 3448 | ||
---|---|---|---|
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 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) ipc_call_free(call); |
|
- | 512 | } |
|
- | 513 | ||
- | 514 | /** Cleans up all IPC communication of the current task. |
|
- | 515 | * |
|
- | 516 | * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
|
- | 517 | * have to change it as well if you want to cleanup other tasks than TASK. |
|
- | 518 | */ |
|
- | 519 | void ipc_cleanup(void) |
|
- | 520 | { |
|
- | 521 | int i; |
|
- | 522 | call_t *call; |
|
- | 523 | ||
- | 524 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
|
- | 525 | for (i = 0; i < IPC_MAX_PHONES; i++) |
|
- | 526 | ipc_phone_hangup(&TASK->phones[i]); |
|
- | 527 | ||
- | 528 | /* Disconnect all connected irqs */ |
|
- | 529 | ipc_irq_cleanup(&TASK->answerbox); |
|
- | 530 | ||
- | 531 | /* Disconnect all phones connected to our regular answerbox */ |
|
- | 532 | ipc_answerbox_slam_phones(&TASK->answerbox, false); |
|
- | 533 | ||
- | 534 | #ifdef CONFIG_UDEBUG |
|
- | 535 | /* Clean up kbox thread and communications */ |
|
- | 536 | ipc_kbox_cleanup(); |
|
- | 537 | #endif |
|
- | 538 | ||
484 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
539 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
- | 540 | spinlock_lock(&TASK->answerbox.lock); |
|
485 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
541 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
486 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
542 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
487 | spinlock_unlock(&TASK->answerbox.lock); |
543 | spinlock_unlock(&TASK->answerbox.lock); |
488 | 544 | ||
489 | /* Wait for all async answers to arrive */ |
545 | /* Wait for all async answers to arrive */ |