From e95804026974d8873601f668fd54ce220f8957c7 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 3 Sep 2014 18:36:43 -0600 Subject: [PATCH] Add capability to perform initial board initialization on a separate worker thread. --- configs/sama5d4-ek/kernel/defconfig | 3 + sched/Kconfig | 34 +++++++++ sched/init/os_bringup.c | 113 +++++++++++++++++++++++----- 3 files changed, 133 insertions(+), 17 deletions(-) diff --git a/configs/sama5d4-ek/kernel/defconfig b/configs/sama5d4-ek/kernel/defconfig index b92fab7ae9..1df0c099f6 100644 --- a/configs/sama5d4-ek/kernel/defconfig +++ b/configs/sama5d4-ek/kernel/defconfig @@ -419,6 +419,9 @@ CONFIG_NAME_MAX=32 # RTOS hooks # CONFIG_BOARD_INITIALIZE=y +CONFIG_BOARD_INITTHREAD=y +CONFIG_BOARD_INITTHREAD_STACKSIZE=2048 +CONFIG_BOARD_INITTHREAD_PRIORITY=240 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set diff --git a/sched/Kconfig b/sched/Kconfig index 5068a4e969..12752da752 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -651,6 +651,40 @@ config BOARD_INITIALIZE phase may be used, for example, to initialize board-specific device drivers. +if BOARD_INITIALIZE + +config BOARD_INITTHREAD + bool "Board initialization thread" + default n + ---help--- + Some initialization operations cannot be performed on the start-up, + initialization thread. That is because the initialization thread + cannot wait for event. If waiting is required as part of the board + initialization then this option must be selected. Waiting may be + required, for example, to mount a file system or or initialize a + device such as an SD card. + +if BOARD_INITTHREAD + +config BOARD_INITTHREAD_STACKSIZE + int "Board initialization thread stack size" + default 2048 + ---help--- + The size of the stack to allocate when starting the board + initialization thread. + +config BOARD_INITTHREAD_PRIORITY + int "Board initialization thread priority" + default 240 + ---help--- + The priority of the board initialization thread. This priority is + not a critical setting. No other application threads will be + started until the board initialization is completed. Hence, there + is very little competition for the CPU. + +endif # BOARD_INITTHREAD +endif # BOARD_INITIALIZE + config SCHED_STARTHOOK bool "Enable startup hook" default n diff --git a/sched/init/os_bringup.c b/sched/init/os_bringup.c index f85a33ef1a..23eaed0448 100644 --- a/sched/init/os_bringup.c +++ b/sched/init/os_bringup.c @@ -260,10 +260,11 @@ static inline void os_workqueues(void) #endif /* CONFIG_SCHED_WORKQUEUE */ /**************************************************************************** - * Name: os_init_thread + * Name: os_start_application * * Description: - * Start the application initialization thread. + * Execute the board initialization function (if so configured) and start + * the application initialization thread. * * Input Parameters: * None @@ -274,18 +275,26 @@ static inline void os_workqueues(void) ****************************************************************************/ #if defined(CONFIG_INIT_ENTRYPOINT) -static inline void os_init_thread(void) +static inline void os_do_appstart(void) { int taskid; - svdbg("Starting init thread\n"); +#ifdef CONFIG_BOARD_INITIALIZE + /* Perform any last-minute, board-specific initialization, if so + * configured. + */ - /* Start the application initialization ask. In a flat build, this is + board_initialize(); +#endif + + /* Start the application initialization task. 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. */ + svdbg("Starting init thread\n"); + #ifdef CONFIG_BUILD_PROTECTED DEBUGASSERT(USERSPACE->us_entrypoint != NULL); taskid = task_create("init", SCHED_PRIORITY_DEFAULT, @@ -301,10 +310,23 @@ static inline void os_init_thread(void) } #elif defined(CONFIG_INIT_FILEPATH) -static inline void os_init_thread(void) +static inline void os_do_appstart(void) { int ret; +#ifdef CONFIG_BOARD_INITIALIZE + /* Perform any last-minute, board-specific initialization, if so + * configured. + */ + + board_initialize(); +#endif + + /* Start the application initialization program from a program in a + * mounted file system. Presumably the file system was mounted as part + * of the board_initialize() operation. + */ + svdbg("Starting init task: %s\n", CONFIG_USER_INITPATH); ret = exec(CONFIG_USER_INITPATH, NULL, CONFIG_INIT_SYMTAB, @@ -313,13 +335,78 @@ static inline void os_init_thread(void) } #elif defined(CONFIG_INIT_NONE) -# define os_init_thread() +# define os_do_appstart() #else # error "Cannot start initialization thread" #endif +/**************************************************************************** + * Name: os_start_task + * + * Description: + * This is the framework for a short duration worker thread. It off-loads + * the board initialization and application start-up from the limited + * start-up, initialization thread to a more robust kernel thread. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_INITTHREAD +static int os_start_task(int argc, FAR char **argv) +{ + /* Do the board/application initialization and exit */ + + os_do_appstart(); + return OK; +} +#endif + +/**************************************************************************** + * Name: os_start_application + * + * Description: + * Execute the board initialization function (if so configured) and start + * the application initialization thread. This will be done either on the + * thread of execution of the caller or on a separate thread of execution + * if so configured. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void os_start_application(void) +{ +#ifdef CONFIG_BOARD_INITTHREAD + int taskid; + + /* Do the board/application initialization on a separate thread of + * execution. + */ + + taskid = kernel_thread("AppBringUp", CONFIG_BOARD_INITTHREAD_PRIORITY, + CONFIG_BOARD_INITTHREAD_STACKSIZE, + (main_t)os_start_task, (FAR char * const *)NULL); + ASSERT(taskid > 0); + +#else + /* Do the board/application initialization on this thread of execution. */ + + os_do_appstart(); + +#endif +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -384,20 +471,12 @@ int os_bringup(void) 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. + * will be the first user-mode thread. */ - os_init_thread(); + os_start_application(); /* We an save a few bytes by discarding the IDLE thread's environment. */