From f906f80359f45dea05861802e31d67d10a8d5a88 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 15 Feb 2008 18:20:20 +0000 Subject: [PATCH] Made arch/z80 handling chip-specific git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@686 42af7a65-404d-4744-a932-0658087f49c3 --- arch/z80/src/z8/Make.defs | 6 +- arch/z80/src/z8/chip.h | 2 +- arch/z80/src/z8/switch.h | 20 +- arch/z80/src/z8/z8_copystate.c | 2 +- arch/z80/src/z8/z8_registerdump.c | 2 +- arch/z80/src/z8/z8_schedulesigaction.c | 192 ++++++++++++++++++ .../z80_sigsetup.c => z8/z8_sigdeliver.c} | 84 ++++++-- arch/z80/src/z80/Make.defs | 7 +- arch/z80/src/z80/switch.h | 20 +- .../z80_schedulesigaction.c} | 28 ++- .../up_sigdeliver.c => z80/z80_sigdeliver.c} | 19 +- 11 files changed, 307 insertions(+), 75 deletions(-) create mode 100644 arch/z80/src/z8/z8_schedulesigaction.c rename arch/z80/src/{z80/z80_sigsetup.c => z8/z8_sigdeliver.c} (60%) rename arch/z80/src/{common/up_schedulesigaction.c => z80/z80_schedulesigaction.c} (87%) rename arch/z80/src/{common/up_sigdeliver.c => z80/z80_sigdeliver.c} (90%) diff --git a/arch/z80/src/z8/Make.defs b/arch/z80/src/z8/Make.defs index 9bff5da616..328f785bcb 100644 --- a/arch/z80/src/z8/Make.defs +++ b/arch/z80/src/z8/Make.defs @@ -40,9 +40,9 @@ CMN_CSRCS = up_initialize.c up_allocateheap.c up_createstack.c \ up_releasestack.c up_interruptcontext.c up_blocktask.c \ up_unblocktask.c up_exit.c up_releasepending.c \ up_reprioritizertr.c up_idle.c up_assert.c up_doirq.c \ - up_mdelay.c up_udelay.c up_schedulesigaction.c \ - up_sigdeliver.c up_usestack.c + up_mdelay.c up_udelay.c up_usestack.c CHIP_SSRCS = z8_vector.S z8_saveusercontext.S z8_restorecontext.S -CHIP_CSRCS = z8_initialstate.c z8_copystate.c #z8_irq.c z8_registerdump.c +CHIP_CSRCS = z8_initialstate.c z8_copystate.c z8_irq.c \ + z8_schedulesigaction.c z8_sigdeliver.c z8_registerdump.c diff --git a/arch/z80/src/z8/chip.h b/arch/z80/src/z8/chip.h index 7a0f3355a8..99b058404c 100644 --- a/arch/z80/src/z8/chip.h +++ b/arch/z80/src/z8/chip.h @@ -1,5 +1,5 @@ /************************************************************************************ - * arch/z80/src/z80/chip.h + * arch/z80/src/z8/chip.h * arch/z80/src/chip/chip.h * * Copyright (C) 2008 Gregory Nutt. All rights reserved. diff --git a/arch/z80/src/z8/switch.h b/arch/z80/src/z8/switch.h index d0ab4db136..ff921858e4 100644 --- a/arch/z80/src/z8/switch.h +++ b/arch/z80/src/z8/switch.h @@ -74,17 +74,13 @@ #define IRQ_STATE() (current_regs) -/* Copy a register state save structure to another location */ - -#define COPYSTATE(r1,r2) z8_copystate(r1,r2) - /* Save the current IRQ context in the specified TCB */ -#define SAVE_IRQCONTEXT(tcb) COPYSTATE((tcb)->xcp.regs, current_regs) +#define SAVE_IRQCONTEXT(tcb) z8_copystate((tcb)->xcp.regs, current_regs) /* Set the current IRQ context to the state specified in the TCB */ -#define SET_IRQCONTEXT(tcb) COPYSTATE(current_regs, (tcb)->xcp.regs) +#define SET_IRQCONTEXT(tcb) z8_copystate(current_regs, (tcb)->xcp.regs) /* Save the user context in the specified TCB. User context saves can be simpler * because only those registers normally saved in a C called need be stored. @@ -98,18 +94,6 @@ #define RESTORE_USERCONTEXT(tcb) z8_restorecontext((tcb)->xcp.regs) -/* Verify that we have a signal handler */ - -#define SIGNAL_DELIVERING(tcb) (tcb->xcp.sigdeliver != NULL) - -/* Setup the signal handler trampoline */ - -#define SIGNAL_SETUP(tcb, sigdeliver, regs) z8_sigsetup(tcb, sigdeliver, regs) - -/* Return from a signal handler using the provided register context */ - -#define SIGNAL_RETURN(regs) z8_restorecontext(regs) - /* Dump the current machine registers */ #define _REGISTER_DUMP() z8_registerdump() diff --git a/arch/z80/src/z8/z8_copystate.c b/arch/z80/src/z8/z8_copystate.c index d4d4601a8a..881f0a4a50 100644 --- a/arch/z80/src/z8/z8_copystate.c +++ b/arch/z80/src/z8/z8_copystate.c @@ -63,7 +63,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: z80_copystate + * Name: z8_copystate ****************************************************************************/ /* Maybe a little faster than most memcpy's */ diff --git a/arch/z80/src/z8/z8_registerdump.c b/arch/z80/src/z8/z8_registerdump.c index 8e789b88f7..0a77659a4c 100644 --- a/arch/z80/src/z8/z8_registerdump.c +++ b/arch/z80/src/z8/z8_registerdump.c @@ -71,7 +71,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: z80_registerdump + * Name: z8_registerdump ****************************************************************************/ #ifdef CONFIG_ARCH_STACKDUMP diff --git a/arch/z80/src/z8/z8_schedulesigaction.c b/arch/z80/src/z8/z8_schedulesigaction.c new file mode 100644 index 0000000000..ad02f0137c --- /dev/null +++ b/arch/z80/src/z8/z8_schedulesigaction.c @@ -0,0 +1,192 @@ +/**************************************************************************** + * arch/z80/src/z8/z8_schedulesigaction.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "chip/switch.h" +#include "os_internal.h" +#include "up_internal.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: z8_sigsetup + ****************************************************************************/ + +static void z8_sigsetup(FAR _TCB *tcb, sig_deliver_t sigdeliver, FAR chipreg_t *regs) +{ + /* Save the return address and interrupt state. These will be restored by + * the signal trampoline after the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = regs[XCPT_PC]; + tcb->xcp.saved_i = regs[XCPT_I]; + + /* Then set up to vector to the trampoline with interrupts disabled */ + + regs[XCPT_PC] = (chipreg_t)up_sigdeliver; + regs[XCPT_I] = 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver) +{ + dbg("tcb=0x%p sigdeliver=0x%04x\n", tcb, (uint16)sigdeliver); + + /* Refuse to handle nested signal actions */ + + if (tcb->xcp.sigdeliver == NULL) + { + irqstate_t flags; + + /* Make sure that interrupts are disabled */ + + flags = irqsave(); + + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ + + if (tcb == (FAR _TCB*)g_readytorun.head) + { + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. + */ + + if (!IN_INTERRUPT()) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. + */ + + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ + + z8_sigsetup(tcb, sigdeliver, IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); + } + } + + /* Otherwise, we are (1) signaling a task is not running from an interrupt + * handler or (2) we are not in an interrupt handler and the running task + * is signalling some non-running task. + */ + + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ + + z8_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + } + + irqrestore(flags); + } +} + +#endif /* CONFIG_DISABLE_SIGNALS */ + diff --git a/arch/z80/src/z80/z80_sigsetup.c b/arch/z80/src/z8/z8_sigdeliver.c similarity index 60% rename from arch/z80/src/z80/z80_sigsetup.c rename to arch/z80/src/z8/z8_sigdeliver.c index 504f3ce192..857db51e5b 100644 --- a/arch/z80/src/z80/z80_sigsetup.c +++ b/arch/z80/src/z8/z8_sigdeliver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/z80/src/z80/z80_sigsetup.c + * arch/z80/src/z8/z8_sigdeliver.c * * Copyright (C) 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -40,12 +40,18 @@ #include #include -#include +#include +#include + +#include +#include #include "chip/switch.h" #include "os_internal.h" #include "up_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS + /**************************************************************************** * Definitions ****************************************************************************/ @@ -63,25 +69,73 @@ ****************************************************************************/ /**************************************************************************** - * Name: z80_copystate + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a + * signal action was posted. The task context was mucked + * with and forced to branch to this location with interrupts + * disabled. + * ****************************************************************************/ -void z80_sigsetup(FAR _TCB *tcb, sig_deliver_t sigdeliver, FAR chipreg_t *regs) +void up_sigdeliver(void) { - /* Save the return address and interrupt state. These will be restored by - * the signal trampoline after the signals have been delivered (via - * SIGNAL_RETURN). +#ifndef CONFIG_DISABLE_SIGNALS + FAR _TCB *rtcb = (_TCB*)g_readytorun.head; + chipret_t regs[XCPTCONTEXT_REGS]; + sig_deliver_t sigdeliver; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the the user code final gets the correct errno value (probably + * EINTR). */ - tcb->xcp.sigdeliver = sigdeliver; - tcb->xcp.saved_pc = regs[XCPT_PC]; - tcb->xcp.saved_i = regs[XCPT_I]; + int saved_errno = rtcb->pterrno; - /* Then set up to vector to the trampoline with interrupts disabled */ + up_ledon(LED_SIGNAL); - regs[XCPT_PC] = (chipreg_t)up_sigdeliver; - regs[XCPT_I] = 0; + dbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + ASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the real return state on the stack. */ + + z8_copystate(regs, rtcb->xcp.regs); + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + + /* Get a local copy of the sigdeliver function pointer. We do this so + * that we can nullify the sigdeliver function point in the TCB and accept + * more signal deliveries while processing the current pending signals. + */ + + sigdeliver = rtcb->xcp.sigdeliver; + rtcb->xcp.sigdeliver = NULL; + + /* Then restore the task interrupt state. */ + + irqrestore(regs[XCPT_I]); + + /* Deliver the signals */ + + sigdeliver(rtcb); + + /* Output any debug messaged BEFORE restoring errno (because they may alter + * errno), then restore the original errno that is needed by the user logic + * (it is probably EINTR). + */ + + dbg("Resuming\n"); + rtcb->pterrno = saved_errno; + + /* Then restore the correct state for this thread of + * execution. + */ + + up_ledoff(LED_SIGNAL); + z8_restoreusercontext(regs); +#endif } - - +#endif /* CONFIG_DISABLE_SIGNALS */ diff --git a/arch/z80/src/z80/Make.defs b/arch/z80/src/z80/Make.defs index 18c6bca72e..fb1be00e20 100644 --- a/arch/z80/src/z80/Make.defs +++ b/arch/z80/src/z80/Make.defs @@ -40,9 +40,10 @@ CMN_CSRCS = up_initialize.c up_allocateheap.c up_createstack.c \ up_releasestack.c up_interruptcontext.c up_blocktask.c \ up_unblocktask.c up_exit.c up_releasepending.c \ up_reprioritizertr.c up_idle.c up_assert.c up_doirq.c \ - up_mdelay.c up_udelay.c up_schedulesigaction.c \ - up_sigdeliver.c up_usestack.c + up_mdelay.c up_udelay.c up_usestack.c CHIP_ASRCS = z80_saveusercontext.asm z80_restoreusercontext.asm -CHIP_CSRCS = z80_initialstate.c z80_irq.c z80_copystate.c z80_registerdump.c +CHIP_CSRCS = z80_initialstate.c z80_irq.c z80_copystate.c \ + z80_schedulesigaction.c z80_sigdeliver.c \ + z80_registerdump.c diff --git a/arch/z80/src/z80/switch.h b/arch/z80/src/z80/switch.h index c0c689dbfd..2ba18615be 100644 --- a/arch/z80/src/z80/switch.h +++ b/arch/z80/src/z80/switch.h @@ -74,17 +74,13 @@ #define IRQ_STATE() (current_regs) -/* Copy a register state save structure to another location */ - -#define COPYSTATE(r1,r2) z80_copystate(r1,r2) - /* Save the current IRQ context in the specified TCB */ -#define SAVE_IRQCONTEXT(tcb) COPYSTATE((tcb)->xcp.regs, current_regs) +#define SAVE_IRQCONTEXT(tcb) z80_copystate((tcb)->xcp.regs, current_regs) /* Set the current IRQ context to the state specified in the TCB */ -#define SET_IRQCONTEXT(tcb) COPYSTATE(current_regs, (tcb)->xcp.regs) +#define SET_IRQCONTEXT(tcb) z80_copystate(current_regs, (tcb)->xcp.regs) /* Save the user context in the specified TCB. User context saves can be simpler * because only those registers normally saved in a C called need be stored. @@ -98,18 +94,6 @@ #define RESTORE_USERCONTEXT(tcb) z80_restoreusercontext((tcb)->xcp.regs) -/* Verify that we have a signal handler */ - -#define SIGNAL_DELIVERING(tcb) (tcb->xcp.sigdeliver != NULL) - -/* Setup the signal handler trampoline */ - -#define SIGNAL_SETUP(tcb, sigdeliver, regs) z80_sigsetup(tcb, sigdeliver, regs) - -/* Return from a signal handler using the provided register context */ - -#define SIGNAL_RETURN(regs) z80_restoreusercontext(regs) - /* Dump the current machine registers */ #define _REGISTER_DUMP() z80_registerdump() diff --git a/arch/z80/src/common/up_schedulesigaction.c b/arch/z80/src/z80/z80_schedulesigaction.c similarity index 87% rename from arch/z80/src/common/up_schedulesigaction.c rename to arch/z80/src/z80/z80_schedulesigaction.c index 2c4d4294d5..6844b44e1f 100644 --- a/arch/z80/src/common/up_schedulesigaction.c +++ b/arch/z80/src/z80/z80_schedulesigaction.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/z80/src/common/up_schedulesigaction.c + * arch/z80/src/z80/z80_schedulesigaction.c * * Copyright (C) 2007,2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -64,6 +64,26 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: z80_sigsetup + ****************************************************************************/ + +static void z80_sigsetup(FAR _TCB *tcb, sig_deliver_t sigdeliver, FAR chipreg_t *regs) +{ + /* Save the return address and interrupt state. These will be restored by + * the signal trampoline after the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = regs[XCPT_PC]; + tcb->xcp.saved_i = regs[XCPT_I]; + + /* Then set up to vector to the trampoline with interrupts disabled */ + + regs[XCPT_PC] = (chipreg_t)up_sigdeliver; + regs[XCPT_I] = 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -107,7 +127,7 @@ void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver) /* Refuse to handle nested signal actions */ - if (!SIGNAL_DELIVERING(tcb)) + if (tcb->xcp.sigdeliver == NULL) { irqstate_t flags; @@ -142,7 +162,7 @@ void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver) { /* Set up to vector to the trampoline with interrupts disabled. */ - SIGNAL_SETUP(tcb, sigdeliver, IRQ_STATE()); + z80_sigsetup(tcb, sigdeliver, IRQ_STATE()); /* And make sure that the saved context in the TCB * is the same as the interrupt return context. @@ -161,7 +181,7 @@ void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver) { /* Set up to vector to the trampoline with interrupts disabled. */ - SIGNAL_SETUP(tcb, sigdeliver, tcb->xcp.regs); + z80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); } irqrestore(flags); diff --git a/arch/z80/src/common/up_sigdeliver.c b/arch/z80/src/z80/z80_sigdeliver.c similarity index 90% rename from arch/z80/src/common/up_sigdeliver.c rename to arch/z80/src/z80/z80_sigdeliver.c index 80fcb4e5c7..299e06a9f2 100644 --- a/arch/z80/src/common/up_sigdeliver.c +++ b/arch/z80/src/z80/z80_sigdeliver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/z80/src/common/up_sigdeliver.c + * arch/z80/src/z80/z80_sigdeliver.c * * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -101,15 +101,13 @@ void up_sigdeliver(void) /* Save the real return state on the stack. */ - COPYSTATE(regs, rtcb->xcp.regs); + z80_copystate(regs, rtcb->xcp.regs); regs[XCPT_PC] = rtcb->xcp.saved_pc; regs[XCPT_I] = rtcb->xcp.saved_i; - /* Get a local copy of the sigdeliver function pointer. - * we do this so that we can nullify the sigdeliver - * function point in the TCB and accept more signal - * deliveries while processing the current pending - * signals. + /* Get a local copy of the sigdeliver function pointer. We do this so + * that we can nullify the sigdeliver function point in the TCB and accept + * more signal deliveries while processing the current pending signals. */ sigdeliver = rtcb->xcp.sigdeliver; @@ -123,9 +121,8 @@ void up_sigdeliver(void) sigdeliver(rtcb); - /* Output any debug messaged BEFORE restoring errno - * (because they may alter errno), then restore the - * original errno that is needed by the user logic + /* Output any debug messaged BEFORE restoring errno (because they may alter + * errno), then restore the original errno that is needed by the user logic * (it is probably EINTR). */ @@ -137,7 +134,7 @@ void up_sigdeliver(void) */ up_ledoff(LED_SIGNAL); - SIGNAL_RETURN(regs); + z80_restoreusercontext(regs); #endif }