diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2011-12-15 22:58:40 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2011-12-15 22:58:40 +0000 |
commit | 8e0346d1372ed32d2c5f559e083f3bd60b281c3a (patch) | |
tree | b72116c382df57f2e7396b58d32370b731535712 /libgloss/sparc_leon/kernel_thread.c | |
parent | e74758408e50f8980de0d73f5b3721efbd698df9 (diff) | |
download | cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.tar.gz cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.tar.bz2 cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.zip |
2011-12-15 Konrad Eisele <konrad@gaisler.com>
* configure.in: Add SPARC LEON support.
* configure: Regenerated.
* sparc_leon/asm-leon/amba.h, sparc_leon/asm-leon/asmmacro.h,
sparc_leon/asm-leon/clock.h, sparc_leon/asm-leon/contextswitch.h,
sparc_leon/asm-leon/elfmacro.h, sparc_leon/asm-leon/head.h,
sparc_leon/asm-leon/irq.h, sparc_leon/asm-leon/jiffies.h,
sparc_leon/asm-leon/lambapp.h, sparc_leon/asm-leon/lambapp_devs.h,
sparc_leon/asm-leon/leon.h, sparc_leon/asm-leon/leon3.h,
sparc_leon/asm-leon/leonbare_debug.h, sparc_leon/asm-leon/leonbare_kernel.h,
sparc_leon/asm-leon/leonbare_kernel_queue.h, sparc_leon/asm-leon/leoncompat.h,
sparc_leon/asm-leon/leondbg.h, sparc_leon/asm-leon/leonstack.h,
sparc_leon/asm-leon/liblocks.h, sparc_leon/asm-leon/linkage.h,
sparc_leon/asm-leon/param.h, sparc_leon/asm-leon/queue.h,
sparc_leon/asm-leon/spinlock.h, sparc_leon/asm-leon/stack.h,
sparc_leon/asm-leon/time.h, sparc_leon/asm-leon/timer.h,
sparc_leon/asm-leon/types.h, sparc_leon/asm-leon/winmacros.h:
New file.
* sparc_leon/Makefile.in, sparc_leon/_exit.c,
sparc_leon/amba.c, sparc_leon/amba_dbg.c,
sparc_leon/amba_driver.c, sparc_leon/amba_scan.c,
sparc_leon/asm-leon, sparc_leon/bdinit.S,
sparc_leon/busscan.S, sparc_leon/cacheA.S,
sparc_leon/catch_interrupt.c, sparc_leon/catch_interrupt_mvt.c,
sparc_leon/catch_interrupt_pending.c, sparc_leon/catch_interrupt_svt.c,
sparc_leon/configure.in,
sparc_leon/console.c, sparc_leon/console_dbg.c,
sparc_leon/console_init.c, sparc_leon/contextswitch.c,
sparc_leon/contextswitch_asm.S, sparc_leon/crt0.S,
sparc_leon/crti.S, sparc_leon/crtn.S,
sparc_leon/etrap.S, sparc_leon/etrap_fast.S,
sparc_leon/fpu.S, sparc_leon/gettimeofday.c,
sparc_leon/initcalls.c, sparc_leon/io.c,
sparc_leon/irqinstall.S, sparc_leon/irqtrap.S,
sparc_leon/irqtrap_fast.S, sparc_leon/jiffies.c,
sparc_leon/kernel.c, sparc_leon/kernel_context.S,
sparc_leon/kernel_debug.c, sparc_leon/kernel_debug_var.c,
sparc_leon/kernel_mm.c, sparc_leon/kernel_mutex.c,
sparc_leon/kernel_queue.c, sparc_leon/kernel_sched.c,
sparc_leon/kernel_thread.c, sparc_leon/lcpuinit.S,
sparc_leon/locore.S, sparc_leon/locore_atexit.c,
sparc_leon/locore_clean.S, sparc_leon/locore_mvt.S,
sparc_leon/locore_mvt_reset.S, sparc_leon/locore_svt.S,
sparc_leon/locore_svt_reset.S, sparc_leon/locore_svtdisp.S,
sparc_leon/locore_var.S, sparc_leon/locore_var_svt.S,
sparc_leon/mmu_asm.S, sparc_leon/mutex.c,
sparc_leon/nocache.S, sparc_leon/pnpinit.c,
sparc_leon/pnpinit_malloc.c, sparc_leon/pnpinit_simple.c,
sparc_leon/regwin.S, sparc_leon/regwin_patch.c,
sparc_leon/regwin_slow.S, sparc_leon/regwinflush.S,
sparc_leon/rtc.c, sparc_leon/rtrap.S,
sparc_leon/rtrap_fast.S, sparc_leon/stop.S,
sparc_leon/timer.c, sparc_leon/times.c:
New file
* sparc_leon/configure: Regenerate
Diffstat (limited to 'libgloss/sparc_leon/kernel_thread.c')
-rw-r--r-- | libgloss/sparc_leon/kernel_thread.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/libgloss/sparc_leon/kernel_thread.c b/libgloss/sparc_leon/kernel_thread.c new file mode 100644 index 000000000..b51b6beed --- /dev/null +++ b/libgloss/sparc_leon/kernel_thread.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2011 Aeroflex Gaisler + * + * BSD license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include <asm-leon/queue.h> +/*#include <sys/fsu_pthread_queue.h>*/ +#include <asm-leon/contextswitch.h> +#include <asm-leon/leonbare_kernel.h> +#include <asm-leon/leonbare_debug.h> +#include <asm-leon/stack.h> +#include <asm-leon/leonstack.h> +#include <asm-leon/irq.h> + +int +leonbare_thread_resume (leonbare_thread_t thread) +{ + leonbare_thread_t i = 0; + if ((thread->th_flags & LEONBARE_TH_SUSPENDED) && + !(thread->th_flags & (LEONBARE_TH_TERMINATED | LEONBARE_TH_FINISHED))) + { + + LEONBARE_PROTECT_KERNEL_START (); + { + unsigned int idx = leonbare_thread_getqueueidx (thread); + + if (idx != -1) + { + LBTAILQ_REMOVE (LEONBARE_KR_RUNQ (idx), thread, th_runq); + } + + if (thread->th_pri_idx != -1) + { + thread->th_runq_idx = thread->th_pri_idx; + thread->th_runq_which = LEONBARE_KR_RUNQ_WHICH; + LBTAILQ_INSERT_HEAD (LEONBARE_KR_RUNQ (thread->th_runq_idx), + thread, th_runq); + LEONBARE_TH_SETSTATE (thread, LEONBARE_TH_READY); + } + } + LEONBARE_PROTECT_KERNEL_END (); + } + +} + +int +leonbare_thread_terminate (leonbare_thread_t thread) +{ + unsigned int ret = 0; + leonbare_thread_t c = LEONBARE_KR_CURRENT; + LEONBARE_PROTECT_KERNEL_START (); + { + unsigned int idx = leonbare_thread_getqueueidx (thread); + + if (LEONBARE_RUNQ_ISREADY (idx) || LEONBARE_RUNQ_ISPREPARE (idx) || + LEONBARE_RUNQ_ISSUSPEND (idx)) + { + LBTAILQ_REMOVE (LEONBARE_KR_RUNQ (idx), thread, th_runq); + } + else + { + LBPASSERT (LEONBARE_RUNQ_ISKILLED (idx), + "thread %s is in no queue ", + LEONBARE_TH_NAME_DBG (thread)); + } + LEONBARE_TH_SETSTATE (thread, LEONBARE_TH_TERMINATED); + LBTAILQ_INSERT_HEAD (LEONBARE_KR_RUNQ (LEONBARE_RUNQ_KILLED_IDX), thread, + th_runq); + + LEONBARE_PRINTQUEUES (); + + LEONBARE_VERIFYSCHED (); + } + if (thread == LEONBARE_KR_CURRENT) + { + ret = reschedule (); + /* never come here */ + LEONBARE_STOPALL; + } + LEONBARE_PROTECT_KERNEL_END (); + return ret; +} + + +int +current_suspend () +{ + unsigned int ret = 0; + leonbare_thread_t c = LEONBARE_KR_CURRENT; + LEONBARE_PROTECT_KERNEL_START (); + { + LBPASSERT ((c->th_runq_which == LEONBARE_KR_RUNQ_WHICH), + "Current thread cannot be on the prepare queue", 0); + + LBTAILQ_REMOVE (LEONBARE_KR_RUNQ (c->th_runq_idx), c, th_runq); + LBTAILQ_INSERT_TAIL (LEONBARE_KR_RUNQ (LEONBARE_RUNQ_SUSPENDED_IDX), + c, th_runq); + c->th_runq_idx = LEONBARE_RUNQ_SUSPENDED_IDX; + LEONBARE_TH_SETSTATE (c, LEONBARE_TH_SUSPENDED); + LEONBARE_VERIFYSCHED (); + } + ret = reschedule (); + LEONBARE_PROTECT_KERNEL_END (); + return ret; +} + +void +_leonbare_thread_body () +{ + LBDEBUG_FNCALL; + leonbare_thread_t thread = LEONBARE_KR_CURRENT; + + LEONBARE_KR_IS_IN_KERNEL = 0; + thread->th_result = thread->th_func (thread->th_arg); + + leonbare_thread_terminate (thread); + + LBDEBUG_FNEXIT; +} + +#define LEONBARE_BODY_OFFSET 200 + +int +leonbare_thread_create (struct leonbare_thread *thread, char *stack, + int stacksize) +{ + LEONBARE_PROTECT_DECL (flags); + struct sparc_stackframe_regs *sp; + unsigned int v; + unsigned int fpspill, bodysp, bodyfp; + struct leonbare_thread_ctx *threadctx; + LBDEBUG_FNCALL; + + thread->th_stack_base = (char *) LEONBARE_STACKALIGN (stack); + stacksize -= thread->th_stack_base - stack; + thread->th_stack_size = stacksize; + thread->th_runq_idx = 0; + thread->th_pri_idx = 0; + thread->th_account = 0; + thread->th_caccount = 0; + + /* stack: + * 0:+--------------------------------+ <- thread.th_stack_base + * | .... | + * +--------------------------------+ <- thread.th_ctx->out[6] (%sp) + * | _leonbare_thread_body() frame | + * +--------------------------------+ <- thread.th_ctx->sf_ins[6] (%fp) + * | WINDOWSPILL | + * +--------------------------------+ <- thread.th_ctx->fpu + * | struct sparc_fpuwindow_regs | + * +--------------------------------+ <- thread.th_stack_base + thread->th_stack_size + * + */ + v = (unsigned int) (thread->th_stack_base + + LEONBARE_STACKALIGN (thread->th_stack_size - + (LEONBARE_BODY_OFFSET + + WINDOWSIZE + FW_REGS_SZ))); + + bodysp = ((unsigned int) v); + bodyfp = ((unsigned int) bodysp) + LEONBARE_BODY_OFFSET; + fpspill = ((unsigned int) bodyfp) + WINDOWSIZE; + + thread->th_ctx.outs[6] = (unsigned int) bodysp; + thread->th_ctx.outs[7] = (int) _leonbare_thread_body; + thread->th_ctx.outs[7] -= 8; + thread->th_ctx.sf_ins[6] = (unsigned int) bodyfp; + thread->th_ctx.fpu = (unsigned int) fpspill; + thread->th_ctx.magic = LEONBARE_THREAD_CTX_MAGIC; + + thread->th_ctx.psr = 0x0e0; + thread->th_ctx.wim = 0x2; + + LBDEBUG_HEADER_PRINTF (LBDEBUG_THREAD_NR, + "Thread %s (0x%x): stack [0x%x-0x%x] \n", + LEONBARE_TH_NAME_DBG (thread), thread, + thread->th_stack_base, + thread->th_stack_base + thread->th_stack_size); + + /* newlibc reent */ + thread->th_reentp = &(thread->th_reent); + _REENT_INIT_PTR (thread->th_reentp); + + LEONBARE_PROTECT_KERNEL_START (); + /* queues */ + LBTAILQ_INSERT_TAIL (LEONBARE_KR_ALLQ, thread, th_allq); + LBTAILQ_INSERT_TAIL (LEONBARE_KR_RUNQ (thread->th_runq_idx), thread, + th_runq); + + LEONBARE_PRINTQUEUES (); + + LEONBARE_PROTECT_KERNEL_END (); + + LBDEBUG_FNEXIT; +} |