Ignore:
File:
1 edited

Legend:

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

    ree42e43 r7ed8530  
    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>
    5051#include <cpu.h>
    5152#include <str.h>
     
    9394 *
    9495 * For locking rules, see declaration thereof.
    95  *
    96  */
    97 IRQ_SPINLOCK_INITIALIZE(threads_lock);
     96 */
     97SPINLOCK_INITIALIZE(threads_lock);
    9898
    9999/** AVL tree of all threads.
     
    101101 * When a thread is found in the threads_tree AVL tree, it is guaranteed to
    102102 * exist as long as the threads_lock is held.
    103  *
    104  */
    105 avltree_t threads_tree;
    106 
    107 IRQ_SPINLOCK_STATIC_INITIALIZE(tidlock);
    108 static thread_id_t last_tid = 0;
     103 */
     104avltree_t threads_tree;         
     105
     106SPINLOCK_INITIALIZE(tidlock);
     107thread_id_t last_tid = 0;
    109108
    110109static slab_cache_t *thread_slab;
    111 
    112110#ifdef CONFIG_FPU
    113111slab_cache_t *fpu_context_slab;
     
    127125        void *arg = THREAD->thread_arg;
    128126        THREAD->last_cycle = get_cycle();
    129        
     127
    130128        /* This is where each thread wakes up after its creation */
    131         irq_spinlock_unlock(&THREAD->lock, false);
     129        spinlock_unlock(&THREAD->lock);
    132130        interrupts_enable();
    133        
     131
    134132        f(arg);
    135133       
    136134        /* Accumulate accounting to the task */
    137         irq_spinlock_lock(&THREAD->lock, true);
     135        ipl_t ipl = interrupts_disable();
     136       
     137        spinlock_lock(&THREAD->lock);
    138138        if (!THREAD->uncounted) {
    139139                thread_update_accounting(true);
     
    142142                uint64_t kcycles = THREAD->kcycles;
    143143                THREAD->kcycles = 0;
     144
     145                spinlock_unlock(&THREAD->lock);
    144146               
    145                 irq_spinlock_pass(&THREAD->lock, &TASK->lock);
     147                spinlock_lock(&TASK->lock);
    146148                TASK->ucycles += ucycles;
    147149                TASK->kcycles += kcycles;
    148                 irq_spinlock_unlock(&TASK->lock, true);
     150                spinlock_unlock(&TASK->lock);
    149151        } else
    150                 irq_spinlock_unlock(&THREAD->lock, true);
     152                spinlock_unlock(&THREAD->lock);
     153       
     154        interrupts_restore(ipl);
    151155       
    152156        thread_exit();
    153        
    154         /* Not reached */
    155 }
    156 
    157 /** Initialization and allocation for thread_t structure
    158  *
    159  */
    160 static 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        
     157        /* not reached */
     158}
     159
     160/** Initialization and allocation for thread_t structure */
     161static int thr_constructor(void *obj, int kmflags)
     162{
     163        thread_t *t = (thread_t *) obj;
     164
     165        spinlock_initialize(&t->lock, "thread_t_lock");
     166        link_initialize(&t->rq_link);
     167        link_initialize(&t->wq_link);
     168        link_initialize(&t->th_link);
     169
    169170        /* call the architecture-specific part of the constructor */
    170         thr_constructor_arch(thread);
     171        thr_constructor_arch(t);
    171172       
    172173#ifdef CONFIG_FPU
    173174#ifdef CONFIG_FPU_LAZY
    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)
     175        t->saved_fpu_context = NULL;
     176#else
     177        t->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags);
     178        if (!t->saved_fpu_context)
    178179                return -1;
    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) {
     180#endif
     181#endif
     182
     183        t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
     184        if (!t->kstack) {
    184185#ifdef CONFIG_FPU
    185                 if (thread->saved_fpu_context)
    186                         slab_free(fpu_context_slab, thread->saved_fpu_context);
     186                if (t->saved_fpu_context)
     187                        slab_free(fpu_context_slab, t->saved_fpu_context);
    187188#endif
    188189                return -1;
    189190        }
    190        
     191
    191192#ifdef CONFIG_UDEBUG
    192         mutex_initialize(&thread->udebug.lock, MUTEX_PASSIVE);
    193 #endif
    194        
     193        mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE);
     194#endif
     195
    195196        return 0;
    196197}
    197198
    198199/** Destruction of thread_t object */
    199 static size_t thr_destructor(void *obj)
    200 {
    201         thread_t *thread = (thread_t *) obj;
    202        
     200static int thr_destructor(void *obj)
     201{
     202        thread_t *t = (thread_t *) obj;
     203
    203204        /* call the architecture-specific part of the destructor */
    204         thr_destructor_arch(thread);
    205        
    206         frame_free(KA2PA(thread->kstack));
    207        
     205        thr_destructor_arch(t);
     206
     207        frame_free(KA2PA(t->kstack));
    208208#ifdef CONFIG_FPU
    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 */
     209        if (t->saved_fpu_context)
     210                slab_free(fpu_context_slab, t->saved_fpu_context);
     211#endif
     212        return 1; /* One page freed */
    214213}
    215214
     
    222221{
    223222        THREAD = NULL;
    224        
    225223        atomic_set(&nrdy, 0);
    226224        thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0,
    227225            thr_constructor, thr_destructor, 0);
    228        
     226
    229227#ifdef CONFIG_FPU
    230228        fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t),
    231229            FPU_CONTEXT_ALIGN, NULL, NULL, 0);
    232230#endif
    233        
     231
    234232        avltree_create(&threads_tree);
    235233}
     
    237235/** Make thread ready
    238236 *
    239  * Switch thread to the ready state.
     237 * Switch thread t to the ready state.
    240238 *
    241239 * @param t Thread to make ready.
    242240 *
    243241 */
    244 void 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;
    257         }
    258         thread->state = Ready;
    259        
    260         irq_spinlock_pass(&thread->lock, &(cpu->rq[i].lock));
     242void thread_ready(thread_t *t)
     243{
     244        cpu_t *cpu;
     245        runq_t *r;
     246        ipl_t ipl;
     247        int i, avg;
     248
     249        ipl = interrupts_disable();
     250
     251        spinlock_lock(&t->lock);
     252
     253        ASSERT(!(t->state == Ready));
     254
     255        i = (t->priority < RQ_COUNT - 1) ? ++t->priority : t->priority;
     256       
     257        cpu = CPU;
     258        if (t->flags & THREAD_FLAG_WIRED) {
     259                ASSERT(t->cpu != NULL);
     260                cpu = t->cpu;
     261        }
     262        t->state = Ready;
     263        spinlock_unlock(&t->lock);
    261264       
    262265        /*
    263          * Append thread to respective ready queue
    264          * on respective processor.
     266         * Append t to respective ready queue on respective processor.
    265267         */
    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        
     268        r = &cpu->rq[i];
     269        spinlock_lock(&r->lock);
     270        list_append(&t->rq_link, &r->rq_head);
     271        r->n++;
     272        spinlock_unlock(&r->lock);
     273
    271274        atomic_inc(&nrdy);
    272         // FIXME: Why is the avg value not used
    273         // avg = atomic_get(&nrdy) / config.cpu_active;
     275        // FIXME: Why is the avg value never read?
     276        avg = atomic_get(&nrdy) / config.cpu_active;
    274277        atomic_inc(&cpu->nrdy);
     278
     279        interrupts_restore(ipl);
    275280}
    276281
     
    279284 * Create a new thread.
    280285 *
    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.
     286 * @param func          Thread's implementing function.
     287 * @param arg           Thread's implementing function argument.
     288 * @param task          Task to which the thread belongs. The caller must
     289 *                      guarantee that the task won't cease to exist during the
     290 *                      call. The task's lock may not be held.
     291 * @param flags         Thread flags.
     292 * @param name          Symbolic name (a copy is made).
     293 * @param uncounted     Thread's accounting doesn't affect accumulated task
     294 *                      accounting.
     295 *
     296 * @return              New thread's structure on success, NULL on failure.
    292297 *
    293298 */
    294299thread_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)
     300    int flags, const char *name, bool uncounted)
     301{
     302        thread_t *t;
     303        ipl_t ipl;
     304       
     305        t = (thread_t *) slab_alloc(thread_slab, 0);
     306        if (!t)
    299307                return NULL;
    300308       
    301309        /* 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();
     310        memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
     311       
     312        ipl = interrupts_disable();
     313        spinlock_lock(&tidlock);
     314        t->tid = ++last_tid;
     315        spinlock_unlock(&tidlock);
    316316        interrupts_restore(ipl);
    317317       
    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        
     318        context_save(&t->saved_context);
     319        context_set(&t->saved_context, FADDR(cushion), (uintptr_t) t->kstack,
     320            THREAD_STACK_SIZE);
     321       
     322        the_initialize((the_t *) t->kstack);
     323       
     324        ipl = interrupts_disable();
     325        t->saved_context.ipl = interrupts_read();
     326        interrupts_restore(ipl);
     327       
     328        memcpy(t->name, name, THREAD_NAME_BUFLEN);
     329        t->name[THREAD_NAME_BUFLEN - 1] = 0;
     330       
     331        t->thread_code = func;
     332        t->thread_arg = arg;
     333        t->ticks = -1;
     334        t->ucycles = 0;
     335        t->kcycles = 0;
     336        t->uncounted = uncounted;
     337        t->priority = -1;               /* start in rq[0] */
     338        t->cpu = NULL;
     339        t->flags = flags;
     340        t->state = Entering;
     341        t->call_me = NULL;
     342        t->call_me_with = NULL;
     343       
     344        timeout_initialize(&t->sleep_timeout);
     345        t->sleep_interruptible = false;
     346        t->sleep_queue = NULL;
     347        t->timeout_pending = 0;
     348
     349        t->in_copy_from_uspace = false;
     350        t->in_copy_to_uspace = false;
     351
     352        t->interrupted = false;
     353        t->detached = false;
     354        waitq_initialize(&t->join_wq);
     355       
     356        t->rwlock_holder_type = RWLOCK_NONE;
     357               
     358        t->task = task;
     359       
     360        t->fpu_context_exists = 0;
     361        t->fpu_context_engaged = 0;
     362
     363        avltree_node_initialize(&t->threads_tree_node);
     364        t->threads_tree_node.key = (uintptr_t) t;
     365
    351366#ifdef CONFIG_UDEBUG
    352367        /* Init debugging stuff */
    353         udebug_thread_initialize(&thread->udebug);
    354 #endif
    355        
    356         /* Might depend on previous initialization */
    357         thread_create_arch(thread);
    358        
     368        udebug_thread_initialize(&t->udebug);
     369#endif
     370
     371        /* might depend on previous initialization */
     372        thread_create_arch(t); 
     373
    359374        if (!(flags & THREAD_FLAG_NOATTACH))
    360                 thread_attach(thread, task);
    361        
    362         return thread;
     375                thread_attach(t, task);
     376
     377        return t;
    363378}
    364379
     
    367382 * Detach thread from all queues, cpus etc. and destroy it.
    368383 *
    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  */
    374 void 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        
     384 * Assume thread->lock is held!!
     385 */
     386void thread_destroy(thread_t *t)
     387{
     388        ASSERT(t->state == Exiting || t->state == Lingering);
     389        ASSERT(t->task);
     390        ASSERT(t->cpu);
     391
     392        spinlock_lock(&t->cpu->lock);
     393        if (t->cpu->fpu_owner == t)
     394                t->cpu->fpu_owner = NULL;
     395        spinlock_unlock(&t->cpu->lock);
     396
     397        spinlock_unlock(&t->lock);
     398
     399        spinlock_lock(&threads_lock);
     400        avltree_delete(&threads_tree, &t->threads_tree_node);
     401        spinlock_unlock(&threads_lock);
     402
    392403        /*
    393404         * Detach from the containing task.
    394405         */
    395         list_remove(&thread->th_link);
    396         irq_spinlock_unlock(&thread->task->lock, irq_res);
    397        
     406        spinlock_lock(&t->task->lock);
     407        list_remove(&t->th_link);
     408        spinlock_unlock(&t->task->lock);       
     409
    398410        /*
    399411         * Drop the reference to the containing task.
    400412         */
    401         task_release(thread->task);
    402         slab_free(thread_slab, thread);
     413        task_release(t->task);
     414       
     415        slab_free(thread_slab, t);
    403416}
    404417
     
    408421 * threads_tree.
    409422 *
    410  * @param t    Thread to be attached to the task.
    411  * @param task Task to which the thread is to be attached.
    412  *
    413  */
    414 void thread_attach(thread_t *thread, task_t *task)
    415 {
     423 * @param t     Thread to be attached to the task.
     424 * @param task  Task to which the thread is to be attached.
     425 */
     426void thread_attach(thread_t *t, task_t *task)
     427{
     428        ipl_t ipl;
     429
    416430        /*
    417431         * Attach to the specified task.
    418432         */
    419         irq_spinlock_lock(&task->lock, true);
    420        
     433        ipl = interrupts_disable();
     434        spinlock_lock(&task->lock);
     435
    421436        /* Hold a reference to the task. */
    422437        task_hold(task);
    423        
     438
    424439        /* Must not count kbox thread into lifecount */
    425         if (thread->flags & THREAD_FLAG_USPACE)
     440        if (t->flags & THREAD_FLAG_USPACE)
    426441                atomic_inc(&task->lifecount);
    427        
    428         list_append(&thread->th_link, &task->th_head);
    429        
    430         irq_spinlock_pass(&task->lock, &threads_lock);
    431        
     442
     443        list_append(&t->th_link, &task->th_head);
     444        spinlock_unlock(&task->lock);
     445
    432446        /*
    433447         * Register this thread in the system-wide list.
    434448         */
    435         avltree_insert(&threads_tree, &thread->threads_tree_node);
    436         irq_spinlock_unlock(&threads_lock, true);
     449        spinlock_lock(&threads_lock);
     450        avltree_insert(&threads_tree, &t->threads_tree_node);
     451        spinlock_unlock(&threads_lock);
     452       
     453        interrupts_restore(ipl);
    437454}
    438455
    439456/** Terminate thread.
    440457 *
    441  * End current thread execution and switch it to the exiting state.
    442  * All pending timeouts are executed.
    443  *
     458 * End current thread execution and switch it to the exiting state. All pending
     459 * timeouts are executed.
    444460 */
    445461void thread_exit(void)
    446462{
     463        ipl_t ipl;
     464
    447465        if (THREAD->flags & THREAD_FLAG_USPACE) {
    448466#ifdef CONFIG_UDEBUG
    449467                /* Generate udebug THREAD_E event */
    450468                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();
    457469#endif
    458470                if (atomic_predec(&TASK->lifecount) == 0) {
     
    463475                         * can only be created by threads of the same task.
    464476                         * We are safe to perform cleanup.
    465                          *
    466477                         */
    467478                        ipc_cleanup();
     
    470481                }
    471482        }
    472        
     483
    473484restart:
    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);
     485        ipl = interrupts_disable();
     486        spinlock_lock(&THREAD->lock);
     487        if (THREAD->timeout_pending) {
     488                /* busy waiting for timeouts in progress */
     489                spinlock_unlock(&THREAD->lock);
     490                interrupts_restore(ipl);
    478491                goto restart;
    479492        }
    480493       
    481494        THREAD->state = Exiting;
    482         irq_spinlock_unlock(&THREAD->lock, true);
    483        
     495        spinlock_unlock(&THREAD->lock);
    484496        scheduler();
    485        
     497
    486498        /* Not reached */
    487         while (true);
    488 }
     499        while (1)
     500                ;
     501}
     502
    489503
    490504/** Thread sleep
     
    501515        while (sec > 0) {
    502516                uint32_t period = (sec > 1000) ? 1000 : sec;
    503                
     517       
    504518                thread_usleep(period * 1000000);
    505519                sec -= period;
     
    509523/** Wait for another thread to exit.
    510524 *
    511  * @param thread Thread to join on exit.
    512  * @param usec   Timeout in microseconds.
    513  * @param flags  Mode of operation.
     525 * @param t Thread to join on exit.
     526 * @param usec Timeout in microseconds.
     527 * @param flags Mode of operation.
    514528 *
    515529 * @return An error code from errno.h or an error code from synch.h.
    516  *
    517  */
    518 int thread_join_timeout(thread_t *thread, uint32_t usec, unsigned int flags)
    519 {
    520         if (thread == THREAD)
     530 */
     531int thread_join_timeout(thread_t *t, uint32_t usec, int flags)
     532{
     533        ipl_t ipl;
     534        int rc;
     535
     536        if (t == THREAD)
    521537                return EINVAL;
    522        
     538
    523539        /*
    524540         * Since thread join can only be called once on an undetached thread,
     
    526542         */
    527543       
    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);
     544        ipl = interrupts_disable();
     545        spinlock_lock(&t->lock);
     546        ASSERT(!t->detached);
     547        spinlock_unlock(&t->lock);
     548        interrupts_restore(ipl);
     549       
     550        rc = waitq_sleep_timeout(&t->join_wq, usec, flags);
     551       
     552        return rc;     
    533553}
    534554
     
    538558 * state, deallocate its resources.
    539559 *
    540  * @param thread Thread to be detached.
    541  *
    542  */
    543 void thread_detach(thread_t *thread)
    544 {
     560 * @param t Thread to be detached.
     561 */
     562void thread_detach(thread_t *t)
     563{
     564        ipl_t ipl;
     565
    545566        /*
    546567         * Since the thread is expected not to be already detached,
    547568         * pointer to it must be still valid.
    548569         */
    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);
     570        ipl = interrupts_disable();
     571        spinlock_lock(&t->lock);
     572        ASSERT(!t->detached);
     573        if (t->state == Lingering) {
     574                thread_destroy(t);      /* unlocks &t->lock */
     575                interrupts_restore(ipl);
    558576                return;
    559577        } else {
    560                 thread->detached = true;
    561         }
    562        
    563         irq_spinlock_unlock(&thread->lock, true);
     578                t->detached = true;
     579        }
     580        spinlock_unlock(&t->lock);
     581        interrupts_restore(ipl);
    564582}
    565583
     
    580598}
    581599
     600/** Register thread out-of-context invocation
     601 *
     602 * Register a function and its argument to be executed
     603 * on next context switch to the current thread.
     604 *
     605 * @param call_me      Out-of-context function.
     606 * @param call_me_with Out-of-context function argument.
     607 *
     608 */
     609void thread_register_call_me(void (* call_me)(void *), void *call_me_with)
     610{
     611        ipl_t ipl;
     612       
     613        ipl = interrupts_disable();
     614        spinlock_lock(&THREAD->lock);
     615        THREAD->call_me = call_me;
     616        THREAD->call_me_with = call_me_with;
     617        spinlock_unlock(&THREAD->lock);
     618        interrupts_restore(ipl);
     619}
     620
    582621static bool thread_walker(avltree_node_t *node, void *arg)
    583622{
    584         bool *additional = (bool *) arg;
    585         thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node);
     623        thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
    586624       
    587625        uint64_t ucycles, kcycles;
    588626        char usuffix, ksuffix;
    589         order_suffix(thread->ucycles, &ucycles, &usuffix);
    590         order_suffix(thread->kcycles, &kcycles, &ksuffix);
    591        
     627        order_suffix(t->ucycles, &ucycles, &usuffix);
     628        order_suffix(t->kcycles, &kcycles, &ksuffix);
     629
    592630#ifdef __32_BITS__
    593         if (*additional)
    594                 printf("%-8" PRIu64" %10p %9" PRIu64 "%c %9" PRIu64 "%c ",
    595                     thread->tid, thread->kstack, ucycles, usuffix,
    596                     kcycles, ksuffix);
     631        printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9"
     632                PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t,
     633                thread_states[t->state], t->task, t->task->context, t->thread_code,
     634                t->kstack, ucycles, usuffix, kcycles, ksuffix);
     635#endif
     636
     637#ifdef __64_BITS__
     638        printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9"
     639                PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t,
     640                thread_states[t->state], t->task, t->task->context, t->thread_code,
     641                t->kstack, ucycles, usuffix, kcycles, ksuffix);
     642#endif
     643                       
     644        if (t->cpu)
     645                printf("%-4u", t->cpu->id);
    597646        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        
     647                printf("none");
     648                       
     649        if (t->state == Sleeping) {
     650#ifdef __32_BITS__
     651                printf(" %10p", t->sleep_queue);
     652#endif
     653
    603654#ifdef __64_BITS__
    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);
    624 #endif
     655                printf(" %18p", t->sleep_queue);
     656#endif
     657        }
    625658                       
     659        printf("\n");
     660
     661        return true;
     662}
     663
     664/** Print list of threads debug info */
     665void thread_print_list(void)
     666{
     667        ipl_t ipl;
     668       
     669        /* Messing with thread structures, avoid deadlock */
     670        ipl = interrupts_disable();
     671        spinlock_lock(&threads_lock);
     672
     673#ifdef __32_BITS__     
     674        printf("tid    name       address    state    task       "
     675                "ctx code       stack      ucycles    kcycles    cpu  "
     676                "waitqueue\n");
     677        printf("------ ---------- ---------- -------- ---------- "
     678                "--- ---------- ---------- ---------- ---------- ---- "
     679                "----------\n");
     680#endif
     681
    626682#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  */
    642 void 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");
    651         else
    652                 printf("[id    ] [name        ] [address ] [state ] [task    ]"
    653                     " [ctx] [code    ]\n");
    654 #endif
    655        
    656 #ifdef __64_BITS__
    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);
     683        printf("tid    name       address            state    task               "
     684                "ctx code               stack              ucycles    kcycles    cpu  "
     685                "waitqueue\n");
     686        printf("------ ---------- ------------------ -------- ------------------ "
     687                "--- ------------------ ------------------ ---------- ---------- ---- "
     688                "------------------\n");
     689#endif
     690
     691        avltree_walk(&threads_tree, thread_walker, NULL);
     692
     693        spinlock_unlock(&threads_lock);
     694        interrupts_restore(ipl);
    668695}
    669696
     
    673700 * interrupts must be already disabled.
    674701 *
    675  * @param thread Pointer to thread.
     702 * @param t Pointer to thread.
    676703 *
    677704 * @return True if thread t is known to the system, false otherwise.
    678  *
    679  */
    680 bool 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));
     705 */
     706bool thread_exists(thread_t *t)
     707{
     708        avltree_node_t *node;
     709
     710        node = avltree_search(&threads_tree, (avltree_key_t) ((uintptr_t) t));
    687711       
    688712        return node != NULL;
     
    694718 * interrupts must be already disabled.
    695719 *
    696  * @param user True to update user accounting, false for kernel.
    697  *
     720 * @param user  True to update user accounting, false for kernel.
    698721 */
    699722void thread_update_accounting(bool user)
    700723{
    701724        uint64_t time = get_cycle();
    702 
    703         ASSERT(interrupts_disabled());
    704         ASSERT(irq_spinlock_locked(&THREAD->lock));
    705        
    706         if (user)
     725        if (user) {
    707726                THREAD->ucycles += time - THREAD->last_cycle;
    708         else
     727        } else {
    709728                THREAD->kcycles += time - THREAD->last_cycle;
    710        
     729        }
    711730        THREAD->last_cycle = time;
    712731}
     
    738757thread_t *thread_find_by_id(thread_id_t thread_id)
    739758{
    740         ASSERT(interrupts_disabled());
    741         ASSERT(irq_spinlock_locked(&threads_lock));
    742 
    743759        thread_iterator_t iterator;
    744760       
     
    758774    size_t name_len, thread_id_t *uspace_thread_id)
    759775{
     776        thread_t *t;
     777        char namebuf[THREAD_NAME_BUFLEN];
     778        uspace_arg_t *kernel_uarg;
     779        int rc;
     780
    760781        if (name_len > THREAD_NAME_BUFLEN - 1)
    761782                name_len = THREAD_NAME_BUFLEN - 1;
    762        
    763         char namebuf[THREAD_NAME_BUFLEN];
    764         int rc = copy_from_uspace(namebuf, uspace_name, name_len);
     783
     784        rc = copy_from_uspace(namebuf, uspace_name, name_len);
    765785        if (rc != 0)
    766786                return (unative_t) rc;
    767        
     787
    768788        namebuf[name_len] = 0;
    769        
     789
    770790        /*
    771791         * In case of failure, kernel_uarg will be deallocated in this function.
    772792         * In case of success, kernel_uarg will be freed in uinit().
    773          *
    774793         */
    775         uspace_arg_t *kernel_uarg =
    776             (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
     794        kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
    777795       
    778796        rc = copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t));
     
    781799                return (unative_t) rc;
    782800        }
    783        
    784         thread_t *thread = thread_create(uinit, kernel_uarg, TASK,
     801
     802        t = thread_create(uinit, kernel_uarg, TASK,
    785803            THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf, false);
    786         if (thread) {
     804        if (t) {
    787805                if (uspace_thread_id != NULL) {
    788                         rc = copy_to_uspace(uspace_thread_id, &thread->tid,
    789                             sizeof(thread->tid));
     806                        int rc;
     807
     808                        rc = copy_to_uspace(uspace_thread_id, &t->tid,
     809                            sizeof(t->tid));
    790810                        if (rc != 0) {
    791811                                /*
     
    793813                                 * has already been created. We need to undo its
    794814                                 * creation now.
    795                                  *
    796815                                 */
    797                                
     816
    798817                                /*
    799818                                 * The new thread structure is initialized, but
     
    801820                                 * We can safely deallocate it.
    802821                                 */
    803                                 slab_free(thread_slab, thread);
    804                                 free(kernel_uarg);
    805                                
     822                                slab_free(thread_slab, t);
     823                                free(kernel_uarg);
     824
    806825                                return (unative_t) rc;
    807826                         }
    808827                }
    809                
    810828#ifdef CONFIG_UDEBUG
    811829                /*
     
    815833                 * THREAD_B events for threads that already existed
    816834                 * and could be detected with THREAD_READ before.
    817                  *
    818835                 */
    819                 udebug_thread_b_event_attach(thread, TASK);
     836                udebug_thread_b_event_attach(t, TASK);
    820837#else
    821                 thread_attach(thread, TASK);
    822 #endif
    823                 thread_ready(thread);
    824                
     838                thread_attach(t, TASK);
     839#endif
     840                thread_ready(t);
     841
    825842                return 0;
    826843        } else
    827844                free(kernel_uarg);
    828        
     845
    829846        return (unative_t) ENOMEM;
    830847}
     
    836853{
    837854        thread_exit();
    838        
    839855        /* Unreachable */
    840856        return 0;
     
    847863 *
    848864 * @return 0 on success or an error code from @ref errno.h.
    849  *
    850865 */
    851866unative_t sys_thread_get_id(thread_id_t *uspace_thread_id)
     
    854869         * No need to acquire lock on THREAD because tid
    855870         * remains constant for the lifespan of the thread.
    856          *
    857871         */
    858872        return (unative_t) copy_to_uspace(uspace_thread_id, &THREAD->tid,
Note: See TracChangeset for help on using the changeset viewer.