Ignore:
File:
1 edited

Legend:

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

    r1d432f9 rd3808d3  
    6060
    6161/** Spinlock protecting the tasks_tree AVL tree. */
    62 IRQ_SPINLOCK_INITIALIZE(tasks_lock);
     62SPINLOCK_INITIALIZE(tasks_lock);
    6363
    6464/** AVL tree of active tasks.
     
    8181/* Forward declarations. */
    8282static void task_kill_internal(task_t *);
    83 static int tsk_constructor(void *, unsigned int);
    84 
    85 /** Initialize kernel tasks support.
    86  *
    87  */
     83static int tsk_constructor(void *, int);
     84
     85/** Initialize kernel tasks support. */
    8886void task_init(void)
    8987{
     
    9492}
    9593
    96 /** Task finish walker.
    97  *
     94/*
    9895 * The idea behind this walker is to kill and count all tasks different from
    9996 * TASK.
    100  *
    10197 */
    10298static bool task_done_walker(avltree_node_t *node, void *arg)
    10399{
    104         task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
    105         size_t *cnt = (size_t *) arg;
    106        
    107         if (task != TASK) {
     100        task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
     101        unsigned *cnt = (unsigned *) arg;
     102       
     103        if (t != TASK) {
    108104                (*cnt)++;
    109                
    110105#ifdef CONFIG_DEBUG
    111                 printf("[%"PRIu64"] ", task->taskid);
    112 #endif
    113                
    114                 task_kill_internal(task);
     106                printf("[%"PRIu64"] ", t->taskid);
     107#endif
     108                task_kill_internal(t);
    115109        }
    116110       
     
    119113}
    120114
    121 /** Kill all tasks except the current task.
    122  *
    123  */
     115/** Kill all tasks except the current task. */
    124116void task_done(void)
    125117{
    126         size_t tasks_left;
    127        
    128         /* Repeat until there are any tasks except TASK */
    129         do {
     118        unsigned tasks_left;
     119       
     120        do { /* Repeat until there are any tasks except TASK */
     121                /* Messing with task structures, avoid deadlock */
    130122#ifdef CONFIG_DEBUG
    131123                printf("Killing tasks... ");
    132124#endif
    133                
    134                 irq_spinlock_lock(&tasks_lock, true);
     125                ipl_t ipl = interrupts_disable();
     126                spinlock_lock(&tasks_lock);
    135127                tasks_left = 0;
    136128                avltree_walk(&tasks_tree, task_done_walker, &tasks_left);
    137                 irq_spinlock_unlock(&tasks_lock, true);
    138                
     129                spinlock_unlock(&tasks_lock);
     130                interrupts_restore(ipl);
    139131                thread_sleep(1);
    140                
    141132#ifdef CONFIG_DEBUG
    142133                printf("\n");
    143134#endif
    144         } while (tasks_left > 0);
    145 }
    146 
    147 int tsk_constructor(void *obj, unsigned int kmflags)
    148 {
    149         task_t *task = (task_t *) obj;
    150        
    151         atomic_set(&task->refcount, 0);
    152         atomic_set(&task->lifecount, 0);
    153         atomic_set(&task->active_calls, 0);
    154        
    155         irq_spinlock_initialize(&task->lock, "task_t_lock");
    156         mutex_initialize(&task->futexes_lock, MUTEX_PASSIVE);
    157        
    158         list_initialize(&task->th_head);
    159         list_initialize(&task->sync_box_head);
    160        
    161         ipc_answerbox_init(&task->answerbox, task);
    162        
    163         size_t i;
     135        } while (tasks_left);
     136}
     137
     138int tsk_constructor(void *obj, int kmflags)
     139{
     140        task_t *ta = obj;
     141        int i;
     142       
     143        atomic_set(&ta->refcount, 0);
     144        atomic_set(&ta->lifecount, 0);
     145        atomic_set(&ta->active_calls, 0);
     146       
     147        spinlock_initialize(&ta->lock, "task_ta_lock");
     148        mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
     149       
     150        list_initialize(&ta->th_head);
     151        list_initialize(&ta->sync_box_head);
     152       
     153        ipc_answerbox_init(&ta->answerbox, ta);
    164154        for (i = 0; i < IPC_MAX_PHONES; i++)
    165                 ipc_phone_init(&task->phones[i]);
     155                ipc_phone_init(&ta->phones[i]);
    166156       
    167157#ifdef CONFIG_UDEBUG
    168158        /* Init kbox stuff */
    169         task->kb.thread = NULL;
    170         ipc_answerbox_init(&task->kb.box, task);
    171         mutex_initialize(&task->kb.cleanup_lock, MUTEX_PASSIVE);
     159        ta->kb.thread = NULL;
     160        ipc_answerbox_init(&ta->kb.box, ta);
     161        mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
    172162#endif
    173163       
     
    185175task_t *task_create(as_t *as, const char *name)
    186176{
    187         task_t *task = (task_t *) slab_alloc(task_slab, 0);
    188         task_create_arch(task);
    189        
    190         task->as = as;
    191         str_cpy(task->name, TASK_NAME_BUFLEN, name);
    192        
    193         task->context = CONTEXT;
    194         task->capabilities = 0;
    195         task->ucycles = 0;
    196         task->kcycles = 0;
    197        
    198         task->ipc_info.call_sent = 0;
    199         task->ipc_info.call_recieved = 0;
    200         task->ipc_info.answer_sent = 0;
    201         task->ipc_info.answer_recieved = 0;
    202         task->ipc_info.irq_notif_recieved = 0;
    203         task->ipc_info.forwarded = 0;
    204        
     177        ipl_t ipl;
     178        task_t *ta;
     179       
     180        ta = (task_t *) slab_alloc(task_slab, 0);
     181        task_create_arch(ta);
     182        ta->as = as;
     183        memcpy(ta->name, name, TASK_NAME_BUFLEN);
     184        ta->name[TASK_NAME_BUFLEN - 1] = 0;
     185       
     186        ta->context = CONTEXT;
     187        ta->capabilities = 0;
     188        ta->ucycles = 0;
     189        ta->kcycles = 0;
     190
     191        ta->ipc_info.call_sent = 0;
     192        ta->ipc_info.call_recieved = 0;
     193        ta->ipc_info.answer_sent = 0;
     194        ta->ipc_info.answer_recieved = 0;
     195        ta->ipc_info.irq_notif_recieved = 0;
     196        ta->ipc_info.forwarded = 0;
     197
    205198#ifdef CONFIG_UDEBUG
    206199        /* Init debugging stuff */
    207         udebug_task_init(&task->udebug);
     200        udebug_task_init(&ta->udebug);
    208201       
    209202        /* Init kbox stuff */
    210         task->kb.finished = false;
     203        ta->kb.finished = false;
    211204#endif
    212205       
    213206        if ((ipc_phone_0) &&
    214             (context_check(ipc_phone_0->task->context, task->context)))
    215                 ipc_phone_connect(&task->phones[0], ipc_phone_0);
    216        
    217         btree_create(&task->futexes);
     207            (context_check(ipc_phone_0->task->context, ta->context)))
     208                ipc_phone_connect(&ta->phones[0], ipc_phone_0);
     209       
     210        btree_create(&ta->futexes);
    218211       
    219212        /*
    220213         * Get a reference to the address space.
    221214         */
    222         as_hold(task->as);
    223        
    224         irq_spinlock_lock(&tasks_lock, true);
    225        
    226         task->taskid = ++task_counter;
    227         avltree_node_initialize(&task->tasks_tree_node);
    228         task->tasks_tree_node.key = task->taskid;
    229         avltree_insert(&tasks_tree, &task->tasks_tree_node);
    230        
    231         irq_spinlock_unlock(&tasks_lock, true);
    232        
    233         return task;
     215        as_hold(ta->as);
     216
     217        ipl = interrupts_disable();
     218        spinlock_lock(&tasks_lock);
     219        ta->taskid = ++task_counter;
     220        avltree_node_initialize(&ta->tasks_tree_node);
     221        ta->tasks_tree_node.key = ta->taskid;
     222        avltree_insert(&tasks_tree, &ta->tasks_tree_node);
     223        spinlock_unlock(&tasks_lock);
     224        interrupts_restore(ipl);
     225       
     226        return ta;
    234227}
    235228
    236229/** Destroy task.
    237230 *
    238  * @param task Task to be destroyed.
    239  *
    240  */
    241 void task_destroy(task_t *task)
     231 * @param t Task to be destroyed.
     232 *
     233 */
     234void task_destroy(task_t *t)
    242235{
    243236        /*
    244237         * Remove the task from the task B+tree.
    245238         */
    246         irq_spinlock_lock(&tasks_lock, true);
    247         avltree_delete(&tasks_tree, &task->tasks_tree_node);
    248         irq_spinlock_unlock(&tasks_lock, true);
     239        spinlock_lock(&tasks_lock);
     240        avltree_delete(&tasks_tree, &t->tasks_tree_node);
     241        spinlock_unlock(&tasks_lock);
    249242       
    250243        /*
    251244         * Perform architecture specific task destruction.
    252245         */
    253         task_destroy_arch(task);
     246        task_destroy_arch(t);
    254247       
    255248        /*
    256249         * Free up dynamically allocated state.
    257250         */
    258         btree_destroy(&task->futexes);
     251        btree_destroy(&t->futexes);
    259252       
    260253        /*
    261254         * Drop our reference to the address space.
    262255         */
    263         as_release(task->as);
    264        
    265         slab_free(task_slab, task);
     256        as_release(t->as);
     257       
     258        slab_free(task_slab, t);
    266259}
    267260
     
    270263 * Holding a reference to a task prevents destruction of that task.
    271264 *
    272  * @param task Task to be held.
    273  *
    274  */
    275 void task_hold(task_t *task)
    276 {
    277         atomic_inc(&task->refcount);
     265 * @param t             Task to be held.
     266 */
     267void task_hold(task_t *t)
     268{
     269        atomic_inc(&t->refcount);
    278270}
    279271
     
    282274 * The last one to release a reference to a task destroys the task.
    283275 *
    284  * @param task Task to be released.
    285  *
    286  */
    287 void task_release(task_t *task)
    288 {
    289         if ((atomic_predec(&task->refcount)) == 0)
    290                 task_destroy(task);
     276 * @param t             Task to be released.
     277 */
     278void task_release(task_t *t)
     279{
     280        if ((atomic_predec(&t->refcount)) == 0)
     281                task_destroy(t);
    291282}
    292283
     
    351342task_t *task_find_by_id(task_id_t id)
    352343{
    353         ASSERT(interrupts_disabled());
    354         ASSERT(irq_spinlock_locked(&tasks_lock));
    355 
    356344        avltree_node_t *node =
    357345            avltree_search(&tasks_tree, (avltree_key_t) id);
    358346       
    359347        if (node)
    360                 return avltree_get_instance(node, task_t, tasks_tree_node);
     348                return avltree_get_instance(node, task_t, tasks_tree_node); 
    361349       
    362350        return NULL;
     
    365353/** Get accounting data of given task.
    366354 *
    367  * Note that task lock of 'task' must be already held and interrupts must be
     355 * Note that task lock of 't' must be already held and interrupts must be
    368356 * already disabled.
    369357 *
    370  * @param task    Pointer to the task.
     358 * @param t       Pointer to thread.
    371359 * @param ucycles Out pointer to sum of all user cycles.
    372360 * @param kcycles Out pointer to sum of all kernel cycles.
    373361 *
    374362 */
    375 void task_get_accounting(task_t *task, uint64_t *ucycles, uint64_t *kcycles)
    376 {
    377         ASSERT(interrupts_disabled());
    378         ASSERT(irq_spinlock_locked(&task->lock));
    379 
     363void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles)
     364{
    380365        /* Accumulated values of task */
    381         uint64_t uret = task->ucycles;
    382         uint64_t kret = task->kcycles;
     366        uint64_t uret = t->ucycles;
     367        uint64_t kret = t->kcycles;
    383368       
    384369        /* Current values of threads */
    385370        link_t *cur;
    386         for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
    387                 thread_t *thread = list_get_instance(cur, thread_t, th_link);
     371        for (cur = t->th_head.next; cur != &t->th_head; cur = cur->next) {
     372                thread_t *thr = list_get_instance(cur, thread_t, th_link);
    388373               
    389                 irq_spinlock_lock(&thread->lock, false);
    390                
     374                spinlock_lock(&thr->lock);
    391375                /* Process only counted threads */
    392                 if (!thread->uncounted) {
    393                         if (thread == THREAD) {
     376                if (!thr->uncounted) {
     377                        if (thr == THREAD) {
    394378                                /* Update accounting of current thread */
    395379                                thread_update_accounting(false);
    396                         }
    397                        
    398                         uret += thread->ucycles;
    399                         kret += thread->kcycles;
     380                        }
     381                        uret += thr->ucycles;
     382                        kret += thr->kcycles;
    400383                }
    401                
    402                 irq_spinlock_unlock(&thread->lock, false);
     384                spinlock_unlock(&thr->lock);
    403385        }
    404386       
     
    407389}
    408390
    409 static void task_kill_internal(task_t *task)
     391static void task_kill_internal(task_t *ta)
    410392{
    411393        link_t *cur;
     
    414396         * Interrupt all threads.
    415397         */
    416         irq_spinlock_lock(&task->lock, false);
    417         for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
    418                 thread_t *thread = list_get_instance(cur, thread_t, th_link);
     398        spinlock_lock(&ta->lock);
     399        for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
     400                thread_t *thr;
    419401                bool sleeping = false;
    420402               
    421                 irq_spinlock_lock(&thread->lock, false);
     403                thr = list_get_instance(cur, thread_t, th_link);
    422404               
    423                 thread->interrupted = true;
    424                 if (thread->state == Sleeping)
     405                spinlock_lock(&thr->lock);
     406                thr->interrupted = true;
     407                if (thr->state == Sleeping)
    425408                        sleeping = true;
    426                
    427                 irq_spinlock_unlock(&thread->lock, false);
     409                spinlock_unlock(&thr->lock);
    428410               
    429411                if (sleeping)
    430                         waitq_interrupt_sleep(thread);
     412                        waitq_interrupt_sleep(thr);
    431413        }
    432        
    433         irq_spinlock_unlock(&task->lock, false);
     414        spinlock_unlock(&ta->lock);
    434415}
    435416
     
    446427int task_kill(task_id_t id)
    447428{
     429        ipl_t ipl;
     430        task_t *ta;
     431
    448432        if (id == 1)
    449433                return EPERM;
    450434       
    451         irq_spinlock_lock(&tasks_lock, true);
    452        
    453         task_t *task = task_find_by_id(id);
    454         if (!task) {
    455                 irq_spinlock_unlock(&tasks_lock, true);
     435        ipl = interrupts_disable();
     436        spinlock_lock(&tasks_lock);
     437        if (!(ta = task_find_by_id(id))) {
     438                spinlock_unlock(&tasks_lock);
     439                interrupts_restore(ipl);
    456440                return ENOENT;
    457441        }
    458        
    459         task_kill_internal(task);
    460         irq_spinlock_unlock(&tasks_lock, true);
    461        
    462         return EOK;
     442        task_kill_internal(ta);
     443        spinlock_unlock(&tasks_lock);
     444        interrupts_restore(ipl);
     445        return 0;
    463446}
    464447
    465448static bool task_print_walker(avltree_node_t *node, void *arg)
    466449{
    467         task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
    468         irq_spinlock_lock(&task->lock, false);
     450        task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
     451        int j;
     452       
     453        spinlock_lock(&t->lock);
    469454       
    470455        uint64_t ucycles;
    471456        uint64_t kcycles;
    472457        char usuffix, ksuffix;
    473         task_get_accounting(task, &ucycles, &kcycles);
     458        task_get_accounting(t, &ucycles, &kcycles);
    474459        order_suffix(ucycles, &ucycles, &usuffix);
    475460        order_suffix(kcycles, &kcycles, &ksuffix);
    476461       
    477 #ifdef __32_BITS__
     462#ifdef __32_BITS__     
    478463        printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 "%c %9"
    479             PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context,
    480             task, task->as, ucycles, usuffix, kcycles, ksuffix,
    481             atomic_get(&task->refcount), atomic_get(&task->active_calls));
     464                PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as,
     465                ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount),
     466                atomic_get(&t->active_calls));
    482467#endif
    483468       
    484469#ifdef __64_BITS__
    485470        printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 "%c %9"
    486             PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context,
    487             task, task->as, ucycles, usuffix, kcycles, ksuffix,
    488             atomic_get(&task->refcount), atomic_get(&task->active_calls));
    489 #endif
    490        
    491         size_t i;
    492         for (i = 0; i < IPC_MAX_PHONES; i++) {
    493                 if (task->phones[i].callee)
    494                         printf(" %" PRIs ":%p", i, task->phones[i].callee);
     471                PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as,
     472                ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount),
     473                atomic_get(&t->active_calls));
     474#endif
     475       
     476        for (j = 0; j < IPC_MAX_PHONES; j++) {
     477                if (t->phones[j].callee)
     478                        printf(" %d:%p", j, t->phones[j].callee);
    495479        }
    496480        printf("\n");
    497481       
    498         irq_spinlock_unlock(&task->lock, false);
     482        spinlock_unlock(&t->lock);
    499483        return true;
    500484}
     
    503487void task_print_list(void)
    504488{
     489        ipl_t ipl;
     490       
    505491        /* Messing with task structures, avoid deadlock */
    506         irq_spinlock_lock(&tasks_lock, true);
     492        ipl = interrupts_disable();
     493        spinlock_lock(&tasks_lock);
    507494       
    508495#ifdef __32_BITS__
     
    522509        avltree_walk(&tasks_tree, task_print_walker, NULL);
    523510       
    524         irq_spinlock_unlock(&tasks_lock, true);
     511        spinlock_unlock(&tasks_lock);
     512        interrupts_restore(ipl);
    525513}
    526514
Note: See TracChangeset for help on using the changeset viewer.