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:
parent
93629d7192
commit
e18844de32
11 changed files with 205 additions and 39 deletions
|
@ -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 <:nuttx/binfmt/binfmt.h>
|
||||
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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -72,6 +72,7 @@ static struct binfmt_s g_builtin_binfmt =
|
|||
{
|
||||
NULL, /* next */
|
||||
builtin_loadbinary, /* load */
|
||||
NULL, /* unload */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -95,6 +95,7 @@ static struct binfmt_s g_elfbinfmt =
|
|||
{
|
||||
NULL, /* next */
|
||||
elf_loadbinary, /* load */
|
||||
NULL, /* unload */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -91,6 +91,7 @@ static struct binfmt_s g_nxflatbinfmt =
|
|||
{
|
||||
NULL, /* next */
|
||||
nxflat_loadbinary, /* load */
|
||||
NULL, /* unload */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
163
binfmt/pcode.c
163
binfmt/pcode.c
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue