forked from nuttx/nuttx-update
Integrate PIC support into context switching
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1900 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
2afd39df07
commit
f876eb552a
13 changed files with 139 additions and 33 deletions
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -41,5 +41,5 @@ NXFLATCC = $(CC)
|
|||
NXFLATCFLAGS = $(CFLAGS)
|
||||
|
||||
NXFLATLD = $(LD)
|
||||
NXFLATLDFLAGS =
|
||||
NXFLATLDFLAGS = -e main
|
||||
|
||||
|
|
|
@ -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) */
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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 *************************************************/
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -142,6 +142,43 @@ static STATUS task_assignpid(FAR _TCB *tcb)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue