Subversion Repositories HelenOS

Rev

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