summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/system/i2c/i2c_get.c5
-rw-r--r--nuttx/Documentation/NuttXBinfmt.html2
-rw-r--r--nuttx/Documentation/NuttXNxFlat.html2
-rw-r--r--nuttx/binfmt/binfmt_dumpmodule.c2
-rw-r--r--nuttx/binfmt/binfmt_loadmodule.c6
-rw-r--r--nuttx/binfmt/binfmt_unloadmodule.c23
-rw-r--r--nuttx/binfmt/builtin.c1
-rw-r--r--nuttx/binfmt/elf.c1
-rw-r--r--nuttx/binfmt/nxflat.c1
-rw-r--r--nuttx/binfmt/pcode.c161
-rw-r--r--nuttx/include/nuttx/binfmt/binfmt.h19
-rw-r--r--nuttx/include/semaphore.h24
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 &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>
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