Changeset da1bafb in mainline for kernel/generic/src/proc/task.c


Ignore:
Timestamp:
2010-05-24T18:57:31Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
File:
1 edited

Legend:

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

    r666f492 rda1bafb  
    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_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       
    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
     
    346355       
    347356        if (node)
    348                 return avltree_get_instance(node, task_t, tasks_tree_node); 
     357                return avltree_get_instance(node, task_t, tasks_tree_node);
    349358       
    350359        return NULL;
     
    356365 * already disabled.
    357366 *
    358  * @param t       Pointer to thread.
     367 * @param task    Pointer to the task.
    359368 * @param ucycles Out pointer to sum of all user cycles.
    360369 * @param kcycles Out pointer to sum of all kernel cycles.
    361370 *
    362371 */
    363 void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles)
     372void task_get_accounting(task_t *task, uint64_t *ucycles, uint64_t *kcycles)
    364373{
    365374        /* Accumulated values of task */
    366         uint64_t uret = t->ucycles;
    367         uint64_t kret = t->kcycles;
     375        uint64_t uret = task->ucycles;
     376        uint64_t kret = task->kcycles;
    368377       
    369378        /* Current values of threads */
    370379        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);
     380        for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
     381                thread_t *thread = list_get_instance(cur, thread_t, th_link);
     382               
     383                irq_spinlock_lock(&thread->lock, false);
     384               
    375385                /* Process only counted threads */
    376                 if (!thr->uncounted) {
    377                         if (thr == THREAD) {
     386                if (!thread->uncounted) {
     387                        if (thread == THREAD) {
    378388                                /* Update accounting of current thread */
    379389                                thread_update_accounting(false);
    380                         }
    381                         uret += thr->ucycles;
    382                         kret += thr->kcycles;
     390                        }
     391                       
     392                        uret += thread->ucycles;
     393                        kret += thread->kcycles;
    383394                }
    384                 spinlock_unlock(&thr->lock);
     395               
     396                irq_spinlock_unlock(&thread->lock, false);
    385397        }
    386398       
     
    389401}
    390402
    391 static void task_kill_internal(task_t *ta)
     403static void task_kill_internal(task_t *task)
    392404{
    393405        link_t *cur;
     
    396408         * Interrupt all threads.
    397409         */
    398         spinlock_lock(&ta->lock);
    399         for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
    400                 thread_t *thr;
     410        irq_spinlock_lock(&task->lock, false);
     411        for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
     412                thread_t *thread = list_get_instance(cur, thread_t, th_link);
    401413                bool sleeping = false;
    402414               
    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)
     415                irq_spinlock_lock(&thread->lock, false);
     416               
     417                thread->interrupted = true;
     418                if (thread->state == Sleeping)
    408419                        sleeping = true;
    409                 spinlock_unlock(&thr->lock);
     420               
     421                irq_spinlock_unlock(&thread->lock, false);
    410422               
    411423                if (sleeping)
    412                         waitq_interrupt_sleep(thr);
     424                        waitq_interrupt_sleep(thread);
    413425        }
    414         spinlock_unlock(&ta->lock);
     426       
     427        irq_spinlock_unlock(&task->lock, false);
    415428}
    416429
     
    427440int task_kill(task_id_t id)
    428441{
    429         ipl_t ipl;
    430         task_t *ta;
    431 
    432442        if (id == 1)
    433443                return EPERM;
    434444       
    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);
     445        irq_spinlock_lock(&tasks_lock, true);
     446       
     447        task_t *task = task_find_by_id(id);
     448        if (!task) {
     449                irq_spinlock_unlock(&tasks_lock, true);
    440450                return ENOENT;
    441451        }
    442         task_kill_internal(ta);
    443         spinlock_unlock(&tasks_lock);
    444         interrupts_restore(ipl);
    445         return 0;
     452       
     453        task_kill_internal(task);
     454        irq_spinlock_unlock(&tasks_lock, true);
     455       
     456        return EOK;
    446457}
    447458
    448459static bool task_print_walker(avltree_node_t *node, void *arg)
    449460{
    450         task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    451         int j;
    452        
    453         spinlock_lock(&t->lock);
     461        task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
     462        irq_spinlock_lock(&task->lock, false);
    454463       
    455464        uint64_t ucycles;
    456465        uint64_t kcycles;
    457466        char usuffix, ksuffix;
    458         task_get_accounting(t, &ucycles, &kcycles);
     467        task_get_accounting(task, &ucycles, &kcycles);
    459468        order_suffix(ucycles, &ucycles, &usuffix);
    460469        order_suffix(kcycles, &kcycles, &ksuffix);
    461470       
    462 #ifdef __32_BITS__     
     471#ifdef __32_BITS__
    463472        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));
     473            PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context,
     474            task, task->as, ucycles, usuffix, kcycles, ksuffix,
     475            atomic_get(&task->refcount), atomic_get(&task->active_calls));
    467476#endif
    468477       
    469478#ifdef __64_BITS__
    470479        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);
     480            PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context,
     481            task, task->as, ucycles, usuffix, kcycles, ksuffix,
     482            atomic_get(&task->refcount), atomic_get(&task->active_calls));
     483#endif
     484       
     485        size_t i;
     486        for (i = 0; i < IPC_MAX_PHONES; i++) {
     487                if (task->phones[i].callee)
     488                        printf(" %" PRIs ":%p", i, task->phones[i].callee);
    479489        }
    480490        printf("\n");
    481491       
    482         spinlock_unlock(&t->lock);
     492        irq_spinlock_unlock(&task->lock, false);
    483493        return true;
    484494}
     
    487497void task_print_list(void)
    488498{
    489         ipl_t ipl;
    490        
    491499        /* Messing with task structures, avoid deadlock */
    492         ipl = interrupts_disable();
    493         spinlock_lock(&tasks_lock);
     500        irq_spinlock_lock(&tasks_lock, true);
    494501       
    495502#ifdef __32_BITS__
     
    509516        avltree_walk(&tasks_tree, task_print_walker, NULL);
    510517       
    511         spinlock_unlock(&tasks_lock);
    512         interrupts_restore(ipl);
     518        irq_spinlock_unlock(&tasks_lock, true);
    513519}
    514520
Note: See TracChangeset for help on using the changeset viewer.