1
0
Fork 0
forked from nuttx/nuttx-update

P-code BINFMT: Add logic to pass information from the binfmt logic to the P-code interpreter. This includes some extension to the binfmt interfaces.

This commit is contained in:
Gregory Nutt 2014-05-08 16:58:10 -06:00
parent 93629d7192
commit e18844de32
11 changed files with 205 additions and 39 deletions

View file

@ -289,7 +289,7 @@ On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appro
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int unload_module(FAR const struct binary_s *bin);
int unload_module(FAR struct binary_s *bin);
</pre></ul>
<p><b>Description:</b></p>
<ul>

View file

@ -655,7 +655,7 @@ cat ../syscall/syscall.csv ../libc/lib.csv | sort >tmp.csv
</p>
</ul>
<p><b><code>int unload_module(FAR const struct binary_s *bin)</code></b>
<p><b><code>int unload_module(FAR struct binary_s *bin)</code></b>
<ul>
<p><b>Description:</b>
Unload a (non-executing) module from memory. If the module has

View file

@ -100,7 +100,9 @@ int dump_module(FAR const struct binary_s *bin)
bdbg(" addrenv: %p\n", bin->addrenv);
#endif
bdbg(" stacksize: %d\n", bin->stacksize);
bdbg(" unload: %p\n", bin->unload);
}
return OK;
}
#endif

View file

@ -72,7 +72,7 @@
* Description:
* Set the default priority of the module to be loaded. This may be
* changed (1) by the actions of the binary format's load() method if
* the binary format contains priority informaition, or (2) by the user
* the binary format contains priority information, or (2) by the user
* between calls to load_module() and exec_module().
*
* Returned Value:
@ -143,6 +143,10 @@ static int load_absmodule(FAR struct binary_s *bin)
/* Successfully loaded -- break out with ret == 0 */
bvdbg("Successfully loaded module %s\n", bin->filename);
/* Save the unload method for use by unload_module */
bin->unload = binfmt->unload;
dump_module(bin);
break;
}

View file

