Rev 3033 | Rev 3035 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3033 | Rev 3034 | ||
|---|---|---|---|
| Line 492... | Line 492... | ||
| 492 | if (call) ipc_call_free(call); |
492 | if (call) ipc_call_free(call); |
| 493 | } |
493 | } |
| 494 | 494 | ||
| 495 | static void ipc_kbox_cleanup() |
495 | static void ipc_kbox_cleanup() |
| 496 | { |
496 | { |
| 497 | ipl_t ipl; |
- | |
| 498 | bool have_kb_thread; |
497 | bool have_kb_thread; |
| 499 | 498 | ||
| 500 | /* Only hold kb_cleanup_lock while setting kb_finished - this is enough */ |
499 | /* Only hold kb_cleanup_lock while setting kb_finished - this is enough */ |
| 501 | ipl = interrupts_disable(); |
- | |
| 502 | spinlock_lock(&TASK->kb_cleanup_lock); |
500 | mutex_lock(&TASK->kb_cleanup_lock); |
| 503 | - | ||
| 504 | TASK->kb_finished = true; |
501 | TASK->kb_finished = true; |
| 505 | - | ||
| 506 | spinlock_unlock(&TASK->kb_cleanup_lock); |
502 | mutex_unlock(&TASK->kb_cleanup_lock); |
| 507 | interrupts_restore(ipl); |
- | |
| 508 | 503 | ||
| 509 | have_kb_thread = (TASK->kb_thread != NULL); |
504 | have_kb_thread = (TASK->kb_thread != NULL); |
| 510 | 505 | ||
| 511 | /* From now on nobody will try to connect phones or attach kbox threads */ |
506 | /* From now on nobody will try to connect phones or attach kbox threads */ |
| 512 | 507 | ||
| Line 782... | Line 777... | ||
| 782 | { |
777 | { |
| 783 | int newphid; |
778 | int newphid; |
| 784 | task_t *ta; |
779 | task_t *ta; |
| 785 | thread_t *kb_thread; |
780 | thread_t *kb_thread; |
| 786 | ipl_t ipl; |
781 | ipl_t ipl; |
| 787 | bool had_kb_thread; |
- | |
| 788 | - | ||
| 789 | newphid = phone_alloc(); |
- | |
| 790 | if (newphid < 0) |
- | |
| 791 | return ELIMIT; |
- | |
| 792 | 782 | ||
| 793 | ipl = interrupts_disable(); |
783 | ipl = interrupts_disable(); |
| 794 | spinlock_lock(&tasks_lock); |
784 | spinlock_lock(&tasks_lock); |
| 795 | 785 | ||
| 796 | ta = task_find_by_id(taskid); |
786 | ta = task_find_by_id(taskid); |
| Line 798... | Line 788... | ||
| 798 | spinlock_unlock(&tasks_lock); |
788 | spinlock_unlock(&tasks_lock); |
| 799 | interrupts_restore(ipl); |
789 | interrupts_restore(ipl); |
| 800 | return ENOENT; |
790 | return ENOENT; |
| 801 | } |
791 | } |
| 802 | 792 | ||
| - | 793 | atomic_inc(&ta->refcount); |
|
| - | 794 | ||
| - | 795 | spinlock_unlock(&tasks_lock); |
|
| - | 796 | interrupts_restore(ipl); |
|
| - | 797 | ||
| 803 | spinlock_lock(&ta->kb_cleanup_lock); |
798 | mutex_lock(&ta->kb_cleanup_lock); |
| - | 799 | ||
| - | 800 | if (atomic_predec(&ta->refcount) == 0) { |
|
| - | 801 | mutex_unlock(&ta->kb_cleanup_lock); |
|
| - | 802 | task_destroy(ta); |
|
| - | 803 | return ENOENT; |
|
| - | 804 | } |
|
| 804 | 805 | ||
| 805 | if (ta->kb_finished != false) { |
806 | if (ta->kb_finished != false) { |
| 806 | spinlock_unlock(&ta->kb_cleanup_lock); |
807 | mutex_unlock(&ta->kb_cleanup_lock); |
| 807 | spinlock_unlock(&tasks_lock); |
- | |
| 808 | interrupts_restore(ipl); |
- | |
| 809 | return EINVAL; |
808 | return EINVAL; |
| 810 | } |
809 | } |
| 811 | 810 | ||
| 812 | spinlock_unlock(&tasks_lock); |
811 | newphid = phone_alloc(); |
| 813 | - | ||
| 814 | /* |
- | |
| 815 | * Only ta->kb_cleanup_lock left. Since we checked the value |
812 | if (newphid < 0) { |
| 816 | * of ta->kb_finished, this suffices to ensure the task's exitence. |
- | |
| 817 | * (And that it didn't start kbox cleanup yet). It also ensures |
813 | mutex_unlock(&ta->kb_cleanup_lock); |
| 818 | * mutual exclusion with other threads running this function. |
814 | return ELIMIT; |
| 819 | */ |
815 | } |
| 820 | 816 | ||
| 821 | /* Connect the newly allocated phone to the kbox */ |
817 | /* Connect the newly allocated phone to the kbox */ |
| 822 | ipc_phone_connect(&TASK->phones[newphid], &ta->kernel_box); |
818 | ipc_phone_connect(&TASK->phones[newphid], &ta->kernel_box); |
| 823 | 819 | ||
| 824 | had_kb_thread = (ta->kb_thread != NULL); |
820 | if (ta->kb_thread != NULL) { |
| 825 | - | ||
| 826 | /* |
- | |
| 827 | * Release all locks. This is an optimisation, that makes |
- | |
| 828 | * unnecessary thread creation very unlikely. |
- | |
| 829 | */ |
- | |
| 830 | spinlock_unlock(&ta->kb_cleanup_lock); |
821 | mutex_unlock(&ta->kb_cleanup_lock); |
| 831 | interrupts_restore(ipl); |
822 | return newphid; |
| - | 823 | } |
|
| 832 | 824 | ||
| 833 | /* Create a kbox thread */ |
825 | /* Create a kbox thread */ |
| 834 | - | ||
| 835 | kb_thread = thread_create(kbox_thread_proc, |
826 | kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0, "kbox", false); |
| 836 | NULL, ta, THREAD_FLAG_NOATTACH, "kbox", false); |
- | |
| 837 | if (!kb_thread) |
827 | if (!kb_thread) { |
| - | 828 | mutex_unlock(&ta->kb_cleanup_lock); |
|
| 838 | return ENOMEM; |
829 | return ENOMEM; |
| 839 | - | ||
| 840 | /* |
- | |
| 841 | * It might happen that someone else has attached a kbox thread. |
- | |
| 842 | * in the meantime. Also, the task might have gone or shut down. |
- | |
| 843 | * Let's try from the beginning. |
- | |
| 844 | */ |
- | |
| 845 | - | ||
| 846 | ipl = interrupts_disable(); |
- | |
| 847 | spinlock_lock(&tasks_lock); |
- | |
| 848 | - | ||
| 849 | ta = task_find_by_id(taskid); |
- | |
| 850 | if (ta == NULL) { |
- | |
| 851 | spinlock_unlock(&tasks_lock); |
- | |
| 852 | return ENOENT; |
- | |
| 853 | } |
- | |
| 854 | - | ||
| 855 | spinlock_lock(&ta->kb_cleanup_lock); |
- | |
| 856 | spinlock_unlock(&tasks_lock); |
- | |
| 857 | - | ||
| 858 | if (ta->kb_finished != false || ta->kb_thread != NULL) { |
- | |
| 859 | spinlock_unlock(&ta->kb_cleanup_lock); |
- | |
| 860 | interrupts_restore(ipl); |
- | |
| 861 | - | ||
| 862 | /* |
- | |
| 863 | * Release the allocated thread struct. This won't |
- | |
| 864 | * happen too often, only if two CPUs raced for |
- | |
| 865 | * connecting to the kbox. |
- | |
| 866 | */ |
- | |
| 867 | thread_unattached_free(kb_thread); |
- | |
| 868 | return EINVAL; |
- | |
| 869 | } |
830 | } |
| 870 | 831 | ||
| 871 | /* Attach thread */ |
- | |
| 872 | ta->kb_thread = kb_thread; |
832 | ta->kb_thread = kb_thread; |
| 873 | thread_attach(kb_thread, ta); |
- | |
| 874 | 833 | ||
| - | 834 | /* FIXME: we could join the kbox thread */ |
|
| 875 | thread_detach(kb_thread); |
835 | thread_detach(kb_thread); |
| 876 | thread_ready(kb_thread); |
836 | thread_ready(kb_thread); |
| 877 | 837 | ||
| 878 | spinlock_unlock(&ta->kb_cleanup_lock); |
838 | mutex_unlock(&ta->kb_cleanup_lock); |
| 879 | interrupts_restore(ipl); |
- | |
| 880 | 839 | ||
| 881 | return newphid; |
840 | return newphid; |
| 882 | } |
841 | } |
| 883 | 842 | ||
| 884 | /** @} |
843 | /** @} |