diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-05-08 16:58:10 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-05-08 16:58:10 -0600 |
commit | faa1f56b5d4ea2e756b8ab44563d1fb68f7595e1 (patch) | |
tree | 8a50251f2e5378bb39e1d7d88cd3969bce0ab9db | |
parent | af5f00732d9551dca5040b18b822393ef27081c1 (diff) | |
download | px4-nuttx-faa1f56b5d4ea2e756b8ab44563d1fb68f7595e1.tar.gz px4-nuttx-faa1f56b5d4ea2e756b8ab44563d1fb68f7595e1.tar.bz2 px4-nuttx-faa1f56b5d4ea2e756b8ab44563d1fb68f7595e1.zip |
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.
-rw-r--r-- | apps/system/i2c/i2c_get.c | 5 | ||||
-rw-r--r-- | nuttx/Documentation/NuttXBinfmt.html | 2 | ||||
-rw-r--r-- | nuttx/Documentation/NuttXNxFlat.html | 2 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_dumpmodule.c | 2 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_loadmodule.c | 6 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_unloadmodule.c | 23 | ||||
-rw-r--r-- | nuttx/binfmt/builtin.c | 1 | ||||
-rw-r--r-- | nuttx/binfmt/elf.c | 1 | ||||
-rw-r--r-- | nuttx/binfmt/nxflat.c | 1 | ||||
-rw-r--r-- | nuttx/binfmt/pcode.c | 161 | ||||
-rw-r--r-- | nuttx/include/nuttx/binfmt/binfmt.h | 19 | ||||
-rw-r--r-- | nuttx/include/semaphore.h | 24 |
12 files changed, 208 insertions, 39 deletions
diff --git a/apps/system/i2c/i2c_get.c b/apps/system/i2c/i2c_get.c index f2c16d4a7..c30fa9a24 100644 --- a/apps/system/i2c/i2c_get.c +++ b/apps/system/i2c/i2c_get.c @@ -46,7 +46,7 @@ #include "i2ctool.h" /**************************************************************************** - * Definitions + * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** @@ -108,6 +108,7 @@ int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) { return ERROR; } + argndx += nargs; } @@ -217,6 +218,7 @@ int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, msg[1].addr = i2ctool->addr; msg[1].flags = I2C_M_READ; + if (i2ctool->width == 8) { msg[1].buffer = &u.data8; @@ -254,5 +256,6 @@ int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev, *result = u.data16; } } + return ret; } diff --git a/nuttx/Documentation/NuttXBinfmt.html b/nuttx/Documentation/NuttXBinfmt.html index 3f3bdbc0a..2f4f6e425 100644 --- a/nuttx/Documentation/NuttXBinfmt.html +++ b/nuttx/Documentation/NuttXBinfmt.html @@ -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> diff --git a/nuttx/Documentation/NuttXNxFlat.html b/nuttx/Documentation/NuttXNxFlat.html index 2036cc723..41b2a19ee 100644 --- a/nuttx/Documentation/NuttXNxFlat.html +++ b/nuttx/Documentation/NuttXNxFlat.html @@ -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 diff --git a/nuttx/binfmt/binfmt_dumpmodule.c b/nuttx/binfmt/binfmt_dumpmodule.c index d320bc830..c1ea7fac0 100644 --- a/nuttx/binfmt/binfmt_dumpmodule.c +++ b/nuttx/binfmt/binfmt_dumpmodule.c @@ -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 diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c index 8db96a49b..00e199b8e 100644 --- a/nuttx/binfmt/binfmt_loadmodule.c +++ b/nuttx/binfmt/binfmt_loadmodule.c @@ -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; } diff --git a/nuttx/binfmt/binfmt_unloadmodule.c b/nuttx/binfmt/binfmt_unloadmodule.c index 0e87d743f..02826444c 100644 --- a/nuttx/binfmt/binfmt_unloadmodule.c +++ b/nuttx/binfmt/binfmt_unloadmodule.c @@ -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) { diff --git a/nuttx/binfmt/builtin.c b/nuttx/binfmt/builtin.c index c532d056f..4731d8815 100644 --- a/nuttx/binfmt/builtin.c +++ b/nuttx/binfmt/builtin.c @@ -72,6 +72,7 @@ static struct binfmt_s g_builtin_binfmt = { NULL, /* next */ builtin_loadbinary, /* load */ + NULL, /* unload */ }; /**************************************************************************** diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c index 6c84ca0e1..575b498bb 100644 --- a/nuttx/binfmt/elf.c +++ b/nuttx/binfmt/elf.c @@ -95,6 +95,7 @@ static struct binfmt_s g_elfbinfmt = { NULL, /* next */ elf_loadbinary, /* load */ + NULL, /* unload */ }; /**************************************************************************** diff --git a/nuttx/binfmt/nxflat.c b/nuttx/binfmt/nxflat.c index 2d06aa7d9..cd7a6828a 100644 --- a/nuttx/binfmt/nxflat.c +++ b/nuttx/binfmt/nxflat.c @@ -91,6 +91,7 @@ static struct binfmt_s g_nxflatbinfmt = { NULL, /* next */ nxflat_loadbinary, /* load */ + NULL, /* unload */ }; /**************************************************************************** diff --git a/nuttx/binfmt/pcode.c b/nuttx/binfmt/pcode.c index af69c93e1..0a187ec81 100644 --- a/nuttx/binfmt/pcode.c +++ b/nuttx/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_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; @@ -296,6 +398,29 @@ errout_with_fd: } /**************************************************************************** + * 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 */ diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h index 7eaa1248f..8750e7215 100644 --- a/nuttx/include/nuttx/binfmt/binfmt.h +++ b/nuttx/include/nuttx/binfmt/binfmt.h @@ -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 diff --git a/nuttx/include/semaphore.h b/nuttx/include/semaphore.h index 46f2c06ea..99f067824 100644 --- a/nuttx/include/semaphore.h +++ b/nuttx/include/semaphore.h @@ -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 |