Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/proc/task.c

    r5a5269d rf35749e  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2010 Jakub Jermar
    3  * Copyright (c) 2018 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    104104 *
    105105 */
    106 void task_done(void)
     106void task_done(task_t *cur_task)
    107107{
    108108        size_t tasks_left;
     
    112112                task_t *task_0 = ipc_box_0->task;
    113113                ipc_box_0 = NULL;
     114
    114115                /*
    115116                 * The first task is held by kinit(), we need to release it or
     
    129130                task = task_first();
    130131                while (task != NULL) {
    131                         if (task != TASK) {
     132                        if (task != cur_task) {
    132133                                tasks_left++;
    133134#ifdef CONFIG_DEBUG
     
    158159                return rc;
    159160
    160         atomic_store(&task->refcount, 0);
    161161        atomic_store(&task->lifecount, 0);
    162162
     
    201201        if (!task)
    202202                return NULL;
     203
     204        refcount_init(&task->refcount);
    203205
    204206        task_create_arch(task);
     
    224226
    225227        task->answerbox.active = true;
     228
     229        task->debug_sections = NULL;
    226230
    227231#ifdef CONFIG_UDEBUG
     
    266270 *
    267271 */
    268 void task_destroy(task_t *task)
     272static void task_destroy(task_t *task)
    269273{
    270274        /*
     
    297301void task_hold(task_t *task)
    298302{
    299         atomic_inc(&task->refcount);
     303        refcount_up(&task->refcount);
    300304}
    301305
     
    309313void task_release(task_t *task)
    310314{
    311         if ((atomic_predec(&task->refcount)) == 0)
     315        if (refcount_down(&task->refcount))
    312316                task_destroy(task);
    313317}
     
    385389        irq_spinlock_lock(&tasks_lock, true);
    386390        irq_spinlock_lock(&TASK->lock, false);
    387         irq_spinlock_lock(&threads_lock, false);
    388391
    389392        /* Set task name */
    390393        str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf);
    391394
    392         irq_spinlock_unlock(&threads_lock, false);
    393395        irq_spinlock_unlock(&TASK->lock, false);
    394396        irq_spinlock_unlock(&tasks_lock, true);
     
    416418/** Find task structure corresponding to task ID.
    417419 *
    418  * The tasks_lock must be already held by the caller of this function and
    419  * interrupts must be disabled.
    420  *
    421420 * @param id Task ID.
    422421 *
    423  * @return Task structure address or NULL if there is no such task ID.
     422 * @return Task reference or NULL if there is no such task ID.
    424423 *
    425424 */
    426425task_t *task_find_by_id(task_id_t id)
    427426{
    428         assert(interrupts_disabled());
    429         assert(irq_spinlock_locked(&tasks_lock));
     427        task_t *task = NULL;
     428
     429        irq_spinlock_lock(&tasks_lock, true);
    430430
    431431        odlink_t *odlink = odict_find_eq(&tasks, &id, NULL);
    432         if (odlink != NULL)
    433                 return odict_get_instance(odlink, task_t, ltasks);
    434 
    435         return NULL;
     432        if (odlink != NULL) {
     433                task = odict_get_instance(odlink, task_t, ltasks);
     434
     435                /*
     436                 * The directory of tasks can't hold a reference, since that would
     437                 * prevent task from ever being destroyed. That means we have to
     438                 * check for the case where the task is already being destroyed, but
     439                 * not yet removed from the directory.
     440                 */
     441                if (!refcount_try_up(&task->refcount))
     442                        task = NULL;
     443        }
     444
     445        irq_spinlock_unlock(&tasks_lock, true);
     446
     447        return task;
    436448}
    437449
     
    506518        /* Current values of threads */
    507519        list_foreach(task->threads, th_link, thread_t, thread) {
    508                 irq_spinlock_lock(&thread->lock, false);
    509 
    510520                /* Process only counted threads */
    511521                if (!thread->uncounted) {
     
    515525                        }
    516526
    517                         uret += thread->ucycles;
    518                         kret += thread->kcycles;
     527                        uret += atomic_time_read(&thread->ucycles);
     528                        kret += atomic_time_read(&thread->kcycles);
    519529                }
    520 
    521                 irq_spinlock_unlock(&thread->lock, false);
    522530        }
    523531
     
    528536static void task_kill_internal(task_t *task)
    529537{
    530         irq_spinlock_lock(&task->lock, false);
    531         irq_spinlock_lock(&threads_lock, false);
     538        irq_spinlock_lock(&task->lock, true);
    532539
    533540        /*
     
    536543
    537544        list_foreach(task->threads, th_link, thread_t, thread) {
    538                 bool sleeping = false;
    539 
    540                 irq_spinlock_lock(&thread->lock, false);
    541 
    542                 thread->interrupted = true;
    543                 if (thread->state == Sleeping)
    544                         sleeping = true;
    545 
    546                 irq_spinlock_unlock(&thread->lock, false);
    547 
    548                 if (sleeping)
    549                         waitq_interrupt_sleep(thread);
     545                thread_interrupt(thread);
    550546        }
    551547
    552         irq_spinlock_unlock(&threads_lock, false);
    553         irq_spinlock_unlock(&task->lock, false);
     548        irq_spinlock_unlock(&task->lock, true);
    554549}
    555550
     
    569564                return EPERM;
    570565
    571         irq_spinlock_lock(&tasks_lock, true);
    572 
    573566        task_t *task = task_find_by_id(id);
    574         if (!task) {
    575                 irq_spinlock_unlock(&tasks_lock, true);
     567        if (!task)
    576568                return ENOENT;
    577         }
    578569
    579570        task_kill_internal(task);
    580         irq_spinlock_unlock(&tasks_lock, true);
    581 
     571        task_release(task);
    582572        return EOK;
    583573}
     
    609599        }
    610600
    611         irq_spinlock_lock(&tasks_lock, true);
    612601        task_kill_internal(TASK);
    613         irq_spinlock_unlock(&tasks_lock, true);
    614 
    615602        thread_exit();
    616603}
     
    641628        if (additional)
    642629                printf("%-8" PRIu64 " %9zu", task->taskid,
    643                     atomic_load(&task->refcount));
     630                    atomic_load(&task->lifecount));
    644631        else
    645632                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p"
     
    653640                printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c "
    654641                    "%9zu\n", task->taskid, ucycles, usuffix, kcycles,
    655                     ksuffix, atomic_load(&task->refcount));
     642                    ksuffix, atomic_load(&task->lifecount));
    656643        else
    657644                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
Note: See TracChangeset for help on using the changeset viewer.