Ignore:
File:
1 edited

Legend:

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

    rd3808d3 rbe06914  
    6060
    6161/** Spinlock protecting the tasks_tree AVL tree. */
    62 SPINLOCK_INITIALIZE(tasks_lock);
     62IRQ_SPINLOCK_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 *, int);
    84 
    85 /** Initialize kernel tasks support. */
     83static int tsk_constructor(void *, unsigned int);
     84
     85/** Initialize kernel tasks support.
     86 *
     87 */
    8688void task_init(void)
    8789{
     
    9294}
    9395
    94 /*
     96/** Task finish walker.
     97 *
    9598 * The idea behind this walker is to kill and count all tasks different from
    9699 * TASK.
     100 *
    97101 */
    98102static bool task_done_walker(avltree_node_t *node, void *arg)
    99103{
    100         task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    101         unsigned *cnt = (unsigned *) arg;
    102        
    103         if (t != TASK) {
     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) {
    104108                (*cnt)++;
     109               
    105110#ifdef CONFIG_DEBUG
    106                 printf("[%"PRIu64"] ", t->taskid);
    107 #endif
    108                 task_kill_internal(t);
     111                printf("[%"PRIu64"] ", task->taskid);
     112#endif
     113               
     114                task_kill_internal(task);
    109115        }
    110116       
     
    113119}
    114120
    115 /** Kill all tasks except the current task. */
     121/** Kill all tasks except the current task.
     122 *
     123 */
    116124void task_done(void)
    117125{
    118         unsigned tasks_left;
    119        
    120         do { /* Repeat until there are any tasks except TASK */
    121                 /* Messing with task structures, avoid deadlock */
     126        size_t tasks_left;
     127       
     128        /* Repeat until there are any tasks except TASK */
     129        do {
    122130#ifdef CONFIG_DEBUG
    123131                printf("Killing tasks... ");
    124132#endif
    125                 ipl_t ipl = interrupts_disable();
    126                 spinlock_lock(&tasks_lock);
     133               
     134                irq_spinlock_lock(&tasks_lock, true);
    127135                tasks_left = 0;
    128136                avltree_walk(&tasks_tree, task_done_walker, &tasks_left);
    129                 spinlock_unlock(&tasks_lock);
    130                 interrupts_restore(ipl);
     137                irq_spinlock_unlock(&tasks_lock, true);
     138               
    131139                thread_sleep(1);
     140               
    132141#ifdef CONFIG_DEBUG
    133142                printf("\n");
    134143#endif
    135         } while (tasks_left);
    136 }
    137 
    138 int 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);
     144        } while (tasks_left > 0);
     145}
     146
     147int 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;
    154164        for (i = 0; i < IPC_MAX_PHONES; i++)
    155                 ipc_phone_init(&ta->phones[i]);
     165                ipc_phone_init(&task->phones[i]);
    156166       
    157167#ifdef CONFIG_UDEBUG
    158168        /* Init kbox stuff */
    159         ta->kb.thread = NULL;
    160         ipc_answerbox_init(&ta->kb.box, ta);
    161         mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
     169        task->kb.thread = NULL;
     170        ipc_answerbox_init(&task->kb.box, task);
     171        mutex_initialize(&task->kb.cleanup_lock, MUTEX_PASSIVE);
    162172#endif
    163173       
     
    175185task_t *task_create(as_t *as, const char *name)
    176186{
    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 
     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_received = 0;
     200        task->ipc_info.answer_sent = 0;
     201        task->ipc_info.answer_received = 0;
     202        task->ipc_info.irq_notif_received = 0;
     203        task->ipc_info.forwarded = 0;
     204       
    198205#ifdef CONFIG_UDEBUG
    199206        /* Init debugging stuff */
    200         udebug_task_init(&ta->udebug);
     207        udebug_task_init(&task->udebug);
    201208       
    202209        /* Init kbox stuff */
    203         ta->kb.finished = false;
     210        task->kb.finished = false;
    204211#endif
    205212       
    206213        if ((ipc_phone_0) &&
    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);
     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);
    211218       
    212219        /*
    213220         * Get a reference to the address space.
    214221         */
    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;
     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;
    227234}
    228235
    229236/** Destroy task.
    230237 *
    231  * @param t Task to be destroyed.
    232  *
    233  */
    234 void task_destroy(task_t *t)
     238 * @param task Task to be destroyed.
     239 *
     240 */
     241void task_destroy(task_t *task)
    235242{
    236243        /*
    237244         * Remove the task from the task B+tree.
    238245         */
    239         spinlock_lock(&tasks_lock);
    240         avltree_delete(&tasks_tree, &t->tasks_tree_node);
    241         spinlock_unlock(&tasks_lock);
     246        irq_spinlock_lock(&tasks_lock, true);
     247        avltree_delete(&tasks_tree, &task->tasks_tree_node);
     248        irq_spinlock_unlock(&tasks_lock, true);
    242249       
    243250        /*
    244251         * Perform architecture specific task destruction.
    245252         */
    246         task_destroy_arch(t);
     253        task_destroy_arch(task);
    247254       
    248255        /*
    249256         * Free up dynamically allocated state.
    250257         */
    251         btree_destroy(&t->futexes);
     258        btree_destroy(&task->futexes);
    252259       
    253260        /*
    254261         * Drop our reference to the address space.
    255262         */
    256         as_release(t->as);
    257        
    258         slab_free(task_slab, t);
     263        as_release(task->as);
     264       
     265        slab_free(task_slab, task);
    259266}
    260267
     
    263270 * Holding a reference to a task prevents destruction of that task.
    264271 *
    265  * @param t             Task to be held.
    266  */
    267 void task_hold(task_t *t)
    268 {
    269         atomic_inc(&t->refcount);
     272 * @param task Task to be held.
     273 *
     274 */
     275void task_hold(task_t *task)
     276{
     277        atomic_inc(&task->refcount);
    270278}
    271279
     
    274282 * The last one to release a reference to a task destroys the task.
    275283 *
    276  * @param t             Task to be released.
    277  */
    278 void task_release(task_t *t)
    279 {
    280         if ((atomic_predec(&t->refcount)) == 0)
    281                 task_destroy(t);
     284 * @param task Task to be released.
     285 *
     286 */
     287void task_release(task_t *task)
     288{
     289        if ((atomic_predec(&task->refcount)) == 0)
     290                task_destroy(task);
    282291}
    283292
     
    342351task_t *task_find_by_id(task_id_t id)
    343352{
     353        ASSERT(interrupts_disabled());
     354        ASSERT(irq_spinlock_locked(&tasks_lock));
     355
    344356        avltree_node_t *node =
    345357            avltree_search(&tasks_tree, (avltree_key_t) id);
    346358       
    347359        if (node)
    348                 return avltree_get_instance(node, task_t, tasks_tree_node); 
     360                return avltree_get_instance(node, task_t, tasks_tree_node);
    349361       
    350362        return NULL;
     
    353365/** Get accounting data of given task.
    354366 *
    355  * Note that task lock of 't' must be already held and interrupts must be
     367 * Note that task lock of 'task' must be already held and interrupts must be
    356368 * already disabled.
    357369 *
    358  * @param t       Pointer to thread.
     370 * @param task    Pointer to the task.
    359371 * @param ucycles Out pointer to sum of all user cycles.
    360372 * @param kcycles Out pointer to sum of all kernel cycles.
    361373 *
    362374 */
    363 void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles)
    364 {
     375void 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
    365380        /* Accumulated values of task */
    366         uint64_t uret = t->ucycles;
    367         uint64_t kret = t->kcycles;
     381        uint64_t uret = task->ucycles;
     382        uint64_t kret = task->kcycles;
    368383       
    369384        /* Current values of threads */
    370385        link_t *cur;
    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);
    373                
    374                 spinlock_lock(&thr->lock);
     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);
     388               
     389                irq_spinlock_lock(&thread->lock, false);
     390               
    375391                /* Process only counted threads */
    376                 if (!thr->uncounted) {
    377                         if (thr == THREAD) {
     392                if (!thread->uncounted) {
     393                        if (thread == THREAD) {
    378394                                /* Update accounting of current thread */
    379395                                thread_update_accounting(false);
    380                         }
    381                         uret += thr->ucycles;
    382                         kret += thr->kcycles;
     396                        }
     397                       
     398                        uret += thread->ucycles;
     399                        kret += thread->kcycles;
    383400                }
    384                 spinlock_unlock(&thr->lock);
     401               
     402                irq_spinlock_unlock(&thread->lock, false);
    385403        }
    386404       
     
    389407}
    390408
    391 static void task_kill_internal(task_t *ta)
     409static void task_kill_internal(task_t *task)
    392410{
    393411        link_t *cur;
     
    396414         * Interrupt all threads.
    397415         */
    398         spinlock_lock(&ta->lock);
    399         for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
    400                 thread_t *thr;
     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);
    401419                bool sleeping = false;
    402420               
    403                 thr = list_get_instance(cur, thread_t, th_link);
    404                
    405                 spinlock_lock(&thr->lock);
    406                 thr->interrupted = true;
    407                 if (thr->state == Sleeping)
     421                irq_spinlock_lock(&thread->lock, false);
     422               
     423                thread->interrupted = true;
     424                if (thread->state == Sleeping)
    408425                        sleeping = true;
    409                 spinlock_unlock(&thr->lock);
     426               
     427                irq_spinlock_unlock(&thread->lock, false);
    410428               
    411429                if (sleeping)
    412                         waitq_interrupt_sleep(thr);
     430                        waitq_interrupt_sleep(thread);
    413431        }
    414         spinlock_unlock(&ta->lock);
     432       
     433        irq_spinlock_unlock(&task->lock, false);
    415434}
    416435
     
    427446int task_kill(task_id_t id)
    428447{
    429         ipl_t ipl;
    430         task_t *ta;
    431 
    432448        if (id == 1)
    433449                return EPERM;
    434450       
    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);
     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);
    440456                return ENOENT;
    441457        }
    442         task_kill_internal(ta);
    443         spinlock_unlock(&tasks_lock);
    444         interrupts_restore(ipl);
    445         return 0;
     458       
     459        task_kill_internal(task);
     460        irq_spinlock_unlock(&tasks_lock, true);
     461       
     462        return EOK;
    446463}
    447464
    448465static bool task_print_walker(avltree_node_t *node, void *arg)
    449466{
    450         task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    451         int j;
    452        
    453         spinlock_lock(&t->lock);
     467        bool *additional = (bool *) arg;
     468        task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
     469        irq_spinlock_lock(&task->lock, false);
    454470       
    455471        uint64_t ucycles;
    456472        uint64_t kcycles;
    457473        char usuffix, ksuffix;
    458         task_get_accounting(t, &ucycles, &kcycles);
     474        task_get_accounting(task, &ucycles, &kcycles);
    459475        order_suffix(ucycles, &ucycles, &usuffix);
    460476        order_suffix(kcycles, &kcycles, &ksuffix);
    461477       
    462 #ifdef __32_BITS__     
    463         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 "%c %9"
    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));
     478#ifdef __32_BITS__
     479        if (*additional)
     480                printf("%-8" PRIu64 " %9lu %7lu", task->taskid,
     481                    atomic_get(&task->refcount), atomic_get(&task->active_calls));
     482        else
     483                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p"
     484                    " %9" PRIu64 "%c %9" PRIu64 "%c\n", task->taskid,
     485                    task->name, task->context, task, task->as,
     486                    ucycles, usuffix, kcycles, ksuffix);
    467487#endif
    468488       
    469489#ifdef __64_BITS__
    470         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 "%c %9"
    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);
     490        if (*additional)
     491                printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c %9lu %7lu",
     492                    task->taskid, ucycles, usuffix, kcycles, ksuffix,
     493                    atomic_get(&task->refcount), atomic_get(&task->active_calls));
     494        else
     495                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
     496                    task->taskid, task->name, task->context, task, task->as);
     497#endif
     498       
     499        if (*additional) {
     500                size_t i;
     501                for (i = 0; i < IPC_MAX_PHONES; i++) {
     502                        if (task->phones[i].callee)
     503                                printf(" %" PRIs ":%p", i, task->phones[i].callee);
     504                }
     505                printf("\n");
    479506        }
    480         printf("\n");
    481        
    482         spinlock_unlock(&t->lock);
     507       
     508        irq_spinlock_unlock(&task->lock, false);
    483509        return true;
    484510}
    485511
    486 /** Print task list */
    487 void task_print_list(void)
    488 {
    489         ipl_t ipl;
    490        
     512/** Print task list
     513 *
     514 * @param additional Print additional information.
     515 *
     516 */
     517void task_print_list(bool additional)
     518{
    491519        /* Messing with task structures, avoid deadlock */
    492         ipl = interrupts_disable();
    493         spinlock_lock(&tasks_lock);
     520        irq_spinlock_lock(&tasks_lock, true);
    494521       
    495522#ifdef __32_BITS__
    496         printf("taskid name         ctx address    as        "
    497             " ucycles    kcycles    threads calls  callee\n");
    498         printf("------ ------------ --- ---------- ----------"
    499             " ---------- ---------- ------- ------ ------>\n");
     523        if (additional)
     524                printf("[id    ] [threads] [calls] [callee\n");
     525        else
     526                printf("[id    ] [name        ] [ctx] [address ] [as      ]"
     527                    " [ucycles ] [kcycles ]\n");
    500528#endif
    501529       
    502530#ifdef __64_BITS__
    503         printf("taskid name         ctx address            as                "
    504             " ucycles    kcycles    threads calls  callee\n");
    505         printf("------ ------------ --- ------------------ ------------------"
    506             " ---------- ---------- ---------- ------- ------ ------>\n");
    507 #endif
    508        
    509         avltree_walk(&tasks_tree, task_print_walker, NULL);
    510        
    511         spinlock_unlock(&tasks_lock);
    512         interrupts_restore(ipl);
     531        if (additional)
     532                printf("[id    ] [ucycles ] [kcycles ] [threads] [calls]"
     533                    " [callee\n");
     534        else
     535                printf("[id    ] [name        ] [ctx] [address         ]"
     536                    " [as              ]\n");
     537#endif
     538       
     539        avltree_walk(&tasks_tree, task_print_walker, &additional);
     540       
     541        irq_spinlock_unlock(&tasks_lock, true);
    513542}
    514543
Note: See TracChangeset for help on using the changeset viewer.