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 | /** @} |