Changeset 46c20c8 in mainline for kernel/generic/src/proc


Ignore:
Timestamp:
2010-11-26T20:08:10Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
45df59a
Parents:
fb150d78 (diff), ffdd2b9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Location:
kernel/generic/src/proc
Files:
5 edited

Legend:

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

    rfb150d78 r46c20c8  
    3434/**
    3535 * @file
    36  * @brief       Running userspace programs.
     36 * @brief Running userspace programs.
    3737 */
    3838
     
    6666/** Create a program using an existing address space.
    6767 *
    68  * @param as            Address space containing a binary program image.
    69  * @param entry_addr    Program entry-point address in program address space.
    70  * @param name          Name to set for the program's task.
    71  * @param p             Buffer for storing program information.
    72  */
    73 void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p)
    74 {
    75         as_area_t *a;
     68 * @param as         Address space containing a binary program image.
     69 * @param entry_addr Program entry-point address in program address space.
     70 * @param name       Name to set for the program's task.
     71 * @param prg        Buffer for storing program information.
     72 *
     73 * @return EOK on success or negative error code.
     74 *
     75 */
     76int program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *prg)
     77{
    7678        uspace_arg_t *kernel_uarg;
    77 
     79       
    7880        kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
    7981        kernel_uarg->uspace_entry = (void *) entry_addr;
     
    8385        kernel_uarg->uspace_uarg = NULL;
    8486       
    85         p->task = task_create(as, name);
    86         ASSERT(p->task);
    87 
     87        prg->task = task_create(as, name);
     88        if (!prg->task)
     89                return ELIMIT;
     90       
    8891        /*
    89          * Create the data as_area.
     92         * Create the data address space area.
    9093         */
    91         a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
     94        as_area_t *area = as_area_create(as,
     95            AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
    9296            LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
    9397            AS_AREA_ATTR_NONE, &anon_backend, NULL);
    94 
     98        if (!area)
     99                return ENOMEM;
     100       
    95101        /*
    96102         * Create the main thread.
    97103         */
    98         p->main_thread = thread_create(uinit, kernel_uarg, p->task,
     104        prg->main_thread = thread_create(uinit, kernel_uarg, prg->task,
    99105            THREAD_FLAG_USPACE, "uinit", false);
    100         ASSERT(p->main_thread);
     106        if (!prg->main_thread)
     107                return ELIMIT;
     108       
     109        return EOK;
    101110}
    102111
     
    107116 * executable image. The task is returned in *task.
    108117 *
    109  * @param image_addr    Address of an executable program image.
    110  * @param name          Name to set for the program's task.
    111  * @param p             Buffer for storing program info. If image_addr
    112  *                      points to a loader image, p->task will be set to
    113  *                      NULL and EOK will be returned.
     118 * @param image_addr Address of an executable program image.
     119 * @param name       Name to set for the program's task.
     120 * @param prg        Buffer for storing program info. If image_addr
     121 *                   points to a loader image, p->task will be set to
     122 *                   NULL and EOK will be returned.
    114123 *
    115124 * @return EOK on success or negative error code.
    116  */
    117 int program_create_from_image(void *image_addr, char *name, program_t *p)
    118 {
    119         as_t *as;
    120         unsigned int rc;
    121 
    122         as = as_create(0);
    123         ASSERT(as);
    124 
    125         rc = elf_load((elf_header_t *) image_addr, as, 0);
     125 *
     126 */
     127int program_create_from_image(void *image_addr, char *name, program_t *prg)
     128{
     129        as_t *as = as_create(0);
     130        if (!as)
     131                return ENOMEM;
     132       
     133        unsigned int rc = elf_load((elf_header_t *) image_addr, as, 0);
    126134        if (rc != EE_OK) {
    127135                as_destroy(as);
    128                 p->task = NULL;
    129                 p->main_thread = NULL;
     136                prg->task = NULL;
     137                prg->main_thread = NULL;
     138               
    130139                if (rc != EE_LOADER)
    131140                        return ENOTSUP;
    132141               
    133142                /* Register image as the program loader */
    134                 ASSERT(program_loader == NULL);
     143                if (program_loader != NULL)
     144                        return ELIMIT;
     145               
    135146                program_loader = image_addr;
    136                 LOG("Registered program loader at 0x%" PRIp "\n",
    137                     image_addr);
     147                LOG("Registered program loader at %p",
     148                    (void *) image_addr);
     149               
    138150                return EOK;
    139151        }
    140 
    141         program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p);
    142 
    143         return EOK;
     152       
     153        return program_create(as, ((elf_header_t *) image_addr)->e_entry,
     154            name, prg);
    144155}
    145156
    146157/** Create a task from the program loader image.
    147158 *
    148  * @param p     Buffer for storing program info.
    149  * @param name  Name to set for the program's task.
     159 * @param prg  Buffer for storing program info.
     160 * @param name Name to set for the program's task.
    150161 *
    151162 * @return EOK on success or negative error code.
    152  */
    153 int program_create_loader(program_t *p, char *name)
    154 {
    155         as_t *as;
    156         unsigned int rc;
    157         void *loader;
    158 
    159         as = as_create(0);
    160         ASSERT(as);
    161 
    162         loader = program_loader;
     163 *
     164 */
     165int program_create_loader(program_t *prg, char *name)
     166{
     167        as_t *as = as_create(0);
     168        if (!as)
     169                return ENOMEM;
     170       
     171        void *loader = program_loader;
    163172        if (!loader) {
    164173                printf("Cannot spawn loader as none was registered\n");
    165174                return ENOENT;
    166175        }
    167 
    168         rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER);
     176       
     177        unsigned int rc = elf_load((elf_header_t *) program_loader, as,
     178            ELD_F_LOADER);
    169179        if (rc != EE_OK) {
    170180                as_destroy(as);
    171181                return ENOENT;
    172182        }
    173 
    174         program_create(as, ((elf_header_t *) program_loader)->e_entry,
    175             name, p);
    176 
    177         return EOK;
     183       
     184        return program_create(as, ((elf_header_t *) program_loader)->e_entry,
     185            name, prg);
    178186}
    179187
     
    182190 * Switch program's main thread to the ready state.
    183191 *
    184  * @param p Program to make ready.
    185  */
    186 void program_ready(program_t *p)
    187 {
    188         thread_ready(p->main_thread);
     192 * @param prg Program to make ready.
     193 *
     194 */
     195void program_ready(program_t *prg)
     196{
     197        thread_ready(prg->main_thread);
    189198}
    190199
     
    194203 * the task name.
    195204 *
    196  * @param name                  Name to set on the new task (typically the same
    197  *                              as the command used to execute it).
    198  *
    199  * @return 0 on success or an error code from @ref errno.h.
     205 * @param uspace_name Name to set on the new task (typically the same
     206 *                    as the command used to execute it).
     207 * @param name_len    Length of the name.
     208 *
     209 * @return EOK on success or an error code from @ref errno.h.
     210 *
    200211 */
    201212unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len)
    202213{
    203         program_t p;
    204         int rc;
    205         char namebuf[TASK_NAME_BUFLEN];
    206 
    207214        /* Cap length of name and copy it from userspace. */
    208 
    209215        if (name_len > TASK_NAME_BUFLEN - 1)
    210216                name_len = TASK_NAME_BUFLEN - 1;
    211 
    212         rc = copy_from_uspace(namebuf, uspace_name, name_len);
     217       
     218        char namebuf[TASK_NAME_BUFLEN];
     219        int rc = copy_from_uspace(namebuf, uspace_name, name_len);
    213220        if (rc != 0)
    214221                return (unative_t) rc;
    215 
     222       
    216223        namebuf[name_len] = 0;
    217 
     224       
    218225        /* Spawn the new task. */
    219 
    220         rc = program_create_loader(&p, namebuf);
     226        program_t prg;
     227        rc = program_create_loader(&prg, namebuf);
    221228        if (rc != 0)
    222229                return rc;
    223 
     230       
    224231        // FIXME: control the capabilities
    225         cap_set(p.task, cap_get(TASK));
    226 
    227         program_ready(&p);
    228 
     232        cap_set(prg.task, cap_get(TASK));
     233        program_ready(&prg);
     234       
    229235        return EOK;
    230236}
  • kernel/generic/src/proc/scheduler.c

    rfb150d78 r46c20c8  
    11/*
    2  * Copyright (c) 2001-2007 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3333/**
    3434 * @file
    35  * @brief       Scheduler and load balancing.
     35 * @brief Scheduler and load balancing.
    3636 *
    3737 * This file contains the scheduler and kcpulb kernel thread which
     
    6868static void scheduler_separated_stack(void);
    6969
    70 atomic_t nrdy;  /**< Number of ready threads in the system. */
     70atomic_t nrdy;  /**< Number of ready threads in the system. */
    7171
    7272/** Carry out actions before new task runs. */
     
    8989        before_thread_runs_arch();
    9090#ifdef CONFIG_FPU_LAZY
    91         if(THREAD == CPU->fpu_owner) 
     91        if(THREAD == CPU->fpu_owner)
    9292                fpu_enable();
    9393        else
    94                 fpu_disable(); 
     94                fpu_disable();
    9595#else
    9696        fpu_enable();
     
    123123restart:
    124124        fpu_enable();
    125         spinlock_lock(&CPU->lock);
    126 
     125        irq_spinlock_lock(&CPU->lock, false);
     126       
    127127        /* Save old context */
    128         if (CPU->fpu_owner != NULL) { 
    129                 spinlock_lock(&CPU->fpu_owner->lock);
     128        if (CPU->fpu_owner != NULL) {
     129                irq_spinlock_lock(&CPU->fpu_owner->lock, false);
    130130                fpu_context_save(CPU->fpu_owner->saved_fpu_context);
    131                 /* don't prevent migration */
     131               
     132                /* Don't prevent migration */
    132133                CPU->fpu_owner->fpu_context_engaged = 0;
    133                 spinlock_unlock(&CPU->fpu_owner->lock);
     134                irq_spinlock_unlock(&CPU->fpu_owner->lock, false);
    134135                CPU->fpu_owner = NULL;
    135136        }
    136 
    137         spinlock_lock(&THREAD->lock);
     137       
     138        irq_spinlock_lock(&THREAD->lock, false);
    138139        if (THREAD->fpu_context_exists) {
    139140                fpu_context_restore(THREAD->saved_fpu_context);
     
    142143                if (!THREAD->saved_fpu_context) {
    143144                        /* Might sleep */
    144                         spinlock_unlock(&THREAD->lock);
    145                         spinlock_unlock(&CPU->lock);
     145                        irq_spinlock_unlock(&THREAD->lock, false);
     146                        irq_spinlock_unlock(&CPU->lock, false);
    146147                        THREAD->saved_fpu_context =
    147148                            (fpu_context_t *) slab_alloc(fpu_context_slab, 0);
     149                       
    148150                        /* We may have switched CPUs during slab_alloc */
    149                         goto restart; 
     151                        goto restart;
    150152                }
    151153                fpu_init();
    152154                THREAD->fpu_context_exists = 1;
    153155        }
     156       
    154157        CPU->fpu_owner = THREAD;
    155158        THREAD->fpu_context_engaged = 1;
    156         spinlock_unlock(&THREAD->lock);
    157 
    158         spinlock_unlock(&CPU->lock);
    159 }
    160 #endif
     159        irq_spinlock_unlock(&THREAD->lock, false);
     160       
     161        irq_spinlock_unlock(&CPU->lock, false);
     162}
     163#endif /* CONFIG_FPU_LAZY */
    161164
    162165/** Initialize scheduler
     
    180183static thread_t *find_best_thread(void)
    181184{
    182         thread_t *t;
    183         runq_t *r;
    184         int i;
    185 
    186185        ASSERT(CPU != NULL);
    187 
     186       
    188187loop:
    189         interrupts_enable();
    190188       
    191189        if (atomic_get(&CPU->nrdy) == 0) {
     
    195193                 * This improves energy saving and hyperthreading.
    196194                 */
    197 
     195                irq_spinlock_lock(&CPU->lock, false);
     196                CPU->idle = true;
     197                irq_spinlock_unlock(&CPU->lock, false);
     198                interrupts_enable();
     199               
    198200                /*
    199201                 * An interrupt might occur right now and wake up a thread.
     
    201203                 * even though there is a runnable thread.
    202204                 */
    203 
    204                  cpu_sleep();
    205                  goto loop;
    206         }
    207 
    208         interrupts_disable();
    209        
     205                cpu_sleep();
     206                interrupts_disable();
     207                goto loop;
     208        }
     209       
     210        unsigned int i;
    210211        for (i = 0; i < RQ_COUNT; i++) {
    211                 r = &CPU->rq[i];
    212                 spinlock_lock(&r->lock);
    213                 if (r->n == 0) {
     212                irq_spinlock_lock(&(CPU->rq[i].lock), false);
     213                if (CPU->rq[i].n == 0) {
    214214                        /*
    215215                         * If this queue is empty, try a lower-priority queue.
    216216                         */
    217                         spinlock_unlock(&r->lock);
     217                        irq_spinlock_unlock(&(CPU->rq[i].lock), false);
    218218                        continue;
    219219                }
    220 
     220               
    221221                atomic_dec(&CPU->nrdy);
    222222                atomic_dec(&nrdy);
    223                 r->n--;
    224 
     223                CPU->rq[i].n--;
     224               
    225225                /*
    226226                 * Take the first thread from the queue.
    227227                 */
    228                 t = list_get_instance(r->rq_head.next, thread_t, rq_link);
    229                 list_remove(&t->rq_link);
    230 
    231                 spinlock_unlock(&r->lock);
    232 
    233                 spinlock_lock(&t->lock);
    234                 t->cpu = CPU;
    235 
    236                 t->ticks = us2ticks((i + 1) * 10000);
    237                 t->priority = i;        /* correct rq index */
    238 
     228                thread_t *thread =
     229                    list_get_instance(CPU->rq[i].rq_head.next, thread_t, rq_link);
     230                list_remove(&thread->rq_link);
     231               
     232                irq_spinlock_pass(&(CPU->rq[i].lock), &thread->lock);
     233               
     234                thread->cpu = CPU;
     235                thread->ticks = us2ticks((i + 1) * 10000);
     236                thread->priority = i;  /* Correct rq index */
     237               
    239238                /*
    240239                 * Clear the THREAD_FLAG_STOLEN flag so that t can be migrated
    241240                 * when load balancing needs emerge.
    242241                 */
    243                 t->flags &= ~THREAD_FLAG_STOLEN;
    244                 spinlock_unlock(&t->lock);
    245 
    246                 return t;
    247         }
     242                thread->flags &= ~THREAD_FLAG_STOLEN;
     243                irq_spinlock_unlock(&thread->lock, false);
     244               
     245                return thread;
     246        }
     247       
    248248        goto loop;
    249 
    250249}
    251250
     
    264263{
    265264        link_t head;
    266         runq_t *r;
    267         int i, n;
    268 
     265       
    269266        list_initialize(&head);
    270         spinlock_lock(&CPU->lock);
     267        irq_spinlock_lock(&CPU->lock, false);
     268       
    271269        if (CPU->needs_relink > NEEDS_RELINK_MAX) {
     270                int i;
    272271                for (i = start; i < RQ_COUNT - 1; i++) {
    273                         /* remember and empty rq[i + 1] */
    274                         r = &CPU->rq[i + 1];
    275                         spinlock_lock(&r->lock);
    276                         list_concat(&head, &r->rq_head);
    277                         n = r->n;
    278                         r->n = 0;
    279                         spinlock_unlock(&r->lock);
    280                
    281                         /* append rq[i + 1] to rq[i] */
    282                         r = &CPU->rq[i];
    283                         spinlock_lock(&r->lock);
    284                         list_concat(&r->rq_head, &head);
    285                         r->n += n;
    286                         spinlock_unlock(&r->lock);
     272                        /* Remember and empty rq[i + 1] */
     273                       
     274                        irq_spinlock_lock(&CPU->rq[i + 1].lock, false);
     275                        list_concat(&head, &CPU->rq[i + 1].rq_head);
     276                        size_t n = CPU->rq[i + 1].n;
     277                        CPU->rq[i + 1].n = 0;
     278                        irq_spinlock_unlock(&CPU->rq[i + 1].lock, false);
     279                       
     280                        /* Append rq[i + 1] to rq[i] */
     281                       
     282                        irq_spinlock_lock(&CPU->rq[i].lock, false);
     283                        list_concat(&CPU->rq[i].rq_head, &head);
     284                        CPU->rq[i].n += n;
     285                        irq_spinlock_unlock(&CPU->rq[i].lock, false);
    287286                }
     287               
    288288                CPU->needs_relink = 0;
    289289        }
    290         spinlock_unlock(&CPU->lock);
    291 
     290       
     291        irq_spinlock_unlock(&CPU->lock, false);
    292292}
    293293
     
    302302{
    303303        volatile ipl_t ipl;
    304 
     304       
    305305        ASSERT(CPU != NULL);
    306 
     306       
    307307        ipl = interrupts_disable();
    308 
     308       
    309309        if (atomic_get(&haltstate))
    310310                halt();
    311311       
    312312        if (THREAD) {
    313                 spinlock_lock(&THREAD->lock);
    314                
    315                 /* Update thread accounting */
    316                 THREAD->cycles += get_cycle() - THREAD->last_cycle;
     313                irq_spinlock_lock(&THREAD->lock, false);
     314               
     315                /* Update thread kernel accounting */
     316                THREAD->kcycles += get_cycle() - THREAD->last_cycle;
    317317               
    318318#ifndef CONFIG_FPU_LAZY
     
    327327                        THREAD->last_cycle = get_cycle();
    328328                       
    329                         spinlock_unlock(&THREAD->lock);
     329                        irq_spinlock_unlock(&THREAD->lock, false);
    330330                        interrupts_restore(THREAD->saved_context.ipl);
    331331                       
    332332                        return;
    333333                }
    334 
     334               
    335335                /*
    336336                 * Interrupt priority level of preempted thread is recorded
    337337                 * here to facilitate scheduler() invocations from
    338                  * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
     338                 * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
     339                 *
    339340                 */
    340341                THREAD->saved_context.ipl = ipl;
    341342        }
    342 
     343       
    343344        /*
    344345         * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, VM
    345346         * and preemption counter. At this point THE could be coming either
    346347         * from THREAD's or CPU's stack.
     348         *
    347349         */
    348350        the_copy(THE, (the_t *) CPU->stack);
    349 
     351       
    350352        /*
    351353         * We may not keep the old stack.
     
    359361         * Therefore the scheduler() function continues in
    360362         * scheduler_separated_stack().
     363         *
    361364         */
    362365        context_save(&CPU->saved_context);
     
    364367            (uintptr_t) CPU->stack, CPU_STACK_SIZE);
    365368        context_restore(&CPU->saved_context);
    366         /* not reached */
     369       
     370        /* Not reached */
    367371}
    368372
     
    373377 * switch to a new thread.
    374378 *
    375  * Assume THREAD->lock is held.
    376379 */
    377380void scheduler_separated_stack(void)
    378381{
    379         int priority;
    380382        DEADLOCK_PROBE_INIT(p_joinwq);
    381 
     383        task_t *old_task = TASK;
     384        as_t *old_as = AS;
     385       
     386        ASSERT((!THREAD) || (irq_spinlock_locked(&THREAD->lock)));
    382387        ASSERT(CPU != NULL);
    383388       
     389        /*
     390         * Hold the current task and the address space to prevent their
     391         * possible destruction should thread_destroy() be called on this or any
     392         * other processor while the scheduler is still using them.
     393         *
     394         */
     395        if (old_task)
     396                task_hold(old_task);
     397       
     398        if (old_as)
     399                as_hold(old_as);
     400       
    384401        if (THREAD) {
    385                 /* must be run after the switch to scheduler stack */
     402                /* Must be run after the switch to scheduler stack */
    386403                after_thread_ran();
    387 
     404               
    388405                switch (THREAD->state) {
    389406                case Running:
    390                         spinlock_unlock(&THREAD->lock);
     407                        irq_spinlock_unlock(&THREAD->lock, false);
    391408                        thread_ready(THREAD);
    392409                        break;
    393 
     410               
    394411                case Exiting:
    395412repeat:
    396413                        if (THREAD->detached) {
    397                                 thread_destroy(THREAD);
     414                                thread_destroy(THREAD, false);
    398415                        } else {
    399416                                /*
    400417                                 * The thread structure is kept allocated until
    401418                                 * somebody calls thread_detach() on it.
     419                                 *
    402420                                 */
    403                                 if (!spinlock_trylock(&THREAD->join_wq.lock)) {
     421                                if (!irq_spinlock_trylock(&THREAD->join_wq.lock)) {
    404422                                        /*
    405423                                         * Avoid deadlock.
     424                                         *
    406425                                         */
    407                                         spinlock_unlock(&THREAD->lock);
     426                                        irq_spinlock_unlock(&THREAD->lock, false);
    408427                                        delay(HZ);
    409                                         spinlock_lock(&THREAD->lock);
     428                                        irq_spinlock_lock(&THREAD->lock, false);
    410429                                        DEADLOCK_PROBE(p_joinwq,
    411430                                            DEADLOCK_THRESHOLD);
     
    414433                                _waitq_wakeup_unsafe(&THREAD->join_wq,
    415434                                    WAKEUP_FIRST);
    416                                 spinlock_unlock(&THREAD->join_wq.lock);
     435                                irq_spinlock_unlock(&THREAD->join_wq.lock, false);
    417436                               
    418437                                THREAD->state = Lingering;
    419                                 spinlock_unlock(&THREAD->lock);
     438                                irq_spinlock_unlock(&THREAD->lock, false);
    420439                        }
    421440                        break;
     
    424443                        /*
    425444                         * Prefer the thread after it's woken up.
     445                         *
    426446                         */
    427447                        THREAD->priority = -1;
    428 
     448                       
    429449                        /*
    430450                         * We need to release wq->lock which we locked in
    431451                         * waitq_sleep(). Address of wq->lock is kept in
    432452                         * THREAD->sleep_queue.
     453                         *
    433454                         */
    434                         spinlock_unlock(&THREAD->sleep_queue->lock);
    435 
    436                         /*
    437                          * Check for possible requests for out-of-context
    438                          * invocation.
    439                          */
    440                         if (THREAD->call_me) {
    441                                 THREAD->call_me(THREAD->call_me_with);
    442                                 THREAD->call_me = NULL;
    443                                 THREAD->call_me_with = NULL;
    444                         }
    445 
    446                         spinlock_unlock(&THREAD->lock);
    447 
     455                        irq_spinlock_unlock(&THREAD->sleep_queue->lock, false);
     456                       
     457                        irq_spinlock_unlock(&THREAD->lock, false);
    448458                        break;
    449 
     459               
    450460                default:
    451461                        /*
    452462                         * Entering state is unexpected.
     463                         *
    453464                         */
    454465                        panic("tid%" PRIu64 ": unexpected state %s.",
     
    456467                        break;
    457468                }
    458 
     469               
    459470                THREAD = NULL;
    460471        }
    461 
     472       
    462473        THREAD = find_best_thread();
    463474       
    464         spinlock_lock(&THREAD->lock);
    465         priority = THREAD->priority;
    466         spinlock_unlock(&THREAD->lock);
    467 
    468         relink_rq(priority);           
    469 
     475        irq_spinlock_lock(&THREAD->lock, false);
     476        int priority = THREAD->priority;
     477        irq_spinlock_unlock(&THREAD->lock, false);
     478       
     479        relink_rq(priority);
     480       
    470481        /*
    471482         * If both the old and the new task are the same, lots of work is
    472483         * avoided.
     484         *
    473485         */
    474486        if (TASK != THREAD->task) {
    475                 as_t *as1 = NULL;
    476                 as_t *as2;
    477 
    478                 if (TASK) {
    479                         spinlock_lock(&TASK->lock);
    480                         as1 = TASK->as;
    481                         spinlock_unlock(&TASK->lock);
    482                 }
    483 
    484                 spinlock_lock(&THREAD->task->lock);
    485                 as2 = THREAD->task->as;
    486                 spinlock_unlock(&THREAD->task->lock);
     487                as_t *new_as = THREAD->task->as;
    487488               
    488489                /*
    489490                 * Note that it is possible for two tasks to share one address
    490491                 * space.
     492                 (
    491493                 */
    492                 if (as1 != as2) {
     494                if (old_as != new_as) {
    493495                        /*
    494496                         * Both tasks and address spaces are different.
    495497                         * Replace the old one with the new one.
     498                         *
    496499                         */
    497                         as_switch(as1, as2);
     500                        as_switch(old_as, new_as);
    498501                }
     502               
    499503                TASK = THREAD->task;
    500504                before_task_runs();
    501505        }
    502 
    503         spinlock_lock(&THREAD->lock);   
     506       
     507        if (old_task)
     508                task_release(old_task);
     509       
     510        if (old_as)
     511                as_release(old_as);
     512       
     513        irq_spinlock_lock(&THREAD->lock, false);
    504514        THREAD->state = Running;
    505 
     515       
    506516#ifdef SCHEDULER_VERBOSE
    507517        printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
    508518            ", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
    509519            THREAD->ticks, atomic_get(&CPU->nrdy));
    510 #endif 
    511 
     520#endif
     521       
    512522        /*
    513523         * Some architectures provide late kernel PA2KA(identity)
     
    517527         * necessary, is to be mapped in before_thread_runs(). This
    518528         * function must be executed before the switch to the new stack.
     529         *
    519530         */
    520531        before_thread_runs();
    521 
     532       
    522533        /*
    523534         * Copy the knowledge of CPU, TASK, THREAD and preemption counter to
    524535         * thread's stack.
     536         *
    525537         */
    526538        the_copy(THE, (the_t *) THREAD->kstack);
    527539       
    528540        context_restore(&THREAD->saved_context);
    529         /* not reached */
     541       
     542        /* Not reached */
    530543}
    531544
     
    541554void kcpulb(void *arg)
    542555{
    543         thread_t *t;
    544         int count, average, j, k = 0;
    545         unsigned int i;
    546         ipl_t ipl;
    547 
     556        atomic_count_t average;
     557        atomic_count_t rdy;
     558       
    548559        /*
    549560         * Detach kcpulb as nobody will call thread_join_timeout() on it.
     
    556567         */
    557568        thread_sleep(1);
    558 
     569       
    559570not_satisfied:
    560571        /*
     
    562573         * other CPU's. Note that situation can have changed between two
    563574         * passes. Each time get the most up to date counts.
     575         *
    564576         */
    565577        average = atomic_get(&nrdy) / config.cpu_active + 1;
    566         count = average - atomic_get(&CPU->nrdy);
    567 
    568         if (count <= 0)
     578        rdy = atomic_get(&CPU->nrdy);
     579       
     580        if (average <= rdy)
    569581                goto satisfied;
    570 
     582       
     583        atomic_count_t count = average - rdy;
     584       
    571585        /*
    572586         * Searching least priority queues on all CPU's first and most priority
    573587         * queues on all CPU's last.
    574          */
    575         for (j = RQ_COUNT - 1; j >= 0; j--) {
    576                 for (i = 0; i < config.cpu_active; i++) {
    577                         link_t *l;
    578                         runq_t *r;
    579                         cpu_t *cpu;
    580 
    581                         cpu = &cpus[(i + k) % config.cpu_active];
    582 
     588         *
     589         */
     590        size_t acpu;
     591        size_t acpu_bias = 0;
     592        int rq;
     593       
     594        for (rq = RQ_COUNT - 1; rq >= 0; rq--) {
     595                for (acpu = 0; acpu < config.cpu_active; acpu++) {
     596                        cpu_t *cpu = &cpus[(acpu + acpu_bias) % config.cpu_active];
     597                       
    583598                        /*
    584599                         * Not interested in ourselves.
    585600                         * Doesn't require interrupt disabling for kcpulb has
    586601                         * THREAD_FLAG_WIRED.
     602                         *
    587603                         */
    588604                        if (CPU == cpu)
    589605                                continue;
     606                       
    590607                        if (atomic_get(&cpu->nrdy) <= average)
    591608                                continue;
    592 
    593                         ipl = interrupts_disable();
    594                         r = &cpu->rq[j];
    595                         spinlock_lock(&r->lock);
    596                         if (r->n == 0) {
    597                                 spinlock_unlock(&r->lock);
    598                                 interrupts_restore(ipl);
     609                       
     610                        irq_spinlock_lock(&(cpu->rq[rq].lock), true);
     611                        if (cpu->rq[rq].n == 0) {
     612                                irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
    599613                                continue;
    600614                        }
    601                
    602                         t = NULL;
    603                         l = r->rq_head.prev;    /* search rq from the back */
    604                         while (l != &r->rq_head) {
    605                                 t = list_get_instance(l, thread_t, rq_link);
     615                       
     616                        thread_t *thread = NULL;
     617                       
     618                        /* Search rq from the back */
     619                        link_t *link = cpu->rq[rq].rq_head.prev;
     620                       
     621                        while (link != &(cpu->rq[rq].rq_head)) {
     622                                thread = (thread_t *) list_get_instance(link, thread_t, rq_link);
     623                               
    606624                                /*
    607625                                 * We don't want to steal CPU-wired threads
     
    611629                                 * steal threads whose FPU context is still in
    612630                                 * CPU.
     631                                 *
    613632                                 */
    614                                 spinlock_lock(&t->lock);
    615                                 if ((!(t->flags & (THREAD_FLAG_WIRED |
    616                                     THREAD_FLAG_STOLEN))) &&
    617                                     (!(t->fpu_context_engaged))) {
     633                                irq_spinlock_lock(&thread->lock, false);
     634                               
     635                                if ((!(thread->flags & (THREAD_FLAG_WIRED | THREAD_FLAG_STOLEN)))
     636                                    && (!(thread->fpu_context_engaged))) {
    618637                                        /*
    619                                          * Remove t from r.
     638                                         * Remove thread from ready queue.
    620639                                         */
    621                                         spinlock_unlock(&t->lock);
     640                                        irq_spinlock_unlock(&thread->lock, false);
    622641                                       
    623642                                        atomic_dec(&cpu->nrdy);
    624643                                        atomic_dec(&nrdy);
    625 
    626                                         r->n--;
    627                                         list_remove(&t->rq_link);
    628 
     644                                       
     645                                        cpu->rq[rq].n--;
     646                                        list_remove(&thread->rq_link);
     647                                       
    629648                                        break;
    630649                                }
    631                                 spinlock_unlock(&t->lock);
    632                                 l = l->prev;
    633                                 t = NULL;
     650                               
     651                                irq_spinlock_unlock(&thread->lock, false);
     652                               
     653                                link = link->prev;
     654                                thread = NULL;
    634655                        }
    635                         spinlock_unlock(&r->lock);
    636 
    637                         if (t) {
     656                       
     657                        if (thread) {
    638658                                /*
    639                                  * Ready t on local CPU
     659                                 * Ready thread on local CPU
     660                                 *
    640661                                 */
    641                                 spinlock_lock(&t->lock);
     662                               
     663                                irq_spinlock_pass(&(cpu->rq[rq].lock), &thread->lock);
     664                               
    642665#ifdef KCPULB_VERBOSE
    643666                                printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
     
    646669                                    atomic_get(&nrdy) / config.cpu_active);
    647670#endif
    648                                 t->flags |= THREAD_FLAG_STOLEN;
    649                                 t->state = Entering;
    650                                 spinlock_unlock(&t->lock);
    651        
    652                                 thread_ready(t);
    653 
    654                                 interrupts_restore(ipl);
    655        
     671                               
     672                                thread->flags |= THREAD_FLAG_STOLEN;
     673                                thread->state = Entering;
     674                               
     675                                irq_spinlock_unlock(&thread->lock, true);
     676                                thread_ready(thread);
     677                               
    656678                                if (--count == 0)
    657679                                        goto satisfied;
    658                                        
     680                               
    659681                                /*
    660682                                 * We are not satisfied yet, focus on another
    661683                                 * CPU next time.
     684                                 *
    662685                                 */
    663                                 k++;
     686                                acpu_bias++;
    664687                               
    665688                                continue;
    666                         }
    667                         interrupts_restore(ipl);
     689                        } else
     690                                irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
     691                       
    668692                }
    669693        }
    670 
     694       
    671695        if (atomic_get(&CPU->nrdy)) {
    672696                /*
    673697                 * Be a little bit light-weight and let migrated threads run.
     698                 *
    674699                 */
    675700                scheduler();
     
    678703                 * We failed to migrate a single thread.
    679704                 * Give up this turn.
     705                 *
    680706                 */
    681707                goto loop;
    682708        }
    683                
     709       
    684710        goto not_satisfied;
    685 
     711       
    686712satisfied:
    687713        goto loop;
    688714}
    689 
    690715#endif /* CONFIG_SMP */
    691716
    692 
    693 /** Print information about threads & scheduler queues */
     717/** Print information about threads & scheduler queues
     718 *
     719 */
    694720void sched_print_list(void)
    695721{
    696         ipl_t ipl;
    697         unsigned int cpu, i;
    698         runq_t *r;
    699         thread_t *t;
    700         link_t *cur;
    701 
    702         /* We are going to mess with scheduler structures,
    703          * let's not be interrupted */
    704         ipl = interrupts_disable();
     722        size_t cpu;
    705723        for (cpu = 0; cpu < config.cpu_count; cpu++) {
    706 
    707724                if (!cpus[cpu].active)
    708725                        continue;
    709 
    710                 spinlock_lock(&cpus[cpu].lock);
    711                 printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIs "\n",
     726               
     727                irq_spinlock_lock(&cpus[cpu].lock, true);
     728               
     729                printf("cpu%u: address=%p, nrdy=%" PRIua ", needs_relink=%zu\n",
    712730                    cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
    713731                    cpus[cpu].needs_relink);
    714732               
     733                unsigned int i;
    715734                for (i = 0; i < RQ_COUNT; i++) {
    716                         r = &cpus[cpu].rq[i];
    717                         spinlock_lock(&r->lock);
    718                         if (!r->n) {
    719                                 spinlock_unlock(&r->lock);
     735                        irq_spinlock_lock(&(cpus[cpu].rq[i].lock), false);
     736                        if (cpus[cpu].rq[i].n == 0) {
     737                                irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
    720738                                continue;
    721739                        }
     740                       
    722741                        printf("\trq[%u]: ", i);
    723                         for (cur = r->rq_head.next; cur != &r->rq_head;
    724                                 cur = cur->next) {
    725                                 t = list_get_instance(cur, thread_t, rq_link);
    726                                 printf("%" PRIu64 "(%s) ", t->tid,
    727                                     thread_states[t->state]);
     742                        link_t *cur;
     743                        for (cur = cpus[cpu].rq[i].rq_head.next;
     744                            cur != &(cpus[cpu].rq[i].rq_head);
     745                            cur = cur->next) {
     746                                thread_t *thread = list_get_instance(cur, thread_t, rq_link);
     747                                printf("%" PRIu64 "(%s) ", thread->tid,
     748                                    thread_states[thread->state]);
    728749                        }
    729750                        printf("\n");
    730                         spinlock_unlock(&r->lock);
     751                       
     752                        irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
    731753                }
    732                 spinlock_unlock(&cpus[cpu].lock);
    733         }
    734        
    735         interrupts_restore(ipl);
     754               
     755                irq_spinlock_unlock(&cpus[cpu].lock, true);
     756        }
    736757}
    737758
  • kernel/generic/src/proc/task.c

    rfb150d78 r46c20c8  
    11/*
    2  * Copyright (c) 2001-2004 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3333/**
    3434 * @file
    35  * @brief       Task management.
     35 * @brief Task management.
    3636 */
    3737
     
    5353#include <errno.h>
    5454#include <func.h>
    55 #include <string.h>
     55#include <str.h>
    5656#include <memstr.h>
    5757#include <syscall/copy.h>
     
    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.
     
    6666 * The task is guaranteed to exist after it was found in the tasks_tree as
    6767 * long as:
     68 *
    6869 * @li the tasks_lock is held,
    6970 * @li the task's lock is held when task's lock is acquired before releasing
     
    8081/* Forward declarations. */
    8182static void task_kill_internal(task_t *);
    82 static int tsk_constructor(void *, int);
    83 
    84 /** Initialize kernel tasks support. */
     83static int tsk_constructor(void *, unsigned int);
     84
     85/** Initialize kernel tasks support.
     86 *
     87 */
    8588void task_init(void)
    8689{
     
    9194}
    9295
    93 /*
     96/** Task finish walker.
     97 *
    9498 * The idea behind this walker is to kill and count all tasks different from
    9599 * TASK.
     100 *
    96101 */
    97102static bool task_done_walker(avltree_node_t *node, void *arg)
    98103{
    99         task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    100         unsigned *cnt = (unsigned *) arg;
    101 
    102         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) {
    103108                (*cnt)++;
     109               
    104110#ifdef CONFIG_DEBUG
    105                 printf("[%"PRIu64"] ", t->taskid);
    106 #endif
    107                 task_kill_internal(t);
     111                printf("[%"PRIu64"] ", task->taskid);
     112#endif
     113               
     114                task_kill_internal(task);
    108115        }
    109 
    110         return true;    /* continue the walk */
    111 }
    112 
    113 /** Kill all tasks except the current task. */
     116       
     117        /* Continue the walk */
     118        return true;
     119}
     120
     121/** Kill all tasks except the current task.
     122 *
     123 */
    114124void task_done(void)
    115125{
    116         unsigned tasks_left;
    117 
    118         do { /* Repeat until there are any tasks except TASK */
    119                 /* Messing with task structures, avoid deadlock */
     126        size_t tasks_left;
     127       
     128        /* Repeat until there are any tasks except TASK */
     129        do {
    120130#ifdef CONFIG_DEBUG
    121131                printf("Killing tasks... ");
    122132#endif
    123                 ipl_t ipl = interrupts_disable();
    124                 spinlock_lock(&tasks_lock);
     133               
     134                irq_spinlock_lock(&tasks_lock, true);
    125135                tasks_left = 0;
    126136                avltree_walk(&tasks_tree, task_done_walker, &tasks_left);
    127                 spinlock_unlock(&tasks_lock);
    128                 interrupts_restore(ipl);
     137                irq_spinlock_unlock(&tasks_lock, true);
     138               
    129139                thread_sleep(1);
     140               
    130141#ifdef CONFIG_DEBUG
    131142                printf("\n");
    132143#endif
    133         } while (tasks_left);
    134 }
    135 
    136 int tsk_constructor(void *obj, int kmflags)
    137 {
    138         task_t *ta = obj;
    139         int i;
    140 
    141         atomic_set(&ta->refcount, 0);
    142         atomic_set(&ta->lifecount, 0);
    143         atomic_set(&ta->active_calls, 0);
    144 
    145         spinlock_initialize(&ta->lock, "task_ta_lock");
    146         mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
    147 
    148         list_initialize(&ta->th_head);
    149         list_initialize(&ta->sync_box_head);
    150 
    151         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;
    152164        for (i = 0; i < IPC_MAX_PHONES; i++)
    153                 ipc_phone_init(&ta->phones[i]);
    154 
     165                ipc_phone_init(&task->phones[i]);
     166       
    155167#ifdef CONFIG_UDEBUG
    156168        /* Init kbox stuff */
    157         ta->kb.thread = NULL;
    158         ipc_answerbox_init(&ta->kb.box, ta);
    159         mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
    160 #endif
    161 
     169        task->kb.thread = NULL;
     170        ipc_answerbox_init(&task->kb.box, task);
     171        mutex_initialize(&task->kb.cleanup_lock, MUTEX_PASSIVE);
     172#endif
     173       
    162174        return 0;
    163175}
     
    165177/** Create new task with no threads.
    166178 *
    167  * @param as            Task's address space.
    168  * @param name          Symbolic name (a copy is made).
    169  *
    170  * @return              New task's structure.
    171  *
    172  */
    173 task_t *task_create(as_t *as, char *name)
    174 {
    175         ipl_t ipl;
    176         task_t *ta;
    177        
    178         ta = (task_t *) slab_alloc(task_slab, 0);
    179         task_create_arch(ta);
    180         ta->as = as;
    181         memcpy(ta->name, name, TASK_NAME_BUFLEN);
    182         ta->name[TASK_NAME_BUFLEN - 1] = 0;
    183 
    184         ta->context = CONTEXT;
    185         ta->capabilities = 0;
    186         ta->cycles = 0;
    187 
     179 * @param as   Task's address space.
     180 * @param name Symbolic name (a copy is made).
     181 *
     182 * @return New task's structure.
     183 *
     184 */
     185task_t *task_create(as_t *as, const char *name)
     186{
     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       
    188205#ifdef CONFIG_UDEBUG
    189206        /* Init debugging stuff */
    190         udebug_task_init(&ta->udebug);
    191 
     207        udebug_task_init(&task->udebug);
     208       
    192209        /* Init kbox stuff */
    193         ta->kb.finished = false;
    194 #endif
    195 
     210        task->kb.finished = false;
     211#endif
     212       
    196213        if ((ipc_phone_0) &&
    197             (context_check(ipc_phone_0->task->context, ta->context)))
    198                 ipc_phone_connect(&ta->phones[0], ipc_phone_0);
    199 
    200         btree_create(&ta->futexes);
    201        
    202         ipl = interrupts_disable();
    203         atomic_inc(&as->refcount);
    204         spinlock_lock(&tasks_lock);
    205         ta->taskid = ++task_counter;
    206         avltree_node_initialize(&ta->tasks_tree_node);
    207         ta->tasks_tree_node.key = ta->taskid;
    208         avltree_insert(&tasks_tree, &ta->tasks_tree_node);
    209         spinlock_unlock(&tasks_lock);
    210         interrupts_restore(ipl);
    211        
    212         return ta;
     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);
     218       
     219        /*
     220         * Get a reference to the address space.
     221         */
     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;
    213234}
    214235
    215236/** Destroy task.
    216237 *
    217  * @param t             Task to be destroyed.
    218  */
    219 void task_destroy(task_t *t)
     238 * @param task Task to be destroyed.
     239 *
     240 */
     241void task_destroy(task_t *task)
    220242{
    221243        /*
    222244         * Remove the task from the task B+tree.
    223245         */
    224         spinlock_lock(&tasks_lock);
    225         avltree_delete(&tasks_tree, &t->tasks_tree_node);
    226         spinlock_unlock(&tasks_lock);
    227 
     246        irq_spinlock_lock(&tasks_lock, true);
     247        avltree_delete(&tasks_tree, &task->tasks_tree_node);
     248        irq_spinlock_unlock(&tasks_lock, true);
     249       
    228250        /*
    229251         * Perform architecture specific task destruction.
    230252         */
    231         task_destroy_arch(t);
    232 
     253        task_destroy_arch(task);
     254       
    233255        /*
    234256         * Free up dynamically allocated state.
    235257         */
    236         btree_destroy(&t->futexes);
    237 
     258        btree_destroy(&task->futexes);
     259       
    238260        /*
    239261         * Drop our reference to the address space.
    240262         */
    241         if (atomic_predec(&t->as->refcount) == 0)
    242                 as_destroy(t->as);
    243        
    244         slab_free(task_slab, t);
    245         TASK = NULL;
     263        as_release(task->as);
     264       
     265        slab_free(task_slab, task);
     266}
     267
     268/** Hold a reference to a task.
     269 *
     270 * Holding a reference to a task prevents destruction of that task.
     271 *
     272 * @param task Task to be held.
     273 *
     274 */
     275void task_hold(task_t *task)
     276{
     277        atomic_inc(&task->refcount);
     278}
     279
     280/** Release a reference to a task.
     281 *
     282 * The last one to release a reference to a task destroys the task.
     283 *
     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);
    246291}
    247292
    248293/** Syscall for reading task ID from userspace.
    249294 *
    250  * @param               uspace_task_id userspace address of 8-byte buffer
    251  *                      where to store current task ID.
    252  *
    253  * @return              Zero on success or an error code from @ref errno.h.
     295 * @param uspace_task_id Userspace address of 8-byte buffer
     296 *                       where to store current task ID.
     297 *
     298 * @return Zero on success or an error code from @ref errno.h.
     299 *
    254300 */
    255301unative_t sys_task_get_id(task_id_t *uspace_task_id)
     
    267313 * The name simplifies identifying the task in the task list.
    268314 *
    269  * @param name  The new name for the task. (typically the same
    270  *              as the command used to execute it).
     315 * @param name The new name for the task. (typically the same
     316 *             as the command used to execute it).
    271317 *
    272318 * @return 0 on success or an error code from @ref errno.h.
     319 *
    273320 */
    274321unative_t sys_task_set_name(const char *uspace_name, size_t name_len)
     
    276323        int rc;
    277324        char namebuf[TASK_NAME_BUFLEN];
    278 
     325       
    279326        /* Cap length of name and copy it from userspace. */
    280 
     327       
    281328        if (name_len > TASK_NAME_BUFLEN - 1)
    282329                name_len = TASK_NAME_BUFLEN - 1;
    283 
     330       
    284331        rc = copy_from_uspace(namebuf, uspace_name, name_len);
    285332        if (rc != 0)
    286333                return (unative_t) rc;
    287 
     334       
    288335        namebuf[name_len] = '\0';
    289336        str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf);
    290 
     337       
    291338        return EOK;
    292339}
     
    297344 * interrupts must be disabled.
    298345 *
    299  * @param id            Task ID.
    300  *
    301  * @return              Task structure address or NULL if there is no such task
    302  *                      ID.
    303  */
    304 task_t *task_find_by_id(task_id_t id) { avltree_node_t *node;
    305        
    306         node = avltree_search(&tasks_tree, (avltree_key_t) id);
    307 
     346 * @param id Task ID.
     347 *
     348 * @return Task structure address or NULL if there is no such task ID.
     349 *
     350 */
     351task_t *task_find_by_id(task_id_t id)
     352{
     353        ASSERT(interrupts_disabled());
     354        ASSERT(irq_spinlock_locked(&tasks_lock));
     355
     356        avltree_node_t *node =
     357            avltree_search(&tasks_tree, (avltree_key_t) id);
     358       
    308359        if (node)
    309                 return avltree_get_instance(node, task_t, tasks_tree_node);
     360                return avltree_get_instance(node, task_t, tasks_tree_node);
     361       
    310362        return NULL;
    311363}
     
    313365/** Get accounting data of given task.
    314366 *
    315  * 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
    316368 * already disabled.
    317369 *
    318  * @param t             Pointer to thread.
    319  *
    320  * @return              Number of cycles used by the task and all its threads
    321  *                      so far.
    322  */
    323 uint64_t task_get_accounting(task_t *t)
    324 {
    325         /* Accumulated value of task */
    326         uint64_t ret = t->cycles;
     370 * @param task    Pointer to the task.
     371 * @param ucycles Out pointer to sum of all user cycles.
     372 * @param kcycles Out pointer to sum of all kernel cycles.
     373 *
     374 */
     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
     380        /* Accumulated values of task */
     381        uint64_t uret = task->ucycles;
     382        uint64_t kret = task->kcycles;
    327383       
    328384        /* Current values of threads */
    329385        link_t *cur;
    330         for (cur = t->th_head.next; cur != &t->th_head; cur = cur->next) {
    331                 thread_t *thr = list_get_instance(cur, thread_t, th_link);
    332                
    333                 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               
    334391                /* Process only counted threads */
    335                 if (!thr->uncounted) {
    336                         if (thr == THREAD) {
     392                if (!thread->uncounted) {
     393                        if (thread == THREAD) {
    337394                                /* Update accounting of current thread */
    338                                 thread_update_accounting();
    339                         }
    340                         ret += thr->cycles;
     395                                thread_update_accounting(false);
     396                        }
     397                       
     398                        uret += thread->ucycles;
     399                        kret += thread->kcycles;
    341400                }
    342                 spinlock_unlock(&thr->lock);
     401               
     402                irq_spinlock_unlock(&thread->lock, false);
    343403        }
    344404       
    345         return ret;
    346 }
    347 
    348 static void task_kill_internal(task_t *ta)
     405        *ucycles = uret;
     406        *kcycles = kret;
     407}
     408
     409static void task_kill_internal(task_t *task)
    349410{
    350411        link_t *cur;
    351 
     412       
    352413        /*
    353414         * Interrupt all threads.
    354415         */
    355         spinlock_lock(&ta->lock);
    356         for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
    357                 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);
    358419                bool sleeping = false;
    359420               
    360                 thr = list_get_instance(cur, thread_t, th_link);
    361                
    362                 spinlock_lock(&thr->lock);
    363                 thr->interrupted = true;
    364                 if (thr->state == Sleeping)
     421                irq_spinlock_lock(&thread->lock, false);
     422               
     423                thread->interrupted = true;
     424                if (thread->state == Sleeping)
    365425                        sleeping = true;
    366                 spinlock_unlock(&thr->lock);
     426               
     427                irq_spinlock_unlock(&thread->lock, false);
    367428               
    368429                if (sleeping)
    369                         waitq_interrupt_sleep(thr);
     430                        waitq_interrupt_sleep(thread);
    370431        }
    371         spinlock_unlock(&ta->lock);
     432       
     433        irq_spinlock_unlock(&task->lock, false);
    372434}
    373435
     
    377439 * It signals all the task's threads to bail it out.
    378440 *
    379  * @param id            ID of the task to be killed.
    380  *
    381  * @return              Zero on success or an error code from errno.h.
     441 * @param id ID of the task to be killed.
     442 *
     443 * @return Zero on success or an error code from errno.h.
     444 *
    382445 */
    383446int task_kill(task_id_t id)
    384447{
    385         ipl_t ipl;
    386         task_t *ta;
    387 
    388448        if (id == 1)
    389449                return EPERM;
    390450       
    391         ipl = interrupts_disable();
    392         spinlock_lock(&tasks_lock);
    393         if (!(ta = task_find_by_id(id))) {
    394                 spinlock_unlock(&tasks_lock);
    395                 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);
    396456                return ENOENT;
    397457        }
    398         task_kill_internal(ta);
    399         spinlock_unlock(&tasks_lock);
    400         interrupts_restore(ipl);
    401         return 0;
     458       
     459        task_kill_internal(task);
     460        irq_spinlock_unlock(&tasks_lock, true);
     461       
     462        return EOK;
    402463}
    403464
    404465static bool task_print_walker(avltree_node_t *node, void *arg)
    405466{
    406         task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    407         int j;
    408                
    409         spinlock_lock(&t->lock);
    410                        
    411         uint64_t cycles;
    412         char suffix;
    413         order(task_get_accounting(t), &cycles, &suffix);
    414 
    415 #ifdef __32_BITS__     
    416         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64
    417             "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
    418             suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
    419 #endif
    420 
     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);
     470       
     471        uint64_t ucycles;
     472        uint64_t kcycles;
     473        char usuffix, ksuffix;
     474        task_get_accounting(task, &ucycles, &kcycles);
     475        order_suffix(ucycles, &ucycles, &usuffix);
     476        order_suffix(kcycles, &kcycles, &ksuffix);
     477       
     478#ifdef __32_BITS__
     479        if (*additional)
     480                printf("%-8" PRIu64 " %9" PRIua " %7" PRIua, 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);
     487#endif
     488       
    421489#ifdef __64_BITS__
    422         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64
    423             "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
    424             suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
    425 #endif
    426 
    427         for (j = 0; j < IPC_MAX_PHONES; j++) {
    428                 if (t->phones[j].callee)
    429                         printf(" %d:%p", j, t->phones[j].callee);
     490        if (*additional)
     491                printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c "
     492                    "%9" PRIua " %7" PRIua,
     493                    task->taskid, ucycles, usuffix, kcycles, ksuffix,
     494                    atomic_get(&task->refcount), atomic_get(&task->active_calls));
     495        else
     496                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
     497                    task->taskid, task->name, task->context, task, task->as);
     498#endif
     499       
     500        if (*additional) {
     501                size_t i;
     502                for (i = 0; i < IPC_MAX_PHONES; i++) {
     503                        if (task->phones[i].callee)
     504                                printf(" %zu:%p", i, task->phones[i].callee);
     505                }
     506                printf("\n");
    430507        }
    431         printf("\n");
    432                        
    433         spinlock_unlock(&t->lock);
     508       
     509        irq_spinlock_unlock(&task->lock, false);
    434510        return true;
    435511}
    436512
    437 /** Print task list */
    438 void task_print_list(void)
    439 {
    440         ipl_t ipl;
    441        
     513/** Print task list
     514 *
     515 * @param additional Print additional information.
     516 *
     517 */
     518void task_print_list(bool additional)
     519{
    442520        /* Messing with task structures, avoid deadlock */
    443         ipl = interrupts_disable();
    444         spinlock_lock(&tasks_lock);
    445 
    446 #ifdef __32_BITS__     
    447         printf("taskid name         ctx address    as         "
    448             "cycles     threads calls  callee\n");
    449         printf("------ ------------ --- ---------- ---------- "
    450             "---------- ------- ------ ------>\n");
    451 #endif
    452 
     521        irq_spinlock_lock(&tasks_lock, true);
     522       
     523#ifdef __32_BITS__
     524        if (additional)
     525                printf("[id    ] [threads] [calls] [callee\n");
     526        else
     527                printf("[id    ] [name        ] [ctx] [address ] [as      ]"
     528                    " [ucycles ] [kcycles ]\n");
     529#endif
     530       
    453531#ifdef __64_BITS__
    454         printf("taskid name         ctx address            as                 "
    455             "cycles     threads calls  callee\n");
    456         printf("------ ------------ --- ------------------ ------------------ "
    457             "---------- ------- ------ ------>\n");
    458 #endif
    459 
    460         avltree_walk(&tasks_tree, task_print_walker, NULL);
    461 
    462         spinlock_unlock(&tasks_lock);
    463         interrupts_restore(ipl);
     532        if (additional)
     533                printf("[id    ] [ucycles ] [kcycles ] [threads] [calls]"
     534                    " [callee\n");
     535        else
     536                printf("[id    ] [name        ] [ctx] [address         ]"
     537                    " [as              ]\n");
     538#endif
     539       
     540        avltree_walk(&tasks_tree, task_print_walker, &additional);
     541       
     542        irq_spinlock_unlock(&tasks_lock, true);
    464543}
    465544
  • kernel/generic/src/proc/the.c

    rfb150d78 r46c20c8  
    3333/**
    3434 * @file
    35  * @brief       THE structure functions.
     35 * @brief THE structure functions.
    3636 *
    3737 * This file contains functions to manage the THE structure.
     
    4444#include <arch.h>
    4545
    46 
    4746/** Initialize THE structure
    4847 *
     
    5049 *
    5150 * @param the THE structure to be initialized.
     51 *
    5252 */
    5353void the_initialize(the_t *the)
     
    6666 * @param src The source THE structure.
    6767 * @param dst The destination THE structure.
     68 *
    6869 */
    69 void the_copy(the_t *src, the_t *dst)
     70NO_TRACE void the_copy(the_t *src, the_t *dst)
    7071{
    7172        *dst = *src;
  • kernel/generic/src/proc/thread.c

    rfb150d78 r46c20c8  
    11/*
    2  * Copyright (c) 2001-2004 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3333/**
    3434 * @file
    35  * @brief       Thread management functions.
     35 * @brief Thread management functions.
    3636 */
    3737
     
    4848#include <synch/spinlock.h>
    4949#include <synch/waitq.h>
    50 #include <synch/rwlock.h>
    5150#include <cpu.h>
    52 #include <func.h>
     51#include <str.h>
    5352#include <context.h>
    5453#include <adt/avl.h>
     
    7675
    7776/** Thread states */
    78 char *thread_states[] = {
     77const char *thread_states[] = {
    7978        "Invalid",
    8079        "Running",
     
    8483        "Exiting",
    8584        "Lingering"
    86 };
     85};
     86
     87typedef struct {
     88        thread_id_t thread_id;
     89        thread_t *thread;
     90} thread_iterator_t;
    8791
    8892/** Lock protecting the threads_tree AVL tree.
    8993 *
    9094 * For locking rules, see declaration thereof.
    91  */
    92 SPINLOCK_INITIALIZE(threads_lock);
     95 *
     96 */
     97IRQ_SPINLOCK_INITIALIZE(threads_lock);
    9398
    9499/** AVL tree of all threads.
     
    96101 * When a thread is found in the threads_tree AVL tree, it is guaranteed to
    97102 * exist as long as the threads_lock is held.
    98  */
    99 avltree_t threads_tree;         
    100 
    101 SPINLOCK_INITIALIZE(tidlock);
    102 thread_id_t last_tid = 0;
     103 *
     104 */
     105avltree_t threads_tree;
     106
     107IRQ_SPINLOCK_STATIC_INITIALIZE(tidlock);
     108static thread_id_t last_tid = 0;
    103109
    104110static slab_cache_t *thread_slab;
     111
    105112#ifdef CONFIG_FPU
    106113slab_cache_t *fpu_context_slab;
     
    120127        void *arg = THREAD->thread_arg;
    121128        THREAD->last_cycle = get_cycle();
    122 
     129       
    123130        /* This is where each thread wakes up after its creation */
    124         spinlock_unlock(&THREAD->lock);
     131        irq_spinlock_unlock(&THREAD->lock, false);
    125132        interrupts_enable();
    126 
     133       
    127134        f(arg);
    128135       
    129136        /* Accumulate accounting to the task */
    130         ipl_t ipl = interrupts_disable();
    131        
    132         spinlock_lock(&THREAD->lock);
     137        irq_spinlock_lock(&THREAD->lock, true);
    133138        if (!THREAD->uncounted) {
    134                 thread_update_accounting();
    135                 uint64_t cycles = THREAD->cycles;
    136                 THREAD->cycles = 0;
    137                 spinlock_unlock(&THREAD->lock);
     139                thread_update_accounting(true);
     140                uint64_t ucycles = THREAD->ucycles;
     141                THREAD->ucycles = 0;
     142                uint64_t kcycles = THREAD->kcycles;
     143                THREAD->kcycles = 0;
    138144               
    139                 spinlock_lock(&TASK->lock);
    140                 TASK->cycles += cycles;
    141                 spinlock_unlock(&TASK->lock);
     145                irq_spinlock_pass(&THREAD->lock, &TASK->lock);
     146                TASK->ucycles += ucycles;
     147                TASK->kcycles += kcycles;
     148                irq_spinlock_unlock(&TASK->lock, true);
    142149        } else
    143                 spinlock_unlock(&THREAD->lock);
    144        
    145         interrupts_restore(ipl);
     150                irq_spinlock_unlock(&THREAD->lock, true);
    146151       
    147152        thread_exit();
    148         /* not reached */
    149 }
    150 
    151 /** Initialization and allocation for thread_t structure */
    152 static int thr_constructor(void *obj, int kmflags)
    153 {
    154         thread_t *t = (thread_t *) obj;
    155 
    156         spinlock_initialize(&t->lock, "thread_t_lock");
    157         link_initialize(&t->rq_link);
    158         link_initialize(&t->wq_link);
    159         link_initialize(&t->th_link);
    160 
     153       
     154        /* Not reached */
     155}
     156
     157/** Initialization and allocation for thread_t structure
     158 *
     159 */
     160static int thr_constructor(void *obj, unsigned int kmflags)
     161{
     162        thread_t *thread = (thread_t *) obj;
     163       
     164        irq_spinlock_initialize(&thread->lock, "thread_t_lock");
     165        link_initialize(&thread->rq_link);
     166        link_initialize(&thread->wq_link);
     167        link_initialize(&thread->th_link);
     168       
    161169        /* call the architecture-specific part of the constructor */
    162         thr_constructor_arch(t);
     170        thr_constructor_arch(thread);
    163171       
    164172#ifdef CONFIG_FPU
    165173#ifdef CONFIG_FPU_LAZY
    166         t->saved_fpu_context = NULL;
    167 #else
    168         t->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags);
    169         if (!t->saved_fpu_context)
     174        thread->saved_fpu_context = NULL;
     175#else /* CONFIG_FPU_LAZY */
     176        thread->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags);
     177        if (!thread->saved_fpu_context)
    170178                return -1;
    171 #endif
    172 #endif
    173 
    174         t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
    175         if (!t->kstack) {
     179#endif /* CONFIG_FPU_LAZY */
     180#endif /* CONFIG_FPU */
     181       
     182        thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
     183        if (!thread->kstack) {
    176184#ifdef CONFIG_FPU
    177                 if (t->saved_fpu_context)
    178                         slab_free(fpu_context_slab, t->saved_fpu_context);
     185                if (thread->saved_fpu_context)
     186                        slab_free(fpu_context_slab, thread->saved_fpu_context);
    179187#endif
    180188                return -1;
    181189        }
    182 
     190       
    183191#ifdef CONFIG_UDEBUG
    184         mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE);
    185 #endif
    186 
     192        mutex_initialize(&thread->udebug.lock, MUTEX_PASSIVE);
     193#endif
     194       
    187195        return 0;
    188196}
    189197
    190198/** Destruction of thread_t object */
    191 static int thr_destructor(void *obj)
    192 {
    193         thread_t *t = (thread_t *) obj;
    194 
     199static size_t thr_destructor(void *obj)
     200{
     201        thread_t *thread = (thread_t *) obj;
     202       
    195203        /* call the architecture-specific part of the destructor */
    196         thr_destructor_arch(t);
    197 
    198         frame_free(KA2PA(t->kstack));
     204        thr_destructor_arch(thread);
     205       
     206        frame_free(KA2PA(thread->kstack));
     207       
    199208#ifdef CONFIG_FPU
    200         if (t->saved_fpu_context)
    201                 slab_free(fpu_context_slab, t->saved_fpu_context);
    202 #endif
    203         return 1; /* One page freed */
     209        if (thread->saved_fpu_context)
     210                slab_free(fpu_context_slab, thread->saved_fpu_context);
     211#endif
     212       
     213        return 1;  /* One page freed */
    204214}
    205215
     
    212222{
    213223        THREAD = NULL;
     224       
    214225        atomic_set(&nrdy, 0);
    215226        thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0,
    216227            thr_constructor, thr_destructor, 0);
    217 
     228       
    218229#ifdef CONFIG_FPU
    219230        fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t),
    220231            FPU_CONTEXT_ALIGN, NULL, NULL, 0);
    221232#endif
    222 
     233       
    223234        avltree_create(&threads_tree);
    224235}
     
    226237/** Make thread ready
    227238 *
    228  * Switch thread t to the ready state.
     239 * Switch thread to the ready state.
    229240 *
    230241 * @param t Thread to make ready.
    231242 *
    232243 */
    233 void thread_ready(thread_t *t)
    234 {
    235         cpu_t *cpu;
    236         runq_t *r;
    237         ipl_t ipl;
    238         int i, avg;
    239 
    240         ipl = interrupts_disable();
    241 
    242         spinlock_lock(&t->lock);
    243 
    244         ASSERT(!(t->state == Ready));
    245 
    246         i = (t->priority < RQ_COUNT - 1) ? ++t->priority : t->priority;
    247        
    248         cpu = CPU;
    249         if (t->flags & THREAD_FLAG_WIRED) {
    250                 ASSERT(t->cpu != NULL);
    251                 cpu = t->cpu;
     244void thread_ready(thread_t *thread)
     245{
     246        irq_spinlock_lock(&thread->lock, true);
     247       
     248        ASSERT(!(thread->state == Ready));
     249       
     250        int i = (thread->priority < RQ_COUNT - 1)
     251            ? ++thread->priority : thread->priority;
     252       
     253        cpu_t *cpu = CPU;
     254        if (thread->flags & THREAD_FLAG_WIRED) {
     255                ASSERT(thread->cpu != NULL);
     256                cpu = thread->cpu;
    252257        }
    253         t->state = Ready;
    254         spinlock_unlock(&t->lock);
     258        thread->state = Ready;
     259       
     260        irq_spinlock_pass(&thread->lock, &(cpu->rq[i].lock));
    255261       
    256262        /*
    257          * Append t to respective ready queue on respective processor.
     263         * Append thread to respective ready queue
     264         * on respective processor.
    258265         */
    259         r = &cpu->rq[i];
    260         spinlock_lock(&r->lock);
    261         list_append(&t->rq_link, &r->rq_head);
    262         r->n++;
    263         spinlock_unlock(&r->lock);
    264 
     266       
     267        list_append(&thread->rq_link, &cpu->rq[i].rq_head);
     268        cpu->rq[i].n++;
     269        irq_spinlock_unlock(&(cpu->rq[i].lock), true);
     270       
    265271        atomic_inc(&nrdy);
    266         avg = atomic_get(&nrdy) / config.cpu_active;
     272        // FIXME: Why is the avg value not used
     273        // avg = atomic_get(&nrdy) / config.cpu_active;
    267274        atomic_inc(&cpu->nrdy);
    268 
     275}
     276
     277/** Create new thread
     278 *
     279 * Create a new thread.
     280 *
     281 * @param func      Thread's implementing function.
     282 * @param arg       Thread's implementing function argument.
     283 * @param task      Task to which the thread belongs. The caller must
     284 *                  guarantee that the task won't cease to exist during the
     285 *                  call. The task's lock may not be held.
     286 * @param flags     Thread flags.
     287 * @param name      Symbolic name (a copy is made).
     288 * @param uncounted Thread's accounting doesn't affect accumulated task
     289 *                  accounting.
     290 *
     291 * @return New thread's structure on success, NULL on failure.
     292 *
     293 */
     294thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
     295    unsigned int flags, const char *name, bool uncounted)
     296{
     297        thread_t *thread = (thread_t *) slab_alloc(thread_slab, 0);
     298        if (!thread)
     299                return NULL;
     300       
     301        /* Not needed, but good for debugging */
     302        memsetb(thread->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
     303       
     304        irq_spinlock_lock(&tidlock, true);
     305        thread->tid = ++last_tid;
     306        irq_spinlock_unlock(&tidlock, true);
     307       
     308        context_save(&thread->saved_context);
     309        context_set(&thread->saved_context, FADDR(cushion),
     310            (uintptr_t) thread->kstack, THREAD_STACK_SIZE);
     311       
     312        the_initialize((the_t *) thread->kstack);
     313       
     314        ipl_t ipl = interrupts_disable();
     315        thread->saved_context.ipl = interrupts_read();
    269316        interrupts_restore(ipl);
    270 }
    271 
    272 /** Create new thread
    273  *
    274  * Create a new thread.
    275  *
    276  * @param func          Thread's implementing function.
    277  * @param arg           Thread's implementing function argument.
    278  * @param task          Task to which the thread belongs. The caller must
    279  *                      guarantee that the task won't cease to exist during the
    280  *                      call. The task's lock may not be held.
    281  * @param flags         Thread flags.
    282  * @param name          Symbolic name (a copy is made).
    283  * @param uncounted     Thread's accounting doesn't affect accumulated task
    284  *                      accounting.
    285  *
    286  * @return              New thread's structure on success, NULL on failure.
    287  *
    288  */
    289 thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
    290     int flags, char *name, bool uncounted)
    291 {
    292         thread_t *t;
    293         ipl_t ipl;
    294        
    295         t = (thread_t *) slab_alloc(thread_slab, 0);
    296         if (!t)
    297                 return NULL;
    298        
    299         /* Not needed, but good for debugging */
    300         memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
    301        
    302         ipl = interrupts_disable();
    303         spinlock_lock(&tidlock);
    304         t->tid = ++last_tid;
    305         spinlock_unlock(&tidlock);
    306         interrupts_restore(ipl);
    307        
    308         context_save(&t->saved_context);
    309         context_set(&t->saved_context, FADDR(cushion), (uintptr_t) t->kstack,
    310             THREAD_STACK_SIZE);
    311        
    312         the_initialize((the_t *) t->kstack);
    313        
    314         ipl = interrupts_disable();
    315         t->saved_context.ipl = interrupts_read();
    316         interrupts_restore(ipl);
    317        
    318         memcpy(t->name, name, THREAD_NAME_BUFLEN);
    319         t->name[THREAD_NAME_BUFLEN - 1] = 0;
    320        
    321         t->thread_code = func;
    322         t->thread_arg = arg;
    323         t->ticks = -1;
    324         t->cycles = 0;
    325         t->uncounted = uncounted;
    326         t->priority = -1;               /* start in rq[0] */
    327         t->cpu = NULL;
    328         t->flags = flags;
    329         t->state = Entering;
    330         t->call_me = NULL;
    331         t->call_me_with = NULL;
    332        
    333         timeout_initialize(&t->sleep_timeout);
    334         t->sleep_interruptible = false;
    335         t->sleep_queue = NULL;
    336         t->timeout_pending = 0;
    337 
    338         t->in_copy_from_uspace = false;
    339         t->in_copy_to_uspace = false;
    340 
    341         t->interrupted = false;
    342         t->detached = false;
    343         waitq_initialize(&t->join_wq);
    344        
    345         t->rwlock_holder_type = RWLOCK_NONE;
    346                
    347         t->task = task;
    348        
    349         t->fpu_context_exists = 0;
    350         t->fpu_context_engaged = 0;
    351 
    352         avltree_node_initialize(&t->threads_tree_node);
    353         t->threads_tree_node.key = (uintptr_t) t;
    354 
     317       
     318        str_cpy(thread->name, THREAD_NAME_BUFLEN, name);
     319       
     320        thread->thread_code = func;
     321        thread->thread_arg = arg;
     322        thread->ticks = -1;
     323        thread->ucycles = 0;
     324        thread->kcycles = 0;
     325        thread->uncounted = uncounted;
     326        thread->priority = -1;          /* Start in rq[0] */
     327        thread->cpu = NULL;
     328        thread->flags = flags;
     329        thread->state = Entering;
     330       
     331        timeout_initialize(&thread->sleep_timeout);
     332        thread->sleep_interruptible = false;
     333        thread->sleep_queue = NULL;
     334        thread->timeout_pending = false;
     335       
     336        thread->in_copy_from_uspace = false;
     337        thread->in_copy_to_uspace = false;
     338       
     339        thread->interrupted = false;
     340        thread->detached = false;
     341        waitq_initialize(&thread->join_wq);
     342       
     343        thread->task = task;
     344       
     345        thread->fpu_context_exists = 0;
     346        thread->fpu_context_engaged = 0;
     347       
     348        avltree_node_initialize(&thread->threads_tree_node);
     349        thread->threads_tree_node.key = (uintptr_t) thread;
     350       
    355351#ifdef CONFIG_UDEBUG
    356352        /* Init debugging stuff */
    357         udebug_thread_initialize(&t->udebug);
    358 #endif
    359 
    360         /* might depend on previous initialization */
    361         thread_create_arch(t); 
    362 
     353        udebug_thread_initialize(&thread->udebug);
     354#endif
     355       
     356        /* Might depend on previous initialization */
     357        thread_create_arch(thread);
     358       
    363359        if (!(flags & THREAD_FLAG_NOATTACH))
    364                 thread_attach(t, task);
    365 
    366         return t;
     360                thread_attach(thread, task);
     361       
     362        return thread;
    367363}
    368364
     
    371367 * Detach thread from all queues, cpus etc. and destroy it.
    372368 *
    373  * Assume thread->lock is held!!
    374  */
    375 void thread_destroy(thread_t *t)
    376 {
    377         ASSERT(t->state == Exiting || t->state == Lingering);
    378         ASSERT(t->task);
    379         ASSERT(t->cpu);
    380 
    381         spinlock_lock(&t->cpu->lock);
    382         if (t->cpu->fpu_owner == t)
    383                 t->cpu->fpu_owner = NULL;
    384         spinlock_unlock(&t->cpu->lock);
    385 
    386         spinlock_unlock(&t->lock);
    387 
    388         spinlock_lock(&threads_lock);
    389         avltree_delete(&threads_tree, &t->threads_tree_node);
    390         spinlock_unlock(&threads_lock);
    391 
     369 * @param thread  Thread to be destroyed.
     370 * @param irq_res Indicate whether it should unlock thread->lock
     371 *                in interrupts-restore mode.
     372 *
     373 */
     374void thread_destroy(thread_t *thread, bool irq_res)
     375{
     376        ASSERT(irq_spinlock_locked(&thread->lock));
     377        ASSERT((thread->state == Exiting) || (thread->state == Lingering));
     378        ASSERT(thread->task);
     379        ASSERT(thread->cpu);
     380       
     381        irq_spinlock_lock(&thread->cpu->lock, false);
     382        if (thread->cpu->fpu_owner == thread)
     383                thread->cpu->fpu_owner = NULL;
     384        irq_spinlock_unlock(&thread->cpu->lock, false);
     385       
     386        irq_spinlock_pass(&thread->lock, &threads_lock);
     387       
     388        avltree_delete(&threads_tree, &thread->threads_tree_node);
     389       
     390        irq_spinlock_pass(&threads_lock, &thread->task->lock);
     391       
    392392        /*
    393393         * Detach from the containing task.
    394394         */
    395         spinlock_lock(&t->task->lock);
    396         list_remove(&t->th_link);
    397         spinlock_unlock(&t->task->lock);       
    398 
     395        list_remove(&thread->th_link);
     396        irq_spinlock_unlock(&thread->task->lock, irq_res);
     397       
    399398        /*
    400          * t is guaranteed to be the very last thread of its task.
    401          * It is safe to destroy the task.
     399         * Drop the reference to the containing task.
    402400         */
    403         if (atomic_predec(&t->task->refcount) == 0)
    404                 task_destroy(t->task);
    405        
    406         slab_free(thread_slab, t);
     401        task_release(thread->task);
     402        slab_free(thread_slab, thread);
    407403}
    408404
     
    412408 * threads_tree.
    413409 *
    414  * @param t     Thread to be attached to the task.
    415  * @param task  Task to which the thread is to be attached.
    416  */
    417 void thread_attach(thread_t *t, task_t *task)
    418 {
    419         ipl_t ipl;
    420 
     410 * @param t    Thread to be attached to the task.
     411 * @param task Task to which the thread is to be attached.
     412 *
     413 */
     414void thread_attach(thread_t *thread, task_t *task)
     415{
    421416        /*
    422417         * Attach to the specified task.
    423418         */
    424         ipl = interrupts_disable();
    425         spinlock_lock(&task->lock);
    426 
    427         atomic_inc(&task->refcount);
    428 
     419        irq_spinlock_lock(&task->lock, true);
     420       
     421        /* Hold a reference to the task. */
     422        task_hold(task);
     423       
    429424        /* Must not count kbox thread into lifecount */
    430         if (t->flags & THREAD_FLAG_USPACE)
     425        if (thread->flags & THREAD_FLAG_USPACE)
    431426                atomic_inc(&task->lifecount);
    432 
    433         list_append(&t->th_link, &task->th_head);
    434         spinlock_unlock(&task->lock);
    435 
     427       
     428        list_append(&thread->th_link, &task->th_head);
     429       
     430        irq_spinlock_pass(&task->lock, &threads_lock);
     431       
    436432        /*
    437433         * Register this thread in the system-wide list.
    438434         */
    439         spinlock_lock(&threads_lock);
    440         avltree_insert(&threads_tree, &t->threads_tree_node);
    441         spinlock_unlock(&threads_lock);
    442        
    443         interrupts_restore(ipl);
     435        avltree_insert(&threads_tree, &thread->threads_tree_node);
     436        irq_spinlock_unlock(&threads_lock, true);
    444437}
    445438
    446439/** Terminate thread.
    447440 *
    448  * End current thread execution and switch it to the exiting state. All pending
    449  * timeouts are executed.
     441 * End current thread execution and switch it to the exiting state.
     442 * All pending timeouts are executed.
     443 *
    450444 */
    451445void thread_exit(void)
    452446{
    453         ipl_t ipl;
    454 
    455447        if (THREAD->flags & THREAD_FLAG_USPACE) {
    456448#ifdef CONFIG_UDEBUG
    457449                /* Generate udebug THREAD_E event */
    458450                udebug_thread_e_event();
     451
     452                /*
     453                 * This thread will not execute any code or system calls from
     454                 * now on.
     455                 */
     456                udebug_stoppable_begin();
    459457#endif
    460458                if (atomic_predec(&TASK->lifecount) == 0) {
     
    465463                         * can only be created by threads of the same task.
    466464                         * We are safe to perform cleanup.
     465                         *
    467466                         */
    468467                        ipc_cleanup();
     
    471470                }
    472471        }
    473 
     472       
    474473restart:
    475         ipl = interrupts_disable();
    476         spinlock_lock(&THREAD->lock);
    477         if (THREAD->timeout_pending) {
    478                 /* busy waiting for timeouts in progress */
    479                 spinlock_unlock(&THREAD->lock);
    480                 interrupts_restore(ipl);
     474        irq_spinlock_lock(&THREAD->lock, true);
     475        if (THREAD->timeout_pending) {
     476                /* Busy waiting for timeouts in progress */
     477                irq_spinlock_unlock(&THREAD->lock, true);
    481478                goto restart;
    482479        }
    483480       
    484481        THREAD->state = Exiting;
    485         spinlock_unlock(&THREAD->lock);
     482        irq_spinlock_unlock(&THREAD->lock, true);
     483       
    486484        scheduler();
    487 
     485       
    488486        /* Not reached */
    489         while (1)
    490                 ;
    491 }
    492 
     487        while (true);
     488}
    493489
    494490/** Thread sleep
     
    505501        while (sec > 0) {
    506502                uint32_t period = (sec > 1000) ? 1000 : sec;
    507        
     503               
    508504                thread_usleep(period * 1000000);
    509505                sec -= period;
     
    513509/** Wait for another thread to exit.
    514510 *
    515  * @param t Thread to join on exit.
    516  * @param usec Timeout in microseconds.
    517  * @param flags Mode of operation.
     511 * @param thread Thread to join on exit.
     512 * @param usec   Timeout in microseconds.
     513 * @param flags  Mode of operation.
    518514 *
    519515 * @return An error code from errno.h or an error code from synch.h.
    520  */
    521 int thread_join_timeout(thread_t *t, uint32_t usec, int flags)
    522 {
    523         ipl_t ipl;
    524         int rc;
    525 
    526         if (t == THREAD)
     516 *
     517 */
     518int thread_join_timeout(thread_t *thread, uint32_t usec, unsigned int flags)
     519{
     520        if (thread == THREAD)
    527521                return EINVAL;
    528 
     522       
    529523        /*
    530524         * Since thread join can only be called once on an undetached thread,
     
    532526         */
    533527       
    534         ipl = interrupts_disable();
    535         spinlock_lock(&t->lock);
    536         ASSERT(!t->detached);
    537         spinlock_unlock(&t->lock);
    538         interrupts_restore(ipl);
    539        
    540         rc = waitq_sleep_timeout(&t->join_wq, usec, flags);
    541        
    542         return rc;     
     528        irq_spinlock_lock(&thread->lock, true);
     529        ASSERT(!thread->detached);
     530        irq_spinlock_unlock(&thread->lock, true);
     531       
     532        return waitq_sleep_timeout(&thread->join_wq, usec, flags);
    543533}
    544534
     
    548538 * state, deallocate its resources.
    549539 *
    550  * @param t Thread to be detached.
    551  */
    552 void thread_detach(thread_t *t)
    553 {
    554         ipl_t ipl;
    555 
     540 * @param thread Thread to be detached.
     541 *
     542 */
     543void thread_detach(thread_t *thread)
     544{
    556545        /*
    557546         * Since the thread is expected not to be already detached,
    558547         * pointer to it must be still valid.
    559548         */
    560         ipl = interrupts_disable();
    561         spinlock_lock(&t->lock);
    562         ASSERT(!t->detached);
    563         if (t->state == Lingering) {
    564                 thread_destroy(t);      /* unlocks &t->lock */
    565                 interrupts_restore(ipl);
     549        irq_spinlock_lock(&thread->lock, true);
     550        ASSERT(!thread->detached);
     551       
     552        if (thread->state == Lingering) {
     553                /*
     554                 * Unlock &thread->lock and restore
     555                 * interrupts in thread_destroy().
     556                 */
     557                thread_destroy(thread, true);
    566558                return;
    567559        } else {
    568                 t->detached = true;
     560                thread->detached = true;
    569561        }
    570         spinlock_unlock(&t->lock);
    571         interrupts_restore(ipl);
     562       
     563        irq_spinlock_unlock(&thread->lock, true);
    572564}
    573565
     
    588580}
    589581
    590 /** Register thread out-of-context invocation
    591  *
    592  * Register a function and its argument to be executed
    593  * on next context switch to the current thread.
    594  *
    595  * @param call_me      Out-of-context function.
    596  * @param call_me_with Out-of-context function argument.
    597  *
    598  */
    599 void thread_register_call_me(void (* call_me)(void *), void *call_me_with)
    600 {
    601         ipl_t ipl;
    602        
    603         ipl = interrupts_disable();
    604         spinlock_lock(&THREAD->lock);
    605         THREAD->call_me = call_me;
    606         THREAD->call_me_with = call_me_with;
    607         spinlock_unlock(&THREAD->lock);
    608         interrupts_restore(ipl);
    609 }
    610 
    611582static bool thread_walker(avltree_node_t *node, void *arg)
    612583{
    613         thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
    614        
    615         uint64_t cycles;
    616         char suffix;
    617         order(t->cycles, &cycles, &suffix);
    618 
     584        bool *additional = (bool *) arg;
     585        thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node);
     586       
     587        uint64_t ucycles, kcycles;
     588        char usuffix, ksuffix;
     589        order_suffix(thread->ucycles, &ucycles, &usuffix);
     590        order_suffix(thread->kcycles, &kcycles, &ksuffix);
     591       
    619592#ifdef __32_BITS__
    620         printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ",
    621             t->tid, t->name, t, thread_states[t->state], t->task,
    622         t->task->context, t->thread_code, t->kstack, cycles, suffix);
    623 #endif
    624 
     593        if (*additional)
     594                printf("%-8" PRIu64" %10p %9" PRIu64 "%c %9" PRIu64 "%c ",
     595                    thread->tid, thread->kstack, ucycles, usuffix,
     596                    kcycles, ksuffix);
     597        else
     598                printf("%-8" PRIu64" %-14s %10p %-8s %10p %-5" PRIu32 " %10p\n",
     599                    thread->tid, thread->name, thread, thread_states[thread->state],
     600                    thread->task, thread->task->context, thread->thread_code);
     601#endif
     602       
    625603#ifdef __64_BITS__
    626         printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ",
    627             t->tid, t->name, t, thread_states[t->state], t->task,
    628         t->task->context, t->thread_code, t->kstack, cycles, suffix);
     604        if (*additional)
     605                printf("%-8" PRIu64" %18p %18p\n"
     606                    "         %9" PRIu64 "%c %9" PRIu64 "%c ",
     607                    thread->tid, thread->thread_code, thread->kstack,
     608                    ucycles, usuffix, kcycles, ksuffix);
     609        else
     610                printf("%-8" PRIu64" %-14s %18p %-8s %18p %-5" PRIu32 "\n",
     611                    thread->tid, thread->name, thread, thread_states[thread->state],
     612                    thread->task, thread->task->context);
     613#endif
     614       
     615        if (*additional) {
     616                if (thread->cpu)
     617                        printf("%-5u", thread->cpu->id);
     618                else
     619                        printf("none ");
     620               
     621                if (thread->state == Sleeping) {
     622#ifdef __32_BITS__
     623                        printf(" %10p", thread->sleep_queue);
    629624#endif
    630625                       
    631         if (t->cpu)
    632                 printf("%-4u", t->cpu->id);
     626#ifdef __64_BITS__
     627                        printf(" %18p", thread->sleep_queue);
     628#endif
     629                }
     630               
     631                printf("\n");
     632        }
     633       
     634        return true;
     635}
     636
     637/** Print list of threads debug info
     638 *
     639 * @param additional Print additional information.
     640 *
     641 */
     642void thread_print_list(bool additional)
     643{
     644        /* Messing with thread structures, avoid deadlock */
     645        irq_spinlock_lock(&threads_lock, true);
     646       
     647#ifdef __32_BITS__
     648        if (additional)
     649                printf("[id    ] [stack   ] [ucycles ] [kcycles ] [cpu]"
     650                    " [waitqueue]\n");
    633651        else
    634                 printf("none");
    635                        
    636         if (t->state == Sleeping) {
    637 #ifdef __32_BITS__
    638                 printf(" %10p", t->sleep_queue);
    639 #endif
    640 
     652                printf("[id    ] [name        ] [address ] [state ] [task    ]"
     653                    " [ctx] [code    ]\n");
     654#endif
     655       
    641656#ifdef __64_BITS__
    642                 printf(" %18p", t->sleep_queue);
    643 #endif
    644         }
    645                        
    646         printf("\n");
    647 
    648         return true;
    649 }
    650 
    651 /** Print list of threads debug info */
    652 void thread_print_list(void)
    653 {
    654         ipl_t ipl;
    655        
    656         /* Messing with thread structures, avoid deadlock */
    657         ipl = interrupts_disable();
    658         spinlock_lock(&threads_lock);
    659 
    660 #ifdef __32_BITS__     
    661         printf("tid    name       address    state    task       "
    662                 "ctx code       stack      cycles     cpu  "
    663                 "waitqueue\n");
    664         printf("------ ---------- ---------- -------- ---------- "
    665                 "--- ---------- ---------- ---------- ---- "
    666                 "----------\n");
    667 #endif
    668 
    669 #ifdef __64_BITS__
    670         printf("tid    name       address            state    task               "
    671                 "ctx code               stack              cycles     cpu  "
    672                 "waitqueue\n");
    673         printf("------ ---------- ------------------ -------- ------------------ "
    674                 "--- ------------------ ------------------ ---------- ---- "
    675                 "------------------\n");
    676 #endif
    677 
    678         avltree_walk(&threads_tree, thread_walker, NULL);
    679 
    680         spinlock_unlock(&threads_lock);
    681         interrupts_restore(ipl);
     657        if (additional) {
     658                printf("[id    ] [code            ] [stack           ]\n"
     659                    "         [ucycles ] [kcycles ] [cpu] [waitqueue       ]\n");
     660        } else
     661                printf("[id    ] [name        ] [address         ] [state ]"
     662                    " [task            ] [ctx]\n");
     663#endif
     664       
     665        avltree_walk(&threads_tree, thread_walker, &additional);
     666       
     667        irq_spinlock_unlock(&threads_lock, true);
    682668}
    683669
     
    687673 * interrupts must be already disabled.
    688674 *
    689  * @param t Pointer to thread.
     675 * @param thread Pointer to thread.
    690676 *
    691677 * @return True if thread t is known to the system, false otherwise.
    692  */
    693 bool thread_exists(thread_t *t)
    694 {
    695         avltree_node_t *node;
    696 
    697         node = avltree_search(&threads_tree, (avltree_key_t) ((uintptr_t) t));
     678 *
     679 */
     680bool thread_exists(thread_t *thread)
     681{
     682        ASSERT(interrupts_disabled());
     683        ASSERT(irq_spinlock_locked(&threads_lock));
     684
     685        avltree_node_t *node =
     686            avltree_search(&threads_tree, (avltree_key_t) ((uintptr_t) thread));
    698687       
    699688        return node != NULL;
     
    705694 * interrupts must be already disabled.
    706695 *
    707  */
    708 void thread_update_accounting(void)
     696 * @param user True to update user accounting, false for kernel.
     697 *
     698 */
     699void thread_update_accounting(bool user)
    709700{
    710701        uint64_t time = get_cycle();
    711         THREAD->cycles += time - THREAD->last_cycle;
     702
     703        ASSERT(interrupts_disabled());
     704        ASSERT(irq_spinlock_locked(&THREAD->lock));
     705       
     706        if (user)
     707                THREAD->ucycles += time - THREAD->last_cycle;
     708        else
     709                THREAD->kcycles += time - THREAD->last_cycle;
     710       
    712711        THREAD->last_cycle = time;
    713712}
     713
     714static bool thread_search_walker(avltree_node_t *node, void *arg)
     715{
     716        thread_t *thread =
     717            (thread_t *) avltree_get_instance(node, thread_t, threads_tree_node);
     718        thread_iterator_t *iterator = (thread_iterator_t *) arg;
     719       
     720        if (thread->tid == iterator->thread_id) {
     721                iterator->thread = thread;
     722                return false;
     723        }
     724       
     725        return true;
     726}
     727
     728/** Find thread structure corresponding to thread ID.
     729 *
     730 * The threads_lock must be already held by the caller of this function and
     731 * interrupts must be disabled.
     732 *
     733 * @param id Thread ID.
     734 *
     735 * @return Thread structure address or NULL if there is no such thread ID.
     736 *
     737 */
     738thread_t *thread_find_by_id(thread_id_t thread_id)
     739{
     740        ASSERT(interrupts_disabled());
     741        ASSERT(irq_spinlock_locked(&threads_lock));
     742
     743        thread_iterator_t iterator;
     744       
     745        iterator.thread_id = thread_id;
     746        iterator.thread = NULL;
     747       
     748        avltree_walk(&threads_tree, thread_search_walker, (void *) &iterator);
     749       
     750        return iterator.thread;
     751}
     752
    714753
    715754/** Process syscall to create new thread.
     
    719758    size_t name_len, thread_id_t *uspace_thread_id)
    720759{
    721         thread_t *t;
    722         char namebuf[THREAD_NAME_BUFLEN];
    723         uspace_arg_t *kernel_uarg;
    724         int rc;
    725 
    726760        if (name_len > THREAD_NAME_BUFLEN - 1)
    727761                name_len = THREAD_NAME_BUFLEN - 1;
    728 
    729         rc = copy_from_uspace(namebuf, uspace_name, name_len);
     762       
     763        char namebuf[THREAD_NAME_BUFLEN];
     764        int rc = copy_from_uspace(namebuf, uspace_name, name_len);
    730765        if (rc != 0)
    731766                return (unative_t) rc;
    732 
     767       
    733768        namebuf[name_len] = 0;
    734 
     769       
    735770        /*
    736771         * In case of failure, kernel_uarg will be deallocated in this function.
    737772         * In case of success, kernel_uarg will be freed in uinit().
     773         *
    738774         */
    739         kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
     775        uspace_arg_t *kernel_uarg =
     776            (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
    740777       
    741778        rc = copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t));
     
    744781                return (unative_t) rc;
    745782        }
    746 
    747         t = thread_create(uinit, kernel_uarg, TASK,
     783       
     784        thread_t *thread = thread_create(uinit, kernel_uarg, TASK,
    748785            THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf, false);
    749         if (t) {
     786        if (thread) {
    750787                if (uspace_thread_id != NULL) {
    751                         int rc;
    752 
    753                         rc = copy_to_uspace(uspace_thread_id, &t->tid,
    754                             sizeof(t->tid));
     788                        rc = copy_to_uspace(uspace_thread_id, &thread->tid,
     789                            sizeof(thread->tid));
    755790                        if (rc != 0) {
    756791                                /*
     
    758793                                 * has already been created. We need to undo its
    759794                                 * creation now.
     795                                 *
    760796                                 */
    761 
     797                               
    762798                                /*
    763799                                 * The new thread structure is initialized, but
     
    765801                                 * We can safely deallocate it.
    766802                                 */
    767                                 slab_free(thread_slab, t);
    768                                 free(kernel_uarg);
    769 
     803                                slab_free(thread_slab, thread);
     804                                free(kernel_uarg);
     805                               
    770806                                return (unative_t) rc;
    771807                         }
    772808                }
     809               
    773810#ifdef CONFIG_UDEBUG
    774811                /*
     
    778815                 * THREAD_B events for threads that already existed
    779816                 * and could be detected with THREAD_READ before.
     817                 *
    780818                 */
    781                 udebug_thread_b_event_attach(t, TASK);
     819                udebug_thread_b_event_attach(thread, TASK);
    782820#else
    783                 thread_attach(t, TASK);
    784 #endif
    785                 thread_ready(t);
    786 
     821                thread_attach(thread, TASK);
     822#endif
     823                thread_ready(thread);
     824               
    787825                return 0;
    788826        } else
    789827                free(kernel_uarg);
    790 
     828       
    791829        return (unative_t) ENOMEM;
    792830}
     
    798836{
    799837        thread_exit();
     838       
    800839        /* Unreachable */
    801840        return 0;
     
    808847 *
    809848 * @return 0 on success or an error code from @ref errno.h.
     849 *
    810850 */
    811851unative_t sys_thread_get_id(thread_id_t *uspace_thread_id)
     
    814854         * No need to acquire lock on THREAD because tid
    815855         * remains constant for the lifespan of the thread.
     856         *
    816857         */
    817858        return (unative_t) copy_to_uspace(uspace_thread_id, &THREAD->tid,
Note: See TracChangeset for help on using the changeset viewer.