@ -84,7 +84,7 @@
****************************************************************************/
#ifdef CONFIG_BINFMT_CONSTRUCTORS
static inline int exec_dtors(FAR const struct binary_s *binp)
static inline int exec_dtors(FAR struct binary_s *binp)
{
binfmt_dtor_t *dtor = binp->dtors;
#ifdef CONFIG_ADDRENV
@ -136,7 +136,7 @@ static inline int exec_dtors(FAR const struct binary_s *binp)
* been started (via exec_module) and has not exited, calling this will
* be fatal.
*
* However, this function must be called after the module exist. How
* However, this function must be called after the module exits. How
* this is done is up to your logic. Perhaps you register it to be
* called by on_exit()?
*
@ -147,18 +147,29 @@ static inline int exec_dtors(FAR const struct binary_s *binp)
*
****************************************************************************/
int unload_module(FAR const struct binary_s *binp)
int unload_module(FAR struct binary_s *binp)
{
#ifdef CONFIG_BINFMT_CONSTRUCTORS
int ret;
#endif
int i;
if (binp)
{
/* Execute C++ desctructors */
/* Perform any format-specific unload operations */
if (binp->unload)
{
ret = binp->unload(binp);
if (ret < 0)
{
bdbg("binp->unload() failed: %d\n", ret);
set_errno(-ret);
return ERROR;
}
}
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/* Execute C++ destructors */
ret = exec_dtors(binp);
if (ret < 0)
{

View file

@ -72,6 +72,7 @@ static struct binfmt_s g_builtin_binfmt =
{
NULL, /* next */
builtin_loadbinary, /* load */
NULL, /* unload */
};
/****************************************************************************

View file

@ -95,6 +95,7 @@ static struct binfmt_s g_elfbinfmt =
{
NULL, /* next */
elf_loadbinary, /* load */
NULL, /* unload */
};
/****************************************************************************

View file

@ -91,6 +91,7 @@ static struct binfmt_s g_nxflatbinfmt =
{
NULL, /* next */
nxflat_loadbinary, /* load */
NULL, /* unload */
};
/****************************************************************************

View file

@ -47,6 +47,7 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/poff.h>
#include <nuttx/fs/ramdisk.h>
#include <nuttx/binfmt/binfmt.h>
@ -62,24 +63,28 @@
*/
#if CONFIG_NFILE_DESCRIPTORS < 1
# error "You must provide file descriptors via CONFIG_NFILE_DESCRIPTORS in your configuration file"
# error You must provide file descriptors via CONFIG_NFILE_DESCRIPTORS in your configuration file
#endif
#ifdef CONFIG_BINFMT_DISABLE
# error "The binary loader is disabled (CONFIG_BINFMT_DISABLE)!"
# error The binary loader is disabled (CONFIG_BINFMT_DISABLE)!
#endif
#ifndef CONFIG_PCODE
# error "You must select CONFIG_PCODE in your configuration file"
# error You must select CONFIG_PCODE in your configuration file
#endif
#ifndef CONFIG_SCHED_ONEXIT
# error CONFIG_SCHED_ONEXIT is required
#endif
#ifdef CONFIG_PCODE_TEST_FS
# ifndef CONFIG_FS_ROMFS
# error "You must select CONFIG_FS_ROMFS in your configuration file"
# error You must select CONFIG_FS_ROMFS in your configuration file
# endif
# ifdef CONFIG_DISABLE_MOUNTPOINT
# error "You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file"
# error You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file
# endif
# ifndef CONFIG_PCODE_TEST_DEVMINOR
@ -104,7 +109,19 @@
* Private Function Prototypes
****************************************************************************/
static int pcode_loadbinary(FAR struct binary_s *binp);
struct binfmt_handoff_s
{
sem_t exclsem; /* Supports mutually exclusive access */
FAR struct binary_s *binp; /* Binary format being handed off */
FAR char *fullpath; /* Full path to the P-Code file */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int pcode_load(FAR struct binary_s *binp);
static int pcode_unload(FAR struct binary_s *binp);
/****************************************************************************
* Private Data
@ -112,10 +129,13 @@ static int pcode_loadbinary(FAR struct binary_s *binp);
static struct binfmt_s g_pcode_binfmt =
{
NULL, /* next */
pcode_loadbinary, /* load */
NULL, /* next */
pcode_load, /* load */
pcode_unload, /* unload */
};
struct binfmt_handoff_s g_pcode_handoff;
#ifdef CONFIG_PCODE_TEST_FS
# include "romfs.h"
#endif
@ -181,17 +201,70 @@ static int pcode_mount_testfs(void)
#endif
/****************************************************************************
* Name: pcode_proxy
* Name: pcode_onexit
*
* Description:
* This is the proxy program that runs and starts the P-Code interpreter.
*
****************************************************************************/
#ifndef CONFIG_NUTTX_KERNEL
static void pcode_onexit(int exitcode, FAR void *arg)
{
FAR struct binary_s *binp = (FAR struct binary_s *)arg;
DEBUGASSERT(binp);
/* And unload the module */
unload_module(binp);
}
#endif
/****************************************************************************
* Name: pcode_proxy
*
* Description:
* This is the proxy program that runs and starts the P-Code interpreter.
*
* REVISIT: There are issues here when CONFIG_NUTTX_KERNEL is selected.
*
****************************************************************************/
#ifndef CONFIG_NUTTX_KERNEL
static int pcode_proxy(int argc, char **argv)
{
/* REVISIT: There are issues here when CONFIG_NUTTX_KERNEL is selected. */
FAR struct binary_s *binp;
FAR char *fullpath;
int ret;
/* Get the struct binary_s instance from the handoff structure */
binp = g_pcode_handoff.binp;
g_pcode_handoff.binp = NULL;
fullpath = g_pcode_handoff.fullpath;
g_pcode_handoff.fullpath = NULL;
sem_post(&g_pcode_handoff.exclsem);
DEBUGASSERT(binp && fullpath);
bvdbg("Executing %s\n", fullpath);
/* Set-up the on-exit handler that will unload the module on exit */
ret = on_exit(pcode_onexit, binp);
if (ret < 0)
{
bdbg("ERROR: on_exit failed: %d\n", errno);
return EXIT_FAILURE;
}
/* Load the P-code file and execute it */
/* We don't need the fullpath now */
kfree(fullpath);
/* Execute the P-code file and execute it */
bdbg("ERROR: Not implemented\n");
return EXIT_FAILURE;
@ -201,14 +274,14 @@ static int pcode_proxy(int argc, char **argv)
#endif
/****************************************************************************
* Name: pcode_loadbinary
* Name: pcode_load
*
* Description:
* Verify that the file is an pcode binary.
* Verify that the file is a pcode binary.
*
****************************************************************************/
static int pcode_loadbinary(struct binary_s *binp)
static int pcode_load(struct binary_s *binp)
{
FAR struct poff_fileheader_s hdr;
FAR uint8_t *ptr;
@ -262,7 +335,7 @@ static int pcode_loadbinary(struct binary_s *binp)
DEBUGASSERT(nread > 0 && nread <=remaining);
remaining -= nread;
ptr += nread;
}
}
}
#ifdef CONFIG_PCODE_DUMPBUFFER
@ -286,7 +359,36 @@ static int pcode_loadbinary(struct binary_s *binp)
binp->stacksize = CONFIG_PCODE_STACKSIZE;
binp->priority = CONFIG_PCODE_PRIORITY;
/* Successfully identified a p-code binary */
/* Get exclusive access to the p-code handoff structure */
do
{
ret = sem_wait(&g_pcode_handoff.exclsem);
DEBUGASSERT(ret == OK || errno == EINTR);
}
while (ret < 0);
/* Save the data that we need to handoff to the child thread */
DEBUGASSERT(g_pcode_handoff.binp == NULL &&
g_pcode_handoff.fullpath == NULL);
/* Duplicate the full path to the binary */
g_pcode_handoff.fullpath = strdup(binp->filename);
if (!g_pcode_handoff.fullpath)
{
bdbg("ERROR: Failed to duplicate the full path: %d\n",
binp->filename);
sem_post(&g_pcode_handoff.exclsem);
ret = -ENOMEM;
goto errout_with_fd;
}
g_pcode_handoff.binp = binp;
/* Successfully identified (but not really loaded) a p-code binary */
ret = OK;
@ -295,6 +397,29 @@ errout_with_fd:
return ret;
}
/****************************************************************************
* Name: pcode_unload
*
* Description:
* Called when the pcode binary is unloaded. This is necessary primarily
* to handler error conditions where unload_module is called after
* pcode_load without having executed the P-Code module.
*
****************************************************************************/
static int pcode_unload(struct binary_s *binp)
{
/* Increment the semaphore count back to one if appropriate */
if (g_pcode_handoff.binp)
{
g_pcode_handoff.binp = NULL;
sem_post(&g_pcode_handoff.exclsem);
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -318,6 +443,10 @@ int pcode_initialize(void)
{
int ret;
/* Initialize globals */
sem_init(&g_pcode_handoff.exclsem, 0, 1);
/* Mount the test file system */
ret = pcode_mount_testfs();
@ -378,6 +507,10 @@ void pcode_uninitialize(void)
UNUSED(errval);
}
#endif
/* Uninitialize globals */
sem_destroy(&g_pcode_handoff.exclsem);
}
#endif /* CONFIG_PCODE */

View file

@ -136,14 +136,27 @@ struct binary_s
uint8_t priority; /* Task execution priority */
size_t stacksize; /* Size of the stack in bytes (unallocated) */
/* Unload module callback */
CODE int (*unload)(FAR struct binary_s *bin);
};
/* This describes one binary format handler */
struct binfmt_s
{
FAR struct binfmt_s *next; /* Supports a singly-linked list */
int (*load)(FAR struct binary_s *bin); /* Verify and load binary into memory */
/* Supports a singly-linked list */
FAR struct binfmt_s *next;
/* Verify and load binary into memory */
CODE int (*load)(FAR struct binary_s *bin);
/* Unload module callback */
CODE int (*unload)(FAR struct binary_s *bin);
};
/****************************************************************************
@ -224,7 +237,7 @@ int load_module(FAR struct binary_s *bin);
*
****************************************************************************/
int unload_module(FAR const struct binary_s *bin);
int unload_module(FAR struct binary_s *bin);
/****************************************************************************
* Name: exec_module

View file

@ -47,7 +47,8 @@
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
extern "C"
{
#else
#define EXTERN extern
#endif
@ -126,17 +127,16 @@ struct timespec; /* Defined in time.h */
/* Counting Semaphore Interfaces (based on POSIX APIs) */
EXTERN int sem_init(FAR sem_t *sem, int pshared, unsigned int value);
EXTERN int sem_destroy(FAR sem_t *sem);
EXTERN FAR sem_t *sem_open(FAR const char *name, int oflag, ...);
EXTERN int sem_close(FAR sem_t *sem);
EXTERN int sem_unlink(FAR const char *name);
EXTERN int sem_wait(FAR sem_t *sem);
EXTERN int sem_timedwait(FAR sem_t *sem,
FAR const struct timespec *abstime);
EXTERN int sem_trywait(FAR sem_t *sem);
EXTERN int sem_post(FAR sem_t *sem);
EXTERN int sem_getvalue(FAR sem_t *sem, FAR int *sval);
int sem_init(FAR sem_t *sem, int pshared, unsigned int value);
int sem_destroy(FAR sem_t *sem);
FAR sem_t *sem_open(FAR const char *name, int oflag, ...);
int sem_close(FAR sem_t *sem);
int sem_unlink(FAR const char *name);
int sem_wait(FAR sem_t *sem);
int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime);
int sem_trywait(FAR sem_t *sem);
int sem_post(FAR sem_t *sem);
int sem_getvalue(FAR sem_t *sem, FAR int *sval);
#undef EXTERN
#ifdef __cplusplus