Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/kbox.c

    r4acaa7c0 r14ecd6c  
    4747void ipc_kbox_cleanup(void)
    4848{
    49         /*
     49        ipl_t ipl;
     50        bool have_kb_thread;
     51
     52        /*
    5053         * Only hold kb.cleanup_lock while setting kb.finished -
    5154         * this is enough.
     
    5457        TASK->kb.finished = true;
    5558        mutex_unlock(&TASK->kb.cleanup_lock);
    56        
    57         bool have_kb_thread = (TASK->kb.thread != NULL);
    58        
     59
     60        have_kb_thread = (TASK->kb.thread != NULL);
     61
    5962        /*
    6063         * From now on nobody will try to connect phones or attach
    6164         * kbox threads
    6265         */
    63        
     66
    6467        /*
    6568         * Disconnect all phones connected to our kbox. Passing true for
     
    6972         */
    7073        ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread);
    71        
    72         /*
     74
     75        /* 
    7376         * If the task was being debugged, clean up debugging session.
    7477         * This is necessarry as slamming the phones won't force
    7578         * kbox thread to clean it up since sender != debugger.
    7679         */
    77         mutex_lock(&TASK->udebug.lock);
     80        ipl = interrupts_disable();
     81        spinlock_lock(&TASK->lock);
    7882        udebug_task_cleanup(TASK);
    79         mutex_unlock(&TASK->udebug.lock);
     83        spinlock_unlock(&TASK->lock);
     84        interrupts_restore(ipl);
    8085       
    8186        if (have_kb_thread) {
     
    8691                TASK->kb.thread = NULL;
    8792        }
    88        
     93
    8994        /* Answer all messages in 'calls' and 'dispatched_calls' queues. */
    90         irq_spinlock_lock(&TASK->kb.box.lock, true);
     95        spinlock_lock(&TASK->kb.box.lock);
    9196        ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls);
    9297        ipc_cleanup_call_list(&TASK->kb.box.calls);
    93         irq_spinlock_unlock(&TASK->kb.box.lock, true);
     98        spinlock_unlock(&TASK->kb.box.lock);
    9499}
    95100
    96101/** Handle hangup message in kbox.
    97102 *
    98  * @param call The IPC_M_PHONE_HUNGUP call structure.
    99  * @param last Output, the function stores @c true here if
    100  *             this was the last phone, @c false otherwise.
    101  *
    102  */
     103 * @param call  The IPC_M_PHONE_HUNGUP call structure.
     104 * @param last  Output, the function stores @c true here if
     105 *              this was the last phone, @c false otherwise.
     106 **/
    103107static void kbox_proc_phone_hungup(call_t *call, bool *last)
    104108{
     109        ipl_t ipl;
     110
    105111        /* Was it our debugger, who hung up? */
    106112        if (call->sender == TASK->udebug.debugger) {
    107113                /* Terminate debugging session (if any). */
    108114                LOG("Terminate debugging session.");
    109                 irq_spinlock_lock(&TASK->lock, true);
     115                ipl = interrupts_disable();
     116                spinlock_lock(&TASK->lock);
    110117                udebug_task_cleanup(TASK);
    111                 irq_spinlock_unlock(&TASK->lock, true);
     118                spinlock_unlock(&TASK->lock);
     119                interrupts_restore(ipl);
    112120        } else {
    113121                LOG("Was not debugger.");
    114122        }
    115        
     123
    116124        LOG("Continue with hangup message.");
    117125        IPC_SET_RETVAL(call->data, 0);
    118126        ipc_answer(&TASK->kb.box, call);
    119        
    120         mutex_lock(&TASK->kb.cleanup_lock);
    121        
    122         irq_spinlock_lock(&TASK->lock, true);
    123         irq_spinlock_lock(&TASK->kb.box.lock, false);
     127
     128        ipl = interrupts_disable();
     129        spinlock_lock(&TASK->lock);
     130        spinlock_lock(&TASK->kb.box.lock);
    124131        if (list_empty(&TASK->kb.box.connected_phones)) {
    125132                /*
     
    127134                 * gets freed and signal to the caller.
    128135                 */
    129                
     136
    130137                /* Only detach kbox thread unless already terminating. */
     138                mutex_lock(&TASK->kb.cleanup_lock);
    131139                if (TASK->kb.finished == false) {
    132140                        /* Detach kbox thread so it gets freed from memory. */
     
    134142                        TASK->kb.thread = NULL;
    135143                }
    136                
     144                mutex_unlock(&TASK->kb.cleanup_lock);
     145
    137146                LOG("Phone list is empty.");
    138147                *last = true;
    139         } else
     148        } else {
    140149                *last = false;
    141        
    142         irq_spinlock_unlock(&TASK->kb.box.lock, false);
    143         irq_spinlock_unlock(&TASK->lock, true);
    144        
    145         mutex_unlock(&TASK->kb.cleanup_lock);
     150        }
     151
     152        spinlock_unlock(&TASK->kb.box.lock);
     153        spinlock_unlock(&TASK->lock);
     154        interrupts_restore(ipl);
    146155}
    147156
     
    151160 * when all phones are disconnected from the kbox.
    152161 *
    153  * @param arg Ignored.
    154  *
     162 * @param arg   Ignored.
    155163 */
    156164static void kbox_thread_proc(void *arg)
    157165{
    158         (void) arg;
     166        call_t *call;
     167        bool done;
     168
     169        (void)arg;
    159170        LOG("Starting.");
    160         bool done = false;
    161        
     171        done = false;
     172
    162173        while (!done) {
    163                 call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
     174                call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
    164175                        SYNCH_FLAGS_NONE);
    165                
     176
    166177                if (call == NULL)
    167                         continue;  /* Try again. */
    168                
     178                        continue;       /* Try again. */
     179
    169180                switch (IPC_GET_METHOD(call->data)) {
    170                
     181
    171182                case IPC_M_DEBUG_ALL:
    172183                        /* Handle debug call. */
    173184                        udebug_call_receive(call);
    174185                        break;
    175                
     186
    176187                case IPC_M_PHONE_HUNGUP:
    177188                        /*
     
    182193                        kbox_proc_phone_hungup(call, &done);
    183194                        break;
    184                
     195
    185196                default:
    186197                        /* Ignore */
     
    188199                }
    189200        }
    190        
     201
    191202        LOG("Exiting.");
    192203}
    193204
    194205
    195 /** Connect phone to a task kernel-box specified by id.
     206/**
     207 * Connect phone to a task kernel-box specified by id.
    196208 *
    197209 * Note that this is not completely atomic. For optimisation reasons, the task
     
    200212 * cleanup code.
    201213 *
    202  * @return Phone id on success, or negative error code.
    203  *
     214 * @return              Phone id on success, or negative error code.
    204215 */
    205216int ipc_connect_kbox(task_id_t taskid)
    206217{
    207         irq_spinlock_lock(&tasks_lock, true);
    208        
    209         task_t *task = task_find_by_id(taskid);
    210         if (task == NULL) {
    211                 irq_spinlock_unlock(&tasks_lock, true);
     218        int newphid;
     219        task_t *ta;
     220        thread_t *kb_thread;
     221        ipl_t ipl;
     222
     223        ipl = interrupts_disable();
     224        spinlock_lock(&tasks_lock);
     225
     226        ta = task_find_by_id(taskid);
     227        if (ta == NULL) {
     228                spinlock_unlock(&tasks_lock);
     229                interrupts_restore(ipl);
    212230                return ENOENT;
    213231        }
    214        
    215         atomic_inc(&task->refcount);
    216        
    217         irq_spinlock_unlock(&tasks_lock, true);
    218        
    219         mutex_lock(&task->kb.cleanup_lock);
    220        
    221         if (atomic_predec(&task->refcount) == 0) {
    222                 mutex_unlock(&task->kb.cleanup_lock);
    223                 task_destroy(task);
     232
     233        atomic_inc(&ta->refcount);
     234
     235        spinlock_unlock(&tasks_lock);
     236        interrupts_restore(ipl);
     237
     238        mutex_lock(&ta->kb.cleanup_lock);
     239
     240        if (atomic_predec(&ta->refcount) == 0) {
     241                mutex_unlock(&ta->kb.cleanup_lock);
     242                task_destroy(ta);
    224243                return ENOENT;
    225244        }
    226        
    227         if (task->kb.finished != false) {
    228                 mutex_unlock(&task->kb.cleanup_lock);
     245
     246        if (ta->kb.finished != false) {
     247                mutex_unlock(&ta->kb.cleanup_lock);
    229248                return EINVAL;
    230249        }
    231        
    232         int newphid = phone_alloc(TASK);
     250
     251        newphid = phone_alloc(TASK);
    233252        if (newphid < 0) {
    234                 mutex_unlock(&task->kb.cleanup_lock);
     253                mutex_unlock(&ta->kb.cleanup_lock);
    235254                return ELIMIT;
    236255        }
    237        
     256
    238257        /* Connect the newly allocated phone to the kbox */
    239         ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
    240        
    241         if (task->kb.thread != NULL) {
    242                 mutex_unlock(&task->kb.cleanup_lock);
     258        ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box);
     259
     260        if (ta->kb.thread != NULL) {
     261                mutex_unlock(&ta->kb.cleanup_lock);
    243262                return newphid;
    244263        }
    245        
     264
    246265        /* Create a kbox thread */
    247         thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0,
     266        kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0,
    248267            "kbox", false);
    249268        if (!kb_thread) {
    250                 mutex_unlock(&task->kb.cleanup_lock);
     269                mutex_unlock(&ta->kb.cleanup_lock);
    251270                return ENOMEM;
    252271        }
    253        
    254         task->kb.thread = kb_thread;
     272
     273        ta->kb.thread = kb_thread;
    255274        thread_ready(kb_thread);
    256        
    257         mutex_unlock(&task->kb.cleanup_lock);
    258        
     275
     276        mutex_unlock(&ta->kb.cleanup_lock);
     277
    259278        return newphid;
    260279}
Note: See TracChangeset for help on using the changeset viewer.