diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-17 23:38:05 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-17 23:38:05 +0000 |
commit | d1a54833aa39c06f38bc656d0811674e9826f7d3 (patch) | |
tree | 4b5911ef52d216a622db785fddf36eb72c5c3512 /nuttx | |
parent | 05f9f43d38c58f39c7c62279b6a7d1c848507ade (diff) | |
download | px4-nuttx-d1a54833aa39c06f38bc656d0811674e9826f7d3.tar.gz px4-nuttx-d1a54833aa39c06f38bc656d0811674e9826f7d3.tar.bz2 px4-nuttx-d1a54833aa39c06f38bc656d0811674e9826f7d3.zip |
Integrate PIC support into context switching
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1900 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/arch/arm/include/arm/irq.h | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/include/cortexm3/irq.h | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/src/arm/up_initialstate.c | 15 | ||||
-rw-r--r-- | nuttx/arch/arm/src/cortexm3/up_initialstate.c | 15 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_execmodule.c | 2 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_load.c | 16 | ||||
-rw-r--r-- | nuttx/examples/nxflat/tests/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/include/nuttx/binfmt.h | 3 | ||||
-rw-r--r-- | nuttx/include/nuttx/nxflat.h | 24 | ||||
-rw-r--r-- | nuttx/include/nuttx/sched.h | 14 | ||||
-rw-r--r-- | nuttx/sched/sched_releasetcb.c | 11 | ||||
-rw-r--r-- | nuttx/sched/task_setup.c | 56 | ||||
-rw-r--r-- | nuttx/sched/wd_start.c | 2 |
13 files changed, 139 insertions, 33 deletions
diff --git a/nuttx/arch/arm/include/arm/irq.h b/nuttx/arch/arm/include/arm/irq.h index 11c2bb046..98335c23f 100644 --- a/nuttx/arch/arm/include/arm/irq.h +++ b/nuttx/arch/arm/include/arm/irq.h @@ -103,6 +103,12 @@ #define REG_LR REG_R14 #define REG_PC REG_R15 +/* The PIC register is usually R10. It can be R9 is stack checking is enabled + * or if the user changes it with -mpic-register on the GCC command line. + */ + +#define REG_PIC REG_R10 + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/nuttx/arch/arm/include/cortexm3/irq.h b/nuttx/arch/arm/include/cortexm3/irq.h index ce126748a..b439ec42f 100644 --- a/nuttx/arch/arm/include/cortexm3/irq.h +++ b/nuttx/arch/arm/include/cortexm3/irq.h @@ -109,6 +109,12 @@ #define REG_LR REG_R14 #define REG_PC REG_R15 +/* The PIC register is usually R10. It can be R9 is stack checking is enabled + * or if the user changes it with -mpic-register on the GCC command line. + */ + +#define REG_PIC REG_R10 + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/nuttx/arch/arm/src/arm/up_initialstate.c b/nuttx/arch/arm/src/arm/up_initialstate.c index 2ba683445..c3a5f8a83 100644 --- a/nuttx/arch/arm/src/arm/up_initialstate.c +++ b/nuttx/arch/arm/src/arm/up_initialstate.c @@ -93,6 +93,21 @@ void up_initial_state(_TCB *tcb) xcp->regs[REG_PC] = (uint32)tcb->start; + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32)tcb->dspace->region; + } +#endif + /* Enable or disable interrupts, based on user configuration */ # ifdef CONFIG_SUPPRESS_INTERRUPTS diff --git a/nuttx/arch/arm/src/cortexm3/up_initialstate.c b/nuttx/arch/arm/src/cortexm3/up_initialstate.c index c529064d4..9bf65bf57 100644 --- a/nuttx/arch/arm/src/cortexm3/up_initialstate.c +++ b/nuttx/arch/arm/src/cortexm3/up_initialstate.c @@ -97,6 +97,21 @@ void up_initial_state(_TCB *tcb) xcp->regs[REG_XPSR] = CORTEXM3_XPSR_T; + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32)tcb->dspace->region; + } +#endif + /* Enable or disable interrupts, based on user configuration */ # ifdef CONFIG_SUPPRESS_INTERRUPTS diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c index de65c15cf..21fe55987 100644 --- a/nuttx/binfmt/binfmt_execmodule.c +++ b/nuttx/binfmt/binfmt_execmodule.c @@ -145,7 +145,7 @@ int exec_module(FAR const struct binary_s *bin, int priority) /* Add the DSpace address as the PIC base address */ #ifdef CONFIG_PIC - tcb->picbase = bin->dspace; + tcb->dspace = bin->dspace; /* Re-initialize the task's initial state to account for the new PIC base */ diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c index aa00f50c7..b27dca935 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_load.c +++ b/nuttx/binfmt/libnxflat/libnxflat_load.c @@ -118,7 +118,7 @@ static void nxflat_reloc(struct nxflat_loadinfo_s *loadinfo, uint32 rl) * DSpace to hold information needed by ld.so at run time. */ - datastart = loadinfo->dspace; + datastart = (uint32)loadinfo->dspace->region; /* Get a pointer to the value that needs relocation in * DSpace. @@ -257,22 +257,22 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) * uninitialized ISpace memory. */ - loadinfo->dspace = (uint32)malloc(loadinfo->dsize); + loadinfo->dspace = (struct dspace_s *)malloc(SIZEOF_DSPACE_S(loadinfo->dsize)); if (loadinfo->dspace == 0) { bdbg("Failed to allocate DSpace\n"); ret = -ENOMEM; goto errout; } + loadinfo->dspace->crefs = 1; - bvdbg("Allocated DSpace (%d bytes) at %08x\n", - loadinfo->dsize, loadinfo->dspace); + bvdbg("Allocated DSpace (%d bytes) at %p\n", loadinfo->dsize, loadinfo->dspace); /* Now, read the data into allocated DSpace at doffset into the * allocated DSpace memory. */ - ret = nxflat_read(loadinfo, (char*)loadinfo->dspace, dreadsize, doffset); + ret = nxflat_read(loadinfo, (char*)loadinfo->dspace->region, dreadsize, doffset); if (ret < 0) { bdbg("Failed to read .data section: %d\n", ret); @@ -285,10 +285,10 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) /* Resolve the address of the relocation table. In the file, the * relocations should lie at the same offset as BSS. The current * value of relocstart is the offset from the beginning of the file. - * The following adjustment will convert it to an address in DSpace. + * The following adjustment will convert it to an address in dspace-> */ - reloctab = (uint32*)(loadinfo->relocstart + loadinfo->dspace - loadinfo->isize); + reloctab = (uint32*)(loadinfo->relocstart + (uint32)loadinfo->dspace->region - loadinfo->isize); bvdbg("Relocation table at 0x%p, reloccount=%d\n", reloctab, loadinfo->reloccount); @@ -304,7 +304,7 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) * in the file. */ - memset((void*)(loadinfo->dspace + loadinfo->datasize), + memset((void*)(loadinfo->dspace->region + loadinfo->datasize), 0, loadinfo->bsssize); return OK; diff --git a/nuttx/examples/nxflat/tests/Make.defs b/nuttx/examples/nxflat/tests/Make.defs index c4ec82c52..3b6400730 100644 --- a/nuttx/examples/nxflat/tests/Make.defs +++ b/nuttx/examples/nxflat/tests/Make.defs @@ -41,5 +41,5 @@ NXFLATCC = $(CC) NXFLATCFLAGS = $(CFLAGS) NXFLATLD = $(LD) -NXFLATLDFLAGS = +NXFLATLDFLAGS = -e main diff --git a/nuttx/include/nuttx/binfmt.h b/nuttx/include/nuttx/binfmt.h index 855cc3359..0c4238989 100644 --- a/nuttx/include/nuttx/binfmt.h +++ b/nuttx/include/nuttx/binfmt.h @@ -43,6 +43,7 @@ #include <nuttx/config.h> #include <sys/types.h> #include <nxflat.h> +#include <nuttx/sched.h> /**************************************************************************** * Pre-processor Definitions @@ -65,7 +66,7 @@ struct binary_s main_t entrypt; /* Entry point into a program module */ FAR void *ispace; /* Memory-mapped, I-space (.text) address */ - FAR void *dspace; /* Address of the allocated .data/.bss space */ + FAR struct dspace_s *dspace; /* Address of the allocated .data/.bss space */ size_t isize; /* Size of the I-space region (needed for munmap) */ size_t stacksize; /* Size of the stack in bytes (unallocated) */ }; diff --git a/nuttx/include/nuttx/nxflat.h b/nuttx/include/nuttx/nxflat.h index f78c79dcd..543f00e6d 100644 --- a/nuttx/include/nuttx/nxflat.h +++ b/nuttx/include/nuttx/nxflat.h @@ -40,7 +40,9 @@ * Included Files ****************************************************************************/ +#include <nuttx/config.h> #include <nxflat.h> +#include <nuttx/sched.h> /**************************************************************************** * Pre-processor Definitions @@ -61,29 +63,29 @@ struct nxflat_loadinfo_s * text section instance in the system for each module. */ - uint32 ispace; /* Address where hdr/text is loaded */ - uint32 entryoffs; /* Offset from ispace to entry point */ - uint32 isize; /* Size of ispace. */ + uint32 ispace; /* Address where hdr/text is loaded */ + uint32 entryoffs; /* Offset from ispace to entry point */ + uint32 isize; /* Size of ispace. */ /* Data Space (DSpace): This region contains all information that in referenced * as data (other than the stack which is separately allocated). There will be * a unique instance of DSpace (and stack) for each instance of a process. */ - uint32 dspace; /* Address where data/bss/etc. is loaded */ - uint32 datasize; /* Size of data segment in dspace */ - uint32 bsssize; /* Size of bss segment in dspace */ - uint32 stacksize; /* Size of stack (not allocated) */ - uint32 dsize; /* Size of dspace (may be large than parts) */ + struct dspace_s *dspace; /* Allocated D-Space (data/bss/etc) */ + uint32 datasize; /* Size of data segment in dspace */ + uint32 bsssize; /* Size of bss segment in dspace */ + uint32 stacksize; /* Size of stack (not allocated) */ + uint32 dsize; /* Size of dspace (may be large than parts) */ /* This is temporary memory where relocation records will be loaded. */ - uint32 relocstart; /* Start of array of struct flat_reloc */ - uint32 reloccount; /* Number of elements in reloc array */ + uint32 relocstart; /* Start of array of struct flat_reloc */ + uint32 reloccount; /* Number of elements in reloc array */ /* File descriptors */ - int filfd; /* Descriptor for the file being loaded */ + int filfd; /* Descriptor for the file being loaded */ const struct nxflat_hdr_s *header; /* A reference to the flat file header */ }; diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h index 520d73047..0c55dc1f8 100644 --- a/nuttx/include/nuttx/sched.h +++ b/nuttx/include/nuttx/sched.h @@ -161,6 +161,18 @@ typedef struct environ_s environ_t; # define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1) #endif +/* This structure describes a reference counted D-Space region */ + +struct dspace_s +{ + uint32 crefs; /* This is the number of pthreads that shared the + * the same D-Space. + */ + ubyte region[1]; /* Beginning of the allocated region */ +}; + +#define SIZEOF_DSPACE_S(n) (sizeof(struct dspace_s) - 1 + (n)) + /* This is the task control block (TCB) */ struct _TCB @@ -217,7 +229,7 @@ struct _TCB /* External Module Support ****************************************************/ #ifdef CONFIG_PIC - FAR void *picbase; /* Allocated area for .bss and .data */ + FAR struct dspace_s *dspace; /* Allocated area for .bss and .data */ #endif /* POSIX Thread Specific Data *************************************************/ diff --git a/nuttx/sched/sched_releasetcb.c b/nuttx/sched/sched_releasetcb.c index 567db2021..cd8e9c8c3 100644 --- a/nuttx/sched/sched_releasetcb.c +++ b/nuttx/sched/sched_releasetcb.c @@ -138,9 +138,16 @@ int sched_releasetcb(FAR _TCB *tcb) /* Delete the tasks's allocated DSpace region (external modules only) */ #ifdef CONFIG_PIC - if (tcb->picbase) + if (tcb->dspace) { - sched_free(tcb->picbase); + if (tcb->dspace->crefs <= 1) + { + sched_free(tcb->dspace); + } + else + { + tcb->dspace->crefs--; + } } #endif diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c index 25a85394a..83bae570b 100644 --- a/nuttx/sched/task_setup.c +++ b/nuttx/sched/task_setup.c @@ -143,6 +143,43 @@ static STATUS task_assignpid(FAR _TCB *tcb) } /**************************************************************************** + * Function: task_dupdspace + * + * Description: + * When a new task or thread is created from a PIC module, then that + * module (probably) intends the task or thread to execute in the same + * D-Space. This function will duplicate the D-Space for that purpose. + * + * Parameters: + * tcb - The TCB of the new task. + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_PIC +static inline void task_dupdspace(FAR _TCB *tcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (rtcb->dspace != NULL) + { + /* Copy the D-Space structure reference and increment the reference + * count on the memory. The D-Space memory will persist until the + * last thread exits (see sched_releasetcb()). + */ + + tcb->dspace = rtcb->dspace; + tcb->dspace->crefs++; + } +} +#else +# define task_dupdspace(tcb) +#endif + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -150,11 +187,11 @@ static STATUS task_assignpid(FAR _TCB *tcb) * Name: task_schedsetup * * Description: - * This functions initializes a Task Control Block (TCB) - * in preparation for starting a new thread. + * This functions initializes a Task Control Block (TCB) in preparation + * for starting a new thread. * - * task_schedsetup() is called from task_init(), - * task_start(), and pthread_create(); + * task_schedsetup() is called from task_init(), task_start(), and + * pthread_create(); * * Input Parameters: * tcb - Address of the new task's TCB @@ -165,8 +202,8 @@ static STATUS task_assignpid(FAR _TCB *tcb) * Return Value: * OK on success; ERROR on failure. * - * This function can only failure is it is unable to assign - * a new, unique task ID to the TCB (errno is not set). + * This function can only failure is it is unable to assign a new, unique + * task ID to the TCB (errno is not set). * ****************************************************************************/ @@ -204,6 +241,13 @@ STATUS task_schedsetup(FAR _TCB *tcb, int priority, tcb->task_state = TSTATE_TASK_INVALID; + /* Clone the parent tasks D-Space (if it was running PIC). This + * must be done before calling up_initial_state() so that the + * state setup will take the PIC address base into account. + */ + + task_dupdspace(tcb); + /* Initialize the processor-specific portion of the TCB */ up_initial_state(tcb); diff --git a/nuttx/sched/wd_start.c b/nuttx/sched/wd_start.c index ea9117459..a406b3f30 100644 --- a/nuttx/sched/wd_start.c +++ b/nuttx/sched/wd_start.c @@ -158,9 +158,7 @@ STATUS wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...) /* Save the data in the watchdog structure */ wdog->func = wdentry; /* Function to execute when delay expires */ -#ifdef CONFIG_PIC up_getpicbase(&wdog->picbase); -#endif wdog->argc = argc; va_start(ap, argc); |