summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/arch/arm/include/arm/irq.h6
-rw-r--r--nuttx/arch/arm/include/cortexm3/irq.h6
-rw-r--r--nuttx/arch/arm/src/arm/up_initialstate.c15
-rw-r--r--nuttx/arch/arm/src/cortexm3/up_initialstate.c15
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c2
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_load.c16
-rw-r--r--nuttx/examples/nxflat/tests/Make.defs2
-rw-r--r--nuttx/include/nuttx/binfmt.h3
-rw-r--r--nuttx/include/nuttx/nxflat.h24
-rw-r--r--nuttx/include/nuttx/sched.h14
-rw-r--r--nuttx/sched/sched_releasetcb.c11
-rw-r--r--nuttx/sched/task_setup.c56
-rw-r--r--nuttx/sched/wd_start.c2
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);