Ignore:
File:
1 edited

Legend:

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

    rf22dc820 r8ad7dd1  
    4646#include <synch/spinlock.h>
    4747#include <synch/waitq.h>
     48#include <synch/workqueue.h>
     49#include <synch/rcu.h>
    4850#include <cpu.h>
    4951#include <str.h>
     
    192194        kmflags &= ~FRAME_HIGHMEM;
    193195       
    194         thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
    195         if (!thread->kstack) {
     196        uintptr_t stack_phys =
     197            frame_alloc(STACK_FRAMES, kmflags, STACK_SIZE - 1);
     198        if (!stack_phys) {
    196199#ifdef CONFIG_FPU
    197200                if (thread->saved_fpu_context)
     
    201204        }
    202205       
     206        thread->kstack = (uint8_t *) PA2KA(stack_phys);
     207       
    203208#ifdef CONFIG_UDEBUG
    204209        mutex_initialize(&thread->udebug.lock, MUTEX_PASSIVE);
     
    216221        thr_destructor_arch(thread);
    217222       
    218         frame_free(KA2PA(thread->kstack));
     223        frame_free(KA2PA(thread->kstack), STACK_FRAMES);
    219224       
    220225#ifdef CONFIG_FPU
     
    260265}
    261266
     267/** Invoked right before thread_ready() readies the thread. thread is locked. */
     268static void before_thread_is_ready(thread_t *thread)
     269{
     270        ASSERT(irq_spinlock_locked(&thread->lock));
     271        workq_before_thread_is_ready(thread);
     272}
     273
    262274/** Make thread ready
    263275 *
     
    272284       
    273285        ASSERT(thread->state != Ready);
     286
     287        before_thread_is_ready(thread);
    274288       
    275289        int i = (thread->priority < RQ_COUNT - 1) ?
    276290            ++thread->priority : thread->priority;
    277        
     291
    278292        cpu_t *cpu;
    279293        if (thread->wired || thread->nomigrate || thread->fpu_context_engaged) {
     294                /* Cannot ready to another CPU */
    280295                ASSERT(thread->cpu != NULL);
    281296                cpu = thread->cpu;
    282         } else
     297        } else if (thread->stolen) {
     298                /* Ready to the stealing CPU */
    283299                cpu = CPU;
     300        } else if (thread->cpu) {
     301                /* Prefer the CPU on which the thread ran last */
     302                ASSERT(thread->cpu != NULL);
     303                cpu = thread->cpu;
     304        } else {
     305                cpu = CPU;
     306        }
    284307       
    285308        thread->state = Ready;
     
    297320       
    298321        atomic_inc(&nrdy);
    299         // FIXME: Why is the avg value not used
    300         // avg = atomic_get(&nrdy) / config.cpu_active;
    301322        atomic_inc(&cpu->nrdy);
    302323}
     
    374395        thread->task = task;
    375396       
     397        thread->workq = NULL;
     398       
    376399        thread->fpu_context_exists = false;
    377400        thread->fpu_context_engaged = false;
     
    388411        /* Might depend on previous initialization */
    389412        thread_create_arch(thread);
     413       
     414        rcu_thread_init(thread);
    390415       
    391416        if ((flags & THREAD_FLAG_NOATTACH) != THREAD_FLAG_NOATTACH)
     
    498523                         */
    499524                        ipc_cleanup();
    500                         futex_cleanup();
     525                        futex_task_cleanup();
    501526                        LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid);
    502527                }
     
    518543        /* Not reached */
    519544        while (true);
     545}
     546
     547/** Interrupts an existing thread so that it may exit as soon as possible.
     548 *
     549 * Threads that are blocked waiting for a synchronization primitive
     550 * are woken up with a return code of ESYNCH_INTERRUPTED if the
     551 * blocking call was interruptable. See waitq_sleep_timeout().
     552 *
     553 * The caller must guarantee the thread object is valid during the entire
     554 * function, eg by holding the threads_lock lock.
     555 *
     556 * Interrupted threads automatically exit when returning back to user space.
     557 *
     558 * @param thread A valid thread object. The caller must guarantee it
     559 *               will remain valid until thread_interrupt() exits.
     560 */
     561void thread_interrupt(thread_t *thread)
     562{
     563        ASSERT(thread != NULL);
     564       
     565        irq_spinlock_lock(&thread->lock, true);
     566       
     567        thread->interrupted = true;
     568        bool sleeping = (thread->state == Sleeping);
     569       
     570        irq_spinlock_unlock(&thread->lock, true);
     571       
     572        if (sleeping)
     573                waitq_interrupt_sleep(thread);
     574}
     575
     576/** Returns true if the thread was interrupted.
     577 *
     578 * @param thread A valid thread object. User must guarantee it will
     579 *               be alive during the entire call.
     580 * @return true if the thread was already interrupted via thread_interrupt().
     581 */
     582bool thread_interrupted(thread_t *thread)
     583{
     584        ASSERT(thread != NULL);
     585       
     586        bool interrupted;
     587       
     588        irq_spinlock_lock(&thread->lock, true);
     589        interrupted = thread->interrupted;
     590        irq_spinlock_unlock(&thread->lock, true);
     591       
     592        return interrupted;
    520593}
    521594
Note: See TracChangeset for help on using the changeset viewer.