From 6feabf0fee07c60b23971035a957acec4dea6c3a Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 6 Mar 2013 00:02:07 +0000 Subject: [PATCH] Implement user-mode work queues git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5712 42af7a65-404d-4744-a932-0658087f49c3 --- ChangeLog | 5 +- TODO | 21 +-- include/nuttx/wqueue.h | 258 +++++++++++++++++++++++++++++------- libc/Kconfig | 113 +++++++++++++++- libc/wqueue/Make.defs | 4 + libc/wqueue/work_thread.c | 66 ++++++++- libc/wqueue/work_usrstart.c | 118 +++++++++++++++++ sched/Kconfig | 68 ---------- sched/os_bringup.c | 38 +++++- syscall/syscall.csv | 4 +- 10 files changed, 545 insertions(+), 150 deletions(-) create mode 100644 libc/wqueue/work_usrstart.c diff --git a/ChangeLog b/ChangeLog index abfdcf6da6..cb29aeb3d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4255,5 +4255,8 @@ (2013-03-05) * libc/wqueue: Work queue logic moved from sched/ to libc/wqueue. It is not really core OS functionality and this move helps prepare for - user-space work queues. + user-space work queues. (2013-03-05) + * libc/wqueue: Implemented user-space work queues. These will not + get tested until the next time I attempt a NuttX kernel build. + (2013-03-05). diff --git a/TODO b/TODO index 96472bc8fe..5f2fcf016e 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated February 5, 2013) +NuttX TODO List (Last updated March 5, 2013) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -6,7 +6,7 @@ standards, things that could be improved, and ideas for enhancements. nuttx/ - (11) Task/Scheduler (sched/) + (10) Task/Scheduler (sched/) (1) Memory Managment (mm/) (3) Signals (sched/, arch/) (2) pthreads (sched/) @@ -126,23 +126,6 @@ o Task/Scheduler (sched/) Status: Open Priority: Low -- There is no plan to implement this. - Title: USER-SPACE WORK QUEUES - Description: There has been some use of work queues that has crept into some - user code. I am thinking of NxWidgets::CNxTimer. That timer - logic was originally implemented (correctly) using POSIX timers, - but was re-implemented using timed work. - - The issue is that NxWidgets::CNxTimer is a user-space application - but the work queues are an OS internal feature. This will be a - problem for KERNEL builds. Hooks and definitions have been added - in include/nuttx/wqueue.h to support a user-space work queue, but - the corresponding logic has not been implemented. - - The work queue logic will need to be moved from sched/ to libc/wqueue/ - Status: Open. No work will probably be done until a functional KERNEL build - that includes NxWisges::CNxTimer is needed. - Priority: Medium Low for now - Title: INCOMPATIBILITES WITH execv() AND execl() Description: Simplified 'execl()' and 'execv()' functions are provided by NuttX. NuttX does not support processes and hence the concept diff --git a/include/nuttx/wqueue.h b/include/nuttx/wqueue.h index 67a518008b..e76cdfd284 100644 --- a/include/nuttx/wqueue.h +++ b/include/nuttx/wqueue.h @@ -61,6 +61,10 @@ * (which runs at the lowest of priority and may not be appropriate * if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE * is enabled, then the following options can also be used: + * CONFIG_SCHED_HPWORK - Build the high priority work queue. To preserve + * legacy behavior, CONFIG_SCHED_HPWORK is assumed to be true in a flat + * build (CONFIG_SCHED_KERNEL=n) but must be defined in kernel mode + * in order to build the high priority work queue. * CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker * thread. Default: 192 * CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for @@ -83,23 +87,85 @@ * priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE. */ +/* Is this a kernel build (CONFIG_NUTTX_KERNEL=y) */ + +#ifdef CONFIG_NUTTX_KERNEL + + /* Yes.. kernel worker threads are not built in a kernel build when we are + * building the user-space libraries. + */ + +# ifndef __KERNEL__ +# undef CONFIG_SCHED_HPWORK +# undef CONFIG_SCHED_LPWORK + + /* User-space worker threads are not built in a kernel build when we are + * building the kernel-space libraries. + */ + +# else +# undef CONFIG_SCHED_USRWORK +# endif + + /* User-space worker threads are not built in a flat build + * (CONFIG_NUTTX_KERNEL=n) + */ + +#else + + /* To preserve legacy behavior, CONFIG_SCHED_HPWORK is assumed to be true + * in a flat build (CONFIG_SCHED_KERNEL=n) but must be defined in kernel + * mode in order to build the high priority work queue. + */ + +# undef CONFIG_SCHED_HPWORK +# undef CONFIG_SCHED_USRWORK +# define CONFIG_SCHED_HPWORK 1 +#endif + +/* We never build the low priority work queue without building the high + * priority work queue. + */ + +#if defined(CONFIG_SCHED_LPWORK) && !defined(CONFIG_SCHED_HPWORK) +# error "CONFIG_SCHED_LPWORK defined, but CONFIG_SCHED_HPWORK not defined" +# undef CONFIG_SCHED_LPWORK +#endif + +/* We might not be building any work queue support in this context */ + +#if !defined(CONFIG_SCHED_HPWORK) && !defined(CONFIG_SCHED_LPWORK) && !defined(CONFIG_SCHED_USRWORK) +# undef CONFIG_SCHED_WORKQUEUE +#endif + +#ifdef CONFIG_SCHED_WORKQUEUE + +/* We are building work queues... Work queues need signal support */ + #if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_DISABLE_SIGNALS) # warning "Worker thread support requires signals" #endif -#ifndef CONFIG_SCHED_WORKPRIORITY -# define CONFIG_SCHED_WORKPRIORITY 192 -#endif +/* High priority, kernel work queue configuration ***************************/ -#ifndef CONFIG_SCHED_WORKPERIOD -# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */ -#endif +#ifdef CONFIG_SCHED_HPWORK -#ifndef CONFIG_SCHED_WORKSTACKSIZE -# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE -#endif +# ifndef CONFIG_SCHED_WORKPRIORITY +# define CONFIG_SCHED_WORKPRIORITY 192 +# endif + +# ifndef CONFIG_SCHED_WORKPERIOD +# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */ +# endif + +# ifndef CONFIG_SCHED_WORKSTACKSIZE +# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE +# endif + +/* Low priority kernel work queue configuration *****************************/ #ifdef CONFIG_SCHED_LPWORK + # ifndef CONFIG_SCHED_LPWORKPRIORITY # define CONFIG_SCHED_LPWORKPRIORITY 50 # endif @@ -111,44 +177,88 @@ # ifndef CONFIG_SCHED_LPWORKSTACKSIZE # define CONFIG_SCHED_LPWORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE # endif -#endif -/* How many worker threads are there? */ - -#ifdef CONFIG_SCHED_LPWORK -# define NWORKERS 2 -#else -# define NWORKERS 1 -#endif - -/* Work queue IDs (indices): - * - * Kernel Work Queues: - * HPWORK: This ID of the high priority work queue that should only be used for - * hi-priority, time-critical, driver bottom-half functions. - * - * LPWORK: This is the ID of the low priority work queue that can be used for any - * purpose. if CONFIG_SCHED_LPWORK is not defined, then there is only one kernel - * work queue and LPWORK == HPWORK. - * - * User Work Queue: - * USRWORK: CONFIG_NUTTX_KERNEL and CONFIG_SCHED_USRWORK are defined, then NuttX - * will also support a user-accessible work queue. Otherwise, USRWORK == LPWORK. +/* The high priority worker thread should be higher priority than the low + * priority worker thread. */ -#define HPWORK 0 -#ifdef CONFIG_SCHED_LPWORK -# define LPWORK (HPWORK+1) -#else -# define LPWORK HPWORK +#if CONFIG_SCHED_LPWORKPRIORITY > CONFIG_SCHED_WORKPRIORITY +# warning "The Lower priority worker thread has the higher priority" #endif -#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_SCHED_USRWORK) -# warning "Feature not implemented" -# define USRWORK (LPWORK+1) +#endif /* CONFIG_SCHED_LPWORK */ +#endif /* CONFIG_SCHED_HPWORK */ + +/* User space work queue configuration **************************************/ + +#ifdef CONFIG_SCHED_USRWORK + +# ifndef CONFIG_SCHED_USRWORKPRIORITY +# define CONFIG_SCHED_USRWORKPRIORITY 50 +# endif + +# ifndef CONFIG_SCHED_USRWORKPERIOD +# define CONFIG_SCHED_USRWORKPERIOD (50*1000) /* 50 milliseconds */ +# endif + +# ifndef CONFIG_SCHED_USRWORKSTACKSIZE +# define CONFIG_SCHED_USRWORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE +# endif + +#endif /* CONFIG_SCHED_USRWORK */ + +/* How many worker threads are there? In the user-space phase of a kernel + * build, there will be no more than one. + * + * Work queue IDs (indices): + * + * Kernel Work Queues: There are none and any attempts to use them + * should generate errors. + * + * User Work Queue: Will be available if CONFIG_SCHED_USRWORK is defined + */ + +#if defined(CONFIG_NUTTX_KERNEL) && !defined(__KERNEL__) +# ifdef CONFIG_SCHED_USRWORK +# define NWORKERS 1 +# define USRWORK 0 +# endif #else -# define USRWORK LPWORK -#endif + + /* In a flat build (CONFIG_NUTTX_KERNEL=n) or during the kernel phase of + * the kernel build, there may be 0, 1, or 2 work queues. + * + * Work queue IDs (indices): + * + * Kernel Work Queues: + * HPWORK: This ID of the high priority work queue that should only be + * used for hi-priority, time-critical, driver bottom-half functions. + * + * LPWORK: This is the ID of the low priority work queue that can be + * used for any purpose. if CONFIG_SCHED_LPWORK is not defined, then + * there is only one kernel work queue and LPWORK == HPWORK. + * + * User Work Queue: + * USRWORK: In the kernel phase a a kernel build, there should be no + * references to user-space work queues. That would be an error. + * Otherwise, in a flat build, user applications will use the lower + * priority work queue (if there is one). + */ + +# define HPWORK 0 +# ifdef CONFIG_SCHED_LPWORK +# define LPWORK (HPWORK+1) +# define NWORKERS 2 +# else +# define LPWORK HPWORK +# define NWORKERS 1 +# endif + +# ifndef CONFIG_NUTTX_KERNEL +# define USRWORK LPWORK +# endif + +#endif /* CONFIG_NUTTX_KERNEL && !__KERNEL__ */ /**************************************************************************** * Public Types @@ -202,22 +312,50 @@ extern "C" * logic. */ +#ifdef CONFIG_NUTTX_KERNEL + + /* Play some games in the kernel mode build to assure that different + * naming is used for the global work queue data structures. This may + * not be necessary but it safer. + */ + +# ifdef __KERNEL__ +EXTERN struct wqueue_s g_kernelwork[NWORKERS]; +# define g_work g_kernelwork +# else +EXTERN struct wqueue_s g_usrwork[NWORKERS]; +# define g_work g_usrwork +# endif + +#else /* CONFIG_NUTTX_KERNEL */ + EXTERN struct wqueue_s g_work[NWORKERS]; +#endif /* CONFIG_NUTTX_KERNEL */ + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ /**************************************************************************** - * Name: work_hpthread and work_lpthread + * Name: work_hpthread, work_lpthread, and work_usrthread * * Description: - * These are the main worker threads that performs actions placed on the - * work lists. One thread also performs periodic garbage collection (that - * is performed by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * These are the worker threads that performs actions placed on the work + * lists. * - * These entrypoints are referenced by OS internally and should not be - * accessed by application logic. + * work_hpthread and work_lpthread: These are the kernel mode work queues + * (also build in the flat build). One of these threads also performs + * periodic garbage collection (that is otherwise performed by the idle + * thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * These worker threads are started by the OS during normal bringup. + * + * work_usrthread: This is a user mode work queue. It must be started + * by application code by calling work_usrstart(). + * + * All of these entrypoints are referenced by OS internally and should not + * not be accessed by application logic. * * Input parameters: * argc, argv (not used) @@ -227,12 +365,37 @@ EXTERN struct wqueue_s g_work[NWORKERS]; * ****************************************************************************/ +#ifdef CONFIG_SCHED_HPWORK int work_hpthread(int argc, char *argv[]); +#endif #ifdef CONFIG_SCHED_LPWORK int work_lpthread(int argc, char *argv[]); #endif +#ifdef CONFIG_SCHED_USRWORK +int work_usrthread(int argc, char *argv[]); +#endif + +/**************************************************************************** + * Name: work_usrstart + * + * Description: + * Start the user mode work queue. + * + * Input parameters: + * None + * + * Returned Value: + * The task ID of the worker thread is returned on success. A negated + * errno value is returned on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_USRWORK +int work_usrstart(void); +#endif + /**************************************************************************** * Name: work_queue * @@ -324,4 +487,5 @@ int work_signal(int qid); #endif #endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SCHED_WORKQUEUE */ #endif /* __INCLUDE_NUTTX_WQUEUE_H */ diff --git a/libc/Kconfig b/libc/Kconfig index 3aee837c35..a549ced45c 100644 --- a/libc/Kconfig +++ b/libc/Kconfig @@ -346,7 +346,118 @@ config ARCH_BZERO endif -comment "Non-standard Helper Functions" +comment "Non-standard Library Support" + +config SCHED_WORKQUEUE + bool "Enable worker thread" + default n + depends on !DISABLE_SIGNALS + ---help--- + Create a dedicated "worker" thread to handle delayed processing from interrupt + handlers. This feature is required for some drivers but, if there are no + complaints, can be safely disabled. The worker thread also performs + garbage collection -- completing any delayed memory deallocations from + interrupt handlers. If the worker thread is disabled, then that clean up will + be performed by the IDLE thread instead (which runs at the lowest of priority + and may not be appropriate if memory reclamation is of high priority). + +if SCHED_WORKQUEUE + +config SCHED_HPWORK + bool "High priority (kernel) worker thread" + default y + ---help--- + If SCHED_WORKQUEUE is defined, then a single, high priority work queue is + created by default. This high priority worker thread is intended to serve + as the "bottom half" for driver interrupt handling. + +if SCHED_HPWORK +config SCHED_WORKPRIORITY + int "High priority worker thread priority" + default 192 + ---help--- + The execution priority of the worker thread. Default: 192 + +config SCHED_WORKPERIOD + int "High priority worker thread period" + default 50000 + ---help--- + How often the worker thread checks for work in units of microseconds. + Default: 50*1000 (50 MS). + +config SCHED_WORKSTACKSIZE + int "High priority worker thread stack size" + default 2048 + depends on SCHED_WORKQUEUE + ---help--- + The stack size allocated for the worker thread. Default: 2K. + +config SCHED_LPWORK + bool "Low priority (kernel) worker thread" + default n + ---help--- + If SCHED_WORKQUEUE is defined, then a single work queue is created by + default. If SCHED_LPWORK is also defined then an additional, lower- + priority work queue will also be created. This lower priority work + queue is better suited for more extended processing (such as file system + clean-up operations) + +if SCHED_LPWORK + +config SCHED_LPWORKPRIORITY + int "Low priority worker thread priority" + default 50 + ---help--- + The execution priority of the lopwer priority worker thread. Default: 192 + +config SCHED_LPWORKPERIOD + int "Low priority worker thread period" + default 50000 + ---help--- + How often the lower priority worker thread checks for work in units + of microseconds. Default: 50*1000 (50 MS). + +config SCHED_LPWORKSTACKSIZE + int "Low priority worker thread stack size" + default 2048 + ---help--- + The stack size allocated for the lower priority worker thread. Default: 2K. + +endif # SCHED_LPWORK +endif # SCHED_HPWORK + +if NUTTX_KERNEL + +config SCHED_USRWORK + bool "User mode worker thread" + default n + ---help--- + User space work queues can also be made available for deferred processing in the NuttX kernel build. + +if SCHED_USRWORK + +config SCHED_LPWORKPRIORITY + int "User mode priority worker thread priority" + default 50 + ---help--- + The execution priority of the lopwer priority worker thread. Default: 192 + +config SCHED_LPWORKPERIOD + int "User mode worker thread period" + default 50000 + ---help--- + How often the lower priority worker thread checks for work in units + of microseconds. Default: 50*1000 (50 MS). + +config SCHED_LPWORKSTACKSIZE + int "User mode worker thread stack size" + default 2048 + ---help--- + The stack size allocated for the lower priority worker thread. Default: 2K. + +endif # SCHED_USRWORK +endif # NUTTX_KERNEL +endif # SCHED_WORKQUEUE config LIB_KBDCODEC bool "Keyboard CODEC" diff --git a/libc/wqueue/Make.defs b/libc/wqueue/Make.defs index 1a13bcf787..fca63a8a67 100644 --- a/libc/wqueue/Make.defs +++ b/libc/wqueue/Make.defs @@ -39,6 +39,10 @@ ifeq ($(CONFIG_SCHED_WORKQUEUE),y) CSRCS += work_thread.c work_queue.c work_cancel.c work_signal.c +ifeq ($(CONFIG_NUTTX_KERNEL),y) +CSRCS += work_usrstart.c +endif + # Add the wqueue directory to the build DEPPATH += --dep-path wqueue diff --git a/libc/wqueue/work_thread.c b/libc/wqueue/work_thread.c index 32dff9c8c5..febcd0ae86 100644 --- a/libc/wqueue/work_thread.c +++ b/libc/wqueue/work_thread.c @@ -65,10 +65,30 @@ * Public Variables ****************************************************************************/ -/* The state of each work queue */ +/* The state of each work queue. */ + +#ifdef CONFIG_NUTTX_KERNEL + + /* Play some games in the kernel mode build to assure that different + * naming is used for the global work queue data structures. This may + * not be necessary but it safer. + * + * In this case g_work is #define'd to be either g_kernelwork or + * g_usrwork in include/nuttx/wqueue.h + */ + +# ifdef __KERNEL__ +struct wqueue_s g_kernelwork[NWORKERS]; +# else +struct wqueue_s g_usrwork[NWORKERS]; +# endif + +#else /* CONFIG_NUTTX_KERNEL */ struct wqueue_s g_work[NWORKERS]; +#endif /* CONFIG_NUTTX_KERNEL */ + /**************************************************************************** * Private Variables ****************************************************************************/ @@ -181,12 +201,24 @@ static void work_process(FAR struct wqueue_s *wqueue) * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: work_hpthread and work_lpthread + * Name: work_hpthread, work_lpthread, and work_usrthread * * Description: - * These are the main worker threads that performs actions placed on the - * work lists. One thread also performs periodic garbage collection (that - * is performed by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * These are the worker threads that performs actions placed on the work + * lists. + * + * work_hpthread and work_lpthread: These are the kernel mode work queues + * (also build in the flat build). One of these threads also performs + * periodic garbage collection (that is otherwise performed by the idle + * thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * These worker threads are started by the OS during normal bringup. + * + * work_usrthread: This is a user mode work queue. It must be started + * by application code by calling work_usrstart(). + * + * All of these entrypoints are referenced by OS internally and should not + * not be accessed by application logic. * * Input parameters: * argc, argv (not used) @@ -196,6 +228,8 @@ static void work_process(FAR struct wqueue_s *wqueue) * ****************************************************************************/ +#ifdef CONFIG_SCHED_HPWORK + int work_hpthread(int argc, char *argv[]) { /* Loop forever */ @@ -224,6 +258,7 @@ int work_hpthread(int argc, char *argv[]) } #ifdef CONFIG_SCHED_LPWORK + int work_lpthread(int argc, char *argv[]) { /* Loop forever */ @@ -250,5 +285,26 @@ int work_lpthread(int argc, char *argv[]) } #endif /* CONFIG_SCHED_LPWORK */ +#endif /* CONFIG_SCHED_HPWORK */ + +#ifdef CONFIG_SCHED_USRWORK + +int work_usrthread(int argc, char *argv[]) +{ + /* Loop forever */ + + for (;;) + { + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + work_process(&g_work[USRWORK]); + } + + return OK; /* To keep some compilers happy */ +} + +#endif /* CONFIG_SCHED_USRWORK */ #endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/libc/wqueue/work_usrstart.c b/libc/wqueue/work_usrstart.c new file mode 100644 index 0000000000..b472afc8d0 --- /dev/null +++ b/libc/wqueue/work_usrstart.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * libc/wqueue/work_usrstart.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_usrstart + * + * Description: + * Start the user mode work queue. + * + * Input parameters: + * None + * + * Returned Value: + * The task ID of the worker thread is returned on success. A negated + * errno value is returned on failure. + * + ****************************************************************************/ + +int work_usrstart(void) +{ + int errcode; + + DEBUGASSERT(g_usrwork[USRWORK] == NULL); + + /* Start a lower priority worker thread for other, non-critical continuation + * tasks + */ + + svdbg("Starting user-mode worker thread\n"); + + g_usrwork[USRWORK].pid = TASK_CREATE("usrwork", + CONFIG_SCHED_USRWORKPRIORITY, + CONFIG_SCHED_USRWORKSTACKSIZE, + (main_t)work_usrthread, + (FAR char * const *)NULL); + + errcode = errno; + ASSERT(g_usrwork[USRWORK].pid > 0); + if (g_usrwork[USRWORK].pid < 0) + { + sdbg("task_create failed: %d\n", errcode); + return -errcode; + } + + return g_usrwork[USRWORK].pid; +} + +#endif /* CONFIG_SCHED_WORKQUEUE && CONFIG_SCHED_USRWORK */ diff --git a/sched/Kconfig b/sched/Kconfig index 61900f4988..b7561ff583 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -245,74 +245,6 @@ config SDCLONE_DISABLE desciptors by task_create() when a new task is started. If set, all sockets will appear to be closed in the new task. -config SCHED_WORKQUEUE - bool "Enable worker thread" - default n - depends on !DISABLE_SIGNALS - ---help--- - Create a dedicated "worker" thread to handle delayed processing from interrupt - handlers. This feature is required for some drivers but, if there are no - complaints, can be safely disabled. The worker thread also performs - garbage collection -- completing any delayed memory deallocations from - interrupt handlers. If the worker thread is disabled, then that clean up will - be performed by the IDLE thread instead (which runs at the lowest of priority - and may not be appropriate if memory reclamation is of high priority). - -config SCHED_WORKPRIORITY - int "Worker thread priority" - default 192 - depends on SCHED_WORKQUEUE - ---help--- - The execution priority of the worker thread. Default: 192 - -config SCHED_WORKPERIOD - int "Worker thread period" - default 50000 - depends on SCHED_WORKQUEUE - ---help--- - How often the worker thread checks for work in units of microseconds. - Default: 50*1000 (50 MS). - -config SCHED_WORKSTACKSIZE - int "Worker thread stack size" - default 2048 - depends on SCHED_WORKQUEUE - ---help--- - The stack size allocated for the worker thread. Default: 2K. - -config SCHED_LPWORK - bool "Enable a lower priority worker thread" - default n - depends on SCHED_WORKQUEUE - ---help--- - If SCHED_WORKQUEUE is defined, then a single work queue is created by - default. If SCHED_LPWORK is also defined then an additional, lower- - priority work queue will also be created. This lower priority work - queue is better suited for more extended processing (such as file system - clean-up operations) - -config SCHED_LPWORKPRIORITY - int "Lower priority worker thread priority" - default 50 - depends on SCHED_LPWORK - ---help--- - The execution priority of the lopwer priority worker thread. Default: 192 - -config SCHED_LPWORKPERIOD - int "Lower priority worker thread period" - default 50000 - depends on SCHED_LPWORK - ---help--- - How often the lower priority worker thread checks for work in units - of microseconds. Default: 50*1000 (50 MS). - -config SCHED_LPWORKSTACKSIZE - int "Lower priority worker thread stack size" - default 2048 - depends on SCHED_LPWORK - ---help--- - The stack size allocated for the lower priority worker thread. Default: 2K. - config SCHED_WAITPID bool "Enable waitpid() API" default n diff --git a/sched/os_bringup.c b/sched/os_bringup.c index 506de8dc3f..2fcb9ff7b8 100644 --- a/sched/os_bringup.c +++ b/sched/os_bringup.c @@ -62,11 +62,26 @@ * Pre-processor Definitions ****************************************************************************/ -/* If NuttX is built as a separately compiled module, then the the header +/* If NuttX is built as a separately compiled module, then the config.h header * file should contain the address of the user module entry point. If not * then the default entry point is user_start. */ +/* Customize some strings */ + +#ifdef CONFIG_SCHED_WORKQUEUE +# ifdef CONFIG_SCHED_HPWORK +# if defined(CONFIG_SCHED_LPWORK) +# define HPWORKNAME "hpwork" +# define LPWORKNAME "lpwork" +# elif defined(CONFIG_SCHED_USRWORK) +# define HPWORKNAME "knlwork" +# else +# define HPWORKNAME "work" +# endif +# endif +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -147,9 +162,15 @@ int os_bringup(void) */ #ifdef CONFIG_SCHED_WORKQUEUE - svdbg("Starting worker thread\n"); +#ifdef CONFIG_SCHED_HPWORK - g_work[HPWORK].pid = KERNEL_THREAD("work0", CONFIG_SCHED_WORKPRIORITY, +#ifdef CONFIG_SCHED_LPWORK + svdbg("Starting high-priority kernel worker thread\n"); +#else + svdbg("Starting kernel worker thread\n"); +#endif + + g_work[HPWORK].pid = KERNEL_THREAD(HPWORKNAME, CONFIG_SCHED_WORKPRIORITY, CONFIG_SCHED_WORKSTACKSIZE, (main_t)work_hpthread, (FAR char * const *)NULL); ASSERT(g_work[HPWORK].pid > 0); @@ -159,14 +180,17 @@ int os_bringup(void) */ #ifdef CONFIG_SCHED_LPWORK - svdbg("Starting worker thread\n"); - g_work[LPWORK].pid = KERNEL_THREAD("work1", CONFIG_SCHED_LPWORKPRIORITY, + svdbg("Starting low-priority kernel worker thread\n"); + + g_work[LPWORK].pid = KERNEL_THREAD(LPWORKNAME, CONFIG_SCHED_LPWORKPRIORITY, CONFIG_SCHED_LPWORKSTACKSIZE, (main_t)work_lpthread, (FAR char * const *)NULL); ASSERT(g_work[LPWORK].pid > 0); -#endif -#endif + +#endif /* CONFIG_SCHED_LPWORK */ +#endif /* CONFIG_SCHED_HPWORK */ +#endif /* CONFIG_SCHED_WORKQUEUE */ /* Once the operating system has been initialized, the system must be * started by spawning the user init thread of execution. This is the diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 6716e9d6af..5f68697cac 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -43,8 +43,8 @@ "prctl","sys/prctl.h", "CONFIG_TASK_NAME_SIZE > 0","int","int","..." "clock_systimer","nuttx/clock.h","!defined(CONFIG_DISABLE_CLOCK)","uint32_t" "poll","poll.h","!defined(CONFIG_DISABLE_POLL) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","FAR struct pollfd*","nfds_t","int" -"posix_spawnp", defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []" -"posix_spawn", !defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []" +"posix_spawnp","spawn.h","defined(CONFIG_BINFMT_EXEPATH)","int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []" +"posix_spawn","spawn.h","!defined(CONFIG_BINFMT_EXEPATH)","int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []" "pthread_barrier_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*" "pthread_barrier_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*","FAR const pthread_barrierattr_t*","unsigned int" "pthread_barrier_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*"