Ignore:
File:
1 edited

Legend:

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

    r5ab1648 r8658f89  
    7575static task_id_t task_counter = 0;
    7676
    77 /* Forward declarations. */
    78 static void task_kill_internal(task_t *);
    79 
    8077/** Initialize kernel tasks support. */
    8178void task_init(void)
     
    8683
    8784/*
    88  * The idea behind this walker is to kill and count all tasks different from
     85 * The idea behind this walker is to remember a single task different from
    8986 * TASK.
    9087 */
     
    9289{
    9390        task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    94         unsigned *cnt = (unsigned *) arg;
    95 
    96         if (t != TASK) {
    97                 (*cnt)++;
    98 #ifdef CONFIG_DEBUG
    99                 printf("[%"PRIu64"] ", t->taskid);
    100 #endif
    101                 task_kill_internal(t);
     91        task_t **tp = (task_t **) arg;
     92
     93        if (t != TASK) {
     94                *tp = t;
     95                return false;   /* stop walking */
    10296        }
    10397
     
    108102void task_done(void)
    109103{
    110         unsigned tasks_left;
    111 
     104        task_t *t;
    112105        do { /* Repeat until there are any tasks except TASK */
     106               
    113107                /* Messing with task structures, avoid deadlock */
    114 #ifdef CONFIG_DEBUG
    115                 printf("Killing tasks... ");
    116 #endif
    117108                ipl_t ipl = interrupts_disable();
    118109                spinlock_lock(&tasks_lock);
    119                 tasks_left = 0;
    120                 avltree_walk(&tasks_tree, task_done_walker, &tasks_left);
    121                 spinlock_unlock(&tasks_lock);
    122                 interrupts_restore(ipl);
    123                 thread_sleep(1);
     110               
     111                t = NULL;
     112                avltree_walk(&tasks_tree, task_done_walker, &t);
     113               
     114                if (t != NULL) {
     115                        task_id_t id = t->taskid;
     116                       
     117                        spinlock_unlock(&tasks_lock);
     118                        interrupts_restore(ipl);
     119                       
    124120#ifdef CONFIG_DEBUG
    125                 printf("\n");
    126 #endif
    127         } while (tasks_left);
     121                        printf("Killing task %" PRIu64 "\n", id);
     122#endif                 
     123                        task_kill(id);
     124                        thread_usleep(10000);
     125                } else {
     126                        spinlock_unlock(&tasks_lock);
     127                        interrupts_restore(ipl);
     128                }
     129               
     130        } while (t != NULL);
    128131}
    129132
     
    197200        interrupts_restore(ipl);
    198201       
     202        /*
     203         * Notify about task creation.
     204         */
     205        if (event_is_subscribed(EVENT_WAIT))
     206                event_notify_3(EVENT_WAIT, TASK_CREATE, LOWER32(ta->taskid),
     207                    UPPER32(ta->taskid));
     208       
    199209        return ta;
    200210}
     
    228238        if (atomic_predec(&t->as->refcount) == 0)
    229239                as_destroy(t->as);
     240       
     241        /*
     242         * Notify about task destruction.
     243         */
     244        if (event_is_subscribed(EVENT_WAIT))
     245                event_notify_3(EVENT_WAIT, TASK_DESTROY, LOWER32(t->taskid),
     246                    UPPER32(t->taskid));
    230247       
    231248        free(t);
     
    333350}
    334351
    335 static void task_kill_internal(task_t *ta)
    336 {
    337         link_t *cur;
    338 
    339         /*
    340          * Interrupt all threads.
    341          */
    342         spinlock_lock(&ta->lock);
    343         for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
    344                 thread_t *thr;
    345                 bool sleeping = false;
    346                
    347                 thr = list_get_instance(cur, thread_t, th_link);
    348                
    349                 spinlock_lock(&thr->lock);
    350                 thr->interrupted = true;
    351                 if (thr->state == Sleeping)
    352                         sleeping = true;
    353                 spinlock_unlock(&thr->lock);
    354                
    355                 if (sleeping)
    356                         waitq_interrupt_sleep(thr);
    357         }
    358         spinlock_unlock(&ta->lock);
    359 }
    360 
    361352/** Kill task.
    362353 *
     
    372363        ipl_t ipl;
    373364        task_t *ta;
     365        link_t *cur;
    374366
    375367        if (id == 1)
     
    383375                return ENOENT;
    384376        }
    385         task_kill_internal(ta);
    386377        spinlock_unlock(&tasks_lock);
     378       
     379        /*
     380         * Interrupt all threads.
     381         */
     382        spinlock_lock(&ta->lock);
     383        for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
     384                thread_t *thr;
     385                bool sleeping = false;
     386               
     387                thr = list_get_instance(cur, thread_t, th_link);
     388               
     389                spinlock_lock(&thr->lock);
     390                thr->interrupted = true;
     391                if (thr->state == Sleeping)
     392                        sleeping = true;
     393                spinlock_unlock(&thr->lock);
     394               
     395                if (sleeping)
     396                        waitq_interrupt_sleep(thr);
     397        }
     398        spinlock_unlock(&ta->lock);
    387399        interrupts_restore(ipl);
     400       
    388401        return 0;
    389402}
Note: See TracChangeset for help on using the changeset viewer.