Skip to content
Snippets Groups Projects
Select Git revision
  • 9a243b9ccd6f48dda83e40ebfe1988b75691f667
  • master default protected
2 results

thread.c

  • Armin Luntzer's avatar
    Armin Luntzer authored
    	* split EDF scheduler to separate file
    	* some cleanup
    d0d927b5
    History
    thread.c 2.83 KiB
    /**
     * @file arch/sparc/kernel/thread.c
     * 
     * @ingroup sparc
     *
     * This program is free software; you can redistribute it and/or modify it
     * under the terms and conditions of the GNU General Public License,
     * version 2, as published by the Free Software Foundation.
     *
     * This program is distributed in the hope it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     * more details.
     *
     *
     * @brief implements the architecture specific thread component
     *
     */
    
    
    #include <asm/thread.h>
    
    #include <asm/irqflags.h>
    #include <asm/leon.h>
    
    #include <kernel/export.h>
    #include <kernel/kthread.h>
    
    #define MSG "SPARC THREAD: "
    
    
    extern struct thread_info *current_set[];
    
    
    
    
    /**
     * @brief this is a wrapper that actually executes the thread function
     */
    #include <kernel/time.h>
    static void th_starter(void)
    {
    	struct task_struct *task = current_set[0]->task;
    
    	struct timespec ts;
    	double start;
    	double stop;
    
    	ts = get_uptime();
    
    	start = (double) ts.tv_sec + (double) ts.tv_nsec / 1e9;
    
    	task->thread_fn(task->data);
    
    	arch_local_irq_disable();
    	ts = get_uptime();
    	stop = (double) ts.tv_sec + (double) ts.tv_nsec / 1e9;
    	printk("thread: %p returned after %gs\n", task->stack, stop-start);
    	task->state = TASK_DEAD;
    	arch_local_irq_enable();
    
    	schedule();
    
    	pr_crit(MSG "should never have reached %s:%d", __func__, __LINE__);
    	BUG();
    }
    
    
    
    
    /**
     * @brief initialise a task structure
     */
    
    void arch_init_task(struct task_struct *task,
    		    int (*thread_fn)(void *data),
    		    void *data)
    {
    
    #define STACKFRAME_SZ	96
    #define PTREG_SZ	80
    #define PSR_CWP     0x0000001f
    	task->thread_info.ksp = (unsigned long) task->stack_top - (STACKFRAME_SZ + PTREG_SZ);
    	task->thread_info.kpc = (unsigned long) th_starter - 8;
    	task->thread_info.kpsr = get_psr();
    	task->thread_info.kwim = 1 << (((get_psr() & PSR_CWP) + 1) % 8);
    	task->thread_info.task = task;
    
    	task->thread_fn = thread_fn;
    	task->data      = data;
    }
    EXPORT_SYMBOL(arch_init_task);
    
    
    
    /**
     * @brief promote the currently executed path to a task
     * @note we use this to move our main thread to the task list
     */
    
    void arch_promote_to_task(struct task_struct *task)
    {
    #define PSR_CWP     0x0000001f
    
    	task->thread_info.ksp = (unsigned long) leon_get_fp();
    	task->thread_info.kpc = (unsigned long) __builtin_return_address(1) - 8;
    	task->thread_info.kpsr = get_psr();
    	task->thread_info.kwim = 1 << (((get_psr() & PSR_CWP) + 1) % 8);
    	task->thread_info.task = task;
    
    	task->thread_fn = NULL;
    	task->data      = NULL;
    
    
    	printk(MSG "kernel stack %x\n", leon_get_fp());
    
    	printk(MSG "is next at %p stack %p\n", &task->thread_info, task->stack);
    
    
    	/* and set the new thread as current */
    	__asm__ __volatile__("mov	%0, %%g6\n\t"
    			     :: "r"(&(task->thread_info)) : "memory");
    
    
    }
    EXPORT_SYMBOL(arch_promote_to_task);