summaryrefslogtreecommitdiff
path: root/nuttx/sched
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-08-30 13:27:23 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-08-30 13:27:23 -0600
commit6589a0ca8924c1166152a5386e30ea49cd266f51 (patch)
tree5c4eb249cbbee7db43a5ea13779d3dc72825612d /nuttx/sched
parent7af9398910df9a007a16856956fd7754fa6e89ff (diff)
downloadpx4-nuttx-6589a0ca8924c1166152a5386e30ea49cd266f51.tar.gz
px4-nuttx-6589a0ca8924c1166152a5386e30ea49cd266f51.tar.bz2
px4-nuttx-6589a0ca8924c1166152a5386e30ea49cd266f51.zip
Add configuration options to start the system from a program on a file system
Diffstat (limited to 'nuttx/sched')
-rw-r--r--nuttx/sched/Kconfig52
-rw-r--r--nuttx/sched/init/os_bringup.c274
2 files changed, 268 insertions, 58 deletions
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index c3f7dbbf2..02f35d5a0 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -218,6 +218,26 @@ endmenu # Clocks and Timers
menu "Tasks and Scheduling"
+choice
+ prompt "Initialization Task"
+ default INIT_ENTRYPOINT if !BUILD_KERNEL
+ default INIT_FILEPATH if BUILD_KERNEL && !BINFMT_DISABLE
+ default INIT_NONE if BUILD_KERNEL && BINFMT_DISABLE
+
+config INIT_NONE
+ bool
+
+config INIT_ENTRYPOINT
+ bool "Via application entry point"
+ depends on !BUILD_KERNEL
+
+config INIT_FILEPATH
+ bool "Via executable file"
+ depends on !BINFMT_DISABLE
+
+endchoice # Initialization task
+
+if INIT_ENTRYPOINT
config USER_ENTRYPOINT
string "Application entry point"
default "main"
@@ -226,6 +246,38 @@ config USER_ENTRYPOINT
applications this is of the form 'app_main' where 'app' is the application
name. If not defined, USER_ENTRYPOINT defaults to "main".
+endif # INIT_ENTRYPOINT
+
+if INIT_FILEPATH
+
+config USER_INITPATH
+ string "Application initialization path"
+ default "/bin/init"
+ ---help---
+ The name of the entry point for user applications. For the example
+ applications this is of the form 'app_main' where 'app' is the application
+ name. If not defined, USER_ENTRYPOINT defaults to "main".
+
+config INIT_SYMTAB
+ string "Symbol table"
+ default "NULL"
+ ---help---
+ The name of othe global array that holds the exported symbol table.
+ The special string "NULL" may be provided if there is no symbol
+ table. Quotation marks will be stripped when config.h is generated.
+
+config INIT_NEXPORTS
+ string "Symbol table size"
+ default "0"
+ ---help---
+ The size of the symbol table. NOTE that is is logically a numeric
+ value but is represent by a string. That allows you to put
+ sizeof(something) or a macro or a global variable name for the
+ symbol table size. Quotation marks will be stripped when config.h
+ is generated.
+
+endif # INIT_FILEPATH
+
config RR_INTERVAL
int "Round robin timeslice (MSEC)"
default 0
diff --git a/nuttx/sched/init/os_bringup.c b/nuttx/sched/init/os_bringup.c
index 150aa4481..b084bd1b0 100644
--- a/nuttx/sched/init/os_bringup.c
+++ b/nuttx/sched/init/os_bringup.c
@@ -52,6 +52,7 @@
#include <nuttx/wqueue.h>
#include <nuttx/kthread.h>
#include <nuttx/userspace.h>
+#include <nuttx/binfmt/binfmt.h>
#ifdef CONFIG_PAGING
# include "paging/paging.h"
@@ -62,6 +63,59 @@
* Pre-processor Definitions
****************************************************************************/
+/* Configuration */
+
+#if defined(CONFIG_INIT_NONE)
+ /* Kconfig logic will set CONFIG_INIT_NONE if dependencies are not met */
+
+# error No initialization mechanism selected (CONFIG_INIT_NONE)
+
+#else
+# if !defined(CONFIG_INIT_ENTRYPOINT) && !defined(CONFIG_INIT_FILEPATH)
+ /* For backward compatibility with older defconfig files when this was
+ * the way things were done.
+ */
+
+# define CONFIG_INIT_ENTRYPOINT 1
+# endif
+
+# if defined(CONFIG_INIT_ENTRYPOINT)
+ /* Initialize by starting a task at an entry point */
+
+# ifndef CONFIG_USER_ENTRYPOINT
+ /* Entry point name must have been provided */
+
+# error CONFIG_USER_ENTRYPOINT must be defined
+# endif
+
+# elif defined(CONFIG_INIT_FILEPATH)
+ /* Initialize by running an initialization program in the file system.
+ * Presumably the user has configured a board initialization function
+ * that will mount the file system containing the initialization
+ * program.
+ */
+
+# ifndef CONFIG_BOARD_INITIALIZE
+# warning You probably need CONFIG_BOARD_INITIALIZE to mount the file system
+# endif
+
+# ifndef CONFIG_USER_INITPATH
+ /* Path to the initialization program must have been provided */
+
+# error CONFIG_USER_INITPATH must be defined
+# endif
+
+# if !defined(CONFIG_INIT_SYMTAB) || !defined(CONFIG_INIT_NEXPORTS)
+ /* No symbol information... assume no symbol table is available */
+
+# undef CONFIG_INIT_SYMTAB
+# undef CONFIG_INIT_NEXPORTS
+# define CONFIG_INIT_SYMTAB NULL
+# define CONFIG_INIT_NEXPORTS 0
+# endif
+# endif
+#endif
+
/* If NuttX is built as a separately compiled module, then the config.h header
* file should contain the address of the entry point (or path to the file)
* that will perform the application-level initialization.
@@ -103,28 +157,12 @@
****************************************************************************/
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: os_bringup
+ * Name: os_pgworker
*
* Description:
- * Start all initial system tasks. This does the "system bring-up" after
- * the conclusion of basic OS initialization. These initial system tasks
- * may include:
- *
- * - pg_worker: The page-fault worker thread (only if CONFIG_PAGING is
- * defined.
- * - work_thread: The work thread. This general thread can be used to
- * perform most any kind of queued work. Its primary
- * function is to serve as the "bottom half" of device
- * drivers.
- *
- * And the main application entry point:
- * symbols:
- *
- * - USER_ENTRYPOINT: This is the default user application entry point.
+ * Start the page fill worker kernel thread that will resolve page faults.
+ * This should always be the first thread started because it may have to
+ * resolve page faults in other threads
*
* Input Parameters:
* None
@@ -134,42 +172,49 @@
*
****************************************************************************/
-int os_bringup(void)
+#ifdef CONFIG_PAGING
+static inline void os_pgworker(void)
{
- int taskid;
-
- /* Setup up the initial environment for the idle task. At present, this
- * may consist of only the initial PATH variable. The PATH variable is
- * (probably) not used by the IDLE task. However, the environment
- * containing the PATH variable will be inherited by all of the threads
- * created by the IDLE task.
- */
-
-#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL)
- (void)setenv("PATH", CONFIG_PATH_INITIAL, 1);
-#endif
-
/* Start the page fill worker kernel thread that will resolve page faults.
* This should always be the first thread started because it may have to
* resolve page faults in other threads
*/
-#ifdef CONFIG_PAGING
svdbg("Starting paging thread\n");
g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO,
CONFIG_PAGING_STACKSIZE,
(main_t)pg_worker, (FAR char * const *)NULL);
DEBUGASSERT(g_pgworker > 0);
-#endif
+}
- /* Start the worker thread that will serve as the device driver "bottom-
- * half" and will perform misc garbage clean-up.
- */
+#else /* CONFIG_PAGING */
+# define os_pgworker()
+
+#endif /* CONFIG_PAGING */
+
+/****************************************************************************
+ * Name: os_workqueues
+ *
+ * Description:
+ * Start the worker threads that service the work queues.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
#ifdef CONFIG_SCHED_WORKQUEUE
-#ifdef CONFIG_SCHED_HPWORK
+static inline void os_workqueues(void)
+{
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_SCHED_USRWORK)
+ int taskid;
+#endif
+#ifdef CONFIG_SCHED_HPWORK
#ifdef CONFIG_SCHED_LPWORK
svdbg("Starting high-priority kernel worker thread\n");
#else
@@ -178,7 +223,8 @@ int os_bringup(void)
g_work[HPWORK].pid = KERNEL_THREAD(HPWORKNAME, CONFIG_SCHED_WORKPRIORITY,
CONFIG_SCHED_WORKSTACKSIZE,
- (main_t)work_hpthread, (FAR char * const *)NULL);
+ (main_t)work_hpthread,
+ (FAR char * const *)NULL);
DEBUGASSERT(g_work[HPWORK].pid > 0);
/* Start a lower priority worker thread for other, non-critical continuation
@@ -191,7 +237,8 @@ int os_bringup(void)
g_work[LPWORK].pid = KERNEL_THREAD(LPWORKNAME, CONFIG_SCHED_LPWORKPRIORITY,
CONFIG_SCHED_LPWORKSTACKSIZE,
- (main_t)work_lpthread, (FAR char * const *)NULL);
+ (main_t)work_lpthread,
+ (FAR char * const *)NULL);
DEBUGASSERT(g_work[LPWORK].pid > 0);
#endif /* CONFIG_SCHED_LPWORK */
@@ -203,29 +250,40 @@ int os_bringup(void)
DEBUGASSERT(USERSPACE->work_usrstart != NULL);
taskid = USERSPACE->work_usrstart();
DEBUGASSERT(taskid > 0);
+ UNUSED(taskid);
#endif
+}
-#endif /* CONFIG_SCHED_WORKQUEUE */
+#else /* CONFIG_SCHED_WORKQUEUE */
+# define os_workqueues()
- /* Once the operating system has been initialized, the system must be
- * started by spawning the user init thread of execution. This is the
- * first user-mode thead.
- */
+#endif /* CONFIG_SCHED_WORKQUEUE */
- svdbg("Starting init thread\n");
+/****************************************************************************
+ * Name: os_init_thread
+ *
+ * Description:
+ * Start the application initialization thread.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
- /* Perform any last-minute, board-specific initialization, if so
- * configured.
- */
+#if defined(CONFIG_INIT_ENTRYPOINT)
+static inline void os_init_thread(void)
+{
+ int taskid;
-#ifdef CONFIG_BOARD_INITIALIZE
- board_initialize();
-#endif
+ svdbg("Starting init thread\n");
- /* Start the default application. In a flat build, this is entrypoint
- * is given by the definitions, CONFIG_USER_ENTRYPOINT. In the kernel
- * build, however, we must get the address of the entrypoint from the
- * header at the beginning of the user-space blob.
+ /* Start the application initialization ask. In a flat build, this is
+ * entrypoint is given by the definitions, CONFIG_USER_ENTRYPOINT. In
+ * the protected build, however, we must get the address of the
+ * entrypoint from the header at the beginning of the user-space blob.
*/
#ifdef CONFIG_BUILD_PROTECTED
@@ -240,6 +298,106 @@ int os_bringup(void)
(FAR char * const *)NULL);
#endif
ASSERT(taskid > 0);
+}
+
+#elif defined(CONFIG_INIT_FILEPATH)
+static inline void os_init_thread(void)
+{
+ int ret;
+
+ svdbg("Starting init task: %s\n", CONFIG_USER_INITPATH);
+
+ ret = exec(CONFIG_USER_INITPATH, NULL, CONFIG_INIT_SYMTAB,
+ CONFIG_INIT_NEXPORTS);
+ ASSERT(ret >= 0);
+}
+
+#elif defined(CONFIG_INIT_NONE)
+# define os_init_thread()
+
+#else
+# error "Cannot start initialization thread"
+
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: os_bringup
+ *
+ * Description:
+ * Start all initial system tasks. This does the "system bring-up" after
+ * the conclusion of basic OS initialization. These initial system tasks
+ * may include:
+ *
+ * - pg_worker: The page-fault worker thread (only if CONFIG_PAGING is
+ * defined.
+ * - work_thread: The work thread. This general thread can be used to
+ * perform most any kind of queued work. Its primary
+ * function is to serve as the "bottom half" of device
+ * drivers.
+ *
+ * And the main application entry point:
+ * symbols, either:
+ *
+ * - CONFIG_USER_ENTRYPOINT: This is the default user application entry
+ * point, or
+ * - CONFIG_USER_INITPATH: The full path to the location in a mounted
+ * file system where we can expect to find the
+ * initialization program. Presumably, this file system
+ * was mounted by board-specific logic when
+ * board_initialize() was called.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+int os_bringup(void)
+{
+ /* Setup up the initial environment for the idle task. At present, this
+ * may consist of only the initial PATH variable. The PATH variable is
+ * (probably) not used by the IDLE task. However, the environment
+ * containing the PATH variable will be inherited by all of the threads
+ * created by the IDLE task.
+ */
+
+#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL)
+ (void)setenv("PATH", CONFIG_PATH_INITIAL, 1);
+#endif
+
+ /* Start the page fill worker kernel thread that will resolve page faults.
+ * This should always be the first thread started because it may have to
+ * resolve page faults in other threads
+ */
+
+ os_pgworker();
+
+ /* Start the worker thread that will serve as the device driver "bottom-
+ * half" and will perform misc garbage clean-up.
+ */
+
+ os_workqueues();
+
+ /* Perform any last-minute, board-specific initialization, if so
+ * configured.
+ */
+
+#ifdef CONFIG_BOARD_INITIALIZE
+ board_initialize();
+#endif
+
+ /* Once the operating system has been initialized, the system must be
+ * started by spawning the user initialization thread of execution. This
+ * is the first user-mode thread.
+ */
+
+ os_init_thread();
/* We an save a few bytes by discarding the IDLE thread's environment. */