Decouple the user-space work queue from the kernel space work queues

This commit is contained in:
Gregory Nutt 2014-10-11 15:50:22 -06:00
parent c38b81431f
commit 9292e3d9de
16 changed files with 202 additions and 205 deletions

View File

@ -130,7 +130,7 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
/* User-space work queue support (declared in include/nuttx/wqueue.h) */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
.work_usrstart = work_usrstart,
#endif
};

View File

@ -130,7 +130,7 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
/* User-space work queue support (declared in include/nuttx/wqueue.h) */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
.work_usrstart = work_usrstart,
#endif
};

View File

@ -130,7 +130,7 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
/* User-space work queue support (declared in include/nuttx/wqueue.h) */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
.work_usrstart = work_usrstart,
#endif
};

View File

@ -130,7 +130,7 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
/* User-space work queue support (declared in include/nuttx/wqueue.h) */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
.work_usrstart = work_usrstart,
#endif
};

View File

@ -131,7 +131,7 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
/* User-space work queue support (declared in include/nuttx/wqueue.h) */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
.work_usrstart = work_usrstart,
#endif
};

View File

@ -149,7 +149,7 @@ struct userspace_s
/* User-space work queue support */
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK)
#ifdef CONFIG_SCHED_USRWORK
int (*work_usrstart)(void);
#endif
};

View File

@ -51,7 +51,9 @@
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to
/* CONFIG_SCHED_WORKQUEUE. Not selectable. Set by the configuration system
* if either CONFIG_SCHED_HPWORK or CONFIG_SCHED_LPWORK are selected.
* CONFIG_SCHED_HPWORK. Create a dedicated "worker" thread to
* handle delayed processing from interrupt handlers. This feature
* is required for some drivers but, if there are not complaints,
* can be safely disabled. The worker thread also performs
@ -59,7 +61,7 @@
* from interrupt handlers. If the worker thread is disabled,
* then that clean 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 CONFIG_SCHED_WORKQUEUE
* if memory reclamation is of high priority). If CONFIG_SCHED_HPWORK
* 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
@ -77,11 +79,10 @@
* CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
* the worker thread. Default: 17
*
* CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
* work queue is created by default. If CONFIG_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_LPWORK. If CONFIG_SCHED_LPWORK is selected then a lower-
* priority work queue will be created. This lower priority work queue
* is better suited for more extended processing (such as file system
* clean-up operations)
* CONFIG_SCHED_LPNTHREADS - The number of thread in the low-priority queue's
* thread pool. Default: 1
* CONFIG_SCHED_LPWORKPRIORITY - The minimum execution priority of the lower
@ -119,10 +120,7 @@
# undef CONFIG_SCHED_HPWORK
# undef CONFIG_SCHED_LPWORK
# ifndef CONFIG_SCHED_USRWORK
# undef CONFIG_SCHED_WORKQUEUE
# endif
# undef CONFIG_SCHED_WORKQUEUE
/* User-space worker threads are not built in a kernel build when we are
* building the kernel-space libraries (but we still need to know that it
@ -144,7 +142,7 @@
# undef CONFIG_SCHED_USRWORK
#endif
#ifdef CONFIG_SCHED_WORKQUEUE
#if defined(CONFIG_SCHED_WORKQUEUE) || defined(CONFIG_SCHED_USRWORK)
/* High priority, kernel work queue configuration ***************************/
@ -471,5 +469,5 @@ void lpwork_restorepriority(uint8_t reqprio);
#endif
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_SCHED_WORKQUEUE */
#endif /* CONFIG_SCHED_WORKQUEUE || CONFIG_SCHED_USRWORK */
#endif /* __INCLUDE_NUTTX_WQUEUE_H */

View File

@ -393,174 +393,15 @@ endif # ARCH_OPTIMIZED_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 224
---help---
The execution priority of the higher priority worker thread.
The higher priority worker thread is intended to serve as the
"bottom" half for device drivers. As a consequence it must run at
a very high, fixed priority. Typically, it should be the highest
priority thread in your system. Default: 192
For lower priority, application oriented worker thread support,
please consider enabling the lower priority work queue. The lower
priority work queue runs at a lower priority, of course, but has
the added advantage that it supports "priority inheritance" (if
PRIORITY_INHERITANCE is also selected): The priority of the lower
priority worker thread can then be adjusted to match the highest
priority client.
config SCHED_WORKPERIOD
int "High priority worker thread period"
default 100000 if SCHED_LPWORK
default 50000 if !SCHED_LPWORK
---help---
How often the worker thread checks for work in units of microseconds.
Default: If the high priority worker thread is performing garbage
collection, then the default is 50*1000 (50 MS). Otherwise, if the
lower priority worker thread is performing garbage collection, the
default is 100*1000.
config SCHED_WORKSTACKSIZE
int "High priority worker thread stack size"
default 2048
---help---
The stack size allocated for the worker thread. Default: 2K.
endif # SCHED_HPWORK
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, application oriented
processing (such as file system clean-up operations or asynchronous
I/O)
if SCHED_LPWORK
config SCHED_LPNTHREADS
int "Number of low-priority worker threads"
default 1 if !FS_AIO
default 4 if FS_AIO
---help---
This options selectes multiple, low-priority threads. This is
essentially a "thread pool" that provides multi-threaded service
of the low-priority work thread. This breaks the serialization
of the "queue" (hence, it is no longer a queue at all).
This options is required to support, for example, I/O operations
that stall waiting for input. If there is only a single thread,
then the entire low-priority queue processing stalls in such cases.
Such behvior must be support for asynchronous I/O, AIO (for example).
config SCHED_LPWORKPRIORITY
int "Low priority worker thread priority"
default 50
---help---
The minimum execution priority of the lower priority worker thread.
The lower priority worker thread is intended support application-
oriented functions. The lower priority work queue runs at a lower
priority, of course, but has the added advantage that it supports
"priority inheritance" (if PRIORITY_INHERITANCE is also selected):
The priority of the lower priority worker thread can then be
adjusted to match the highest priority client. Default: 50
NOTE: This priority inheritance feature is not automatic. The
lower priority worker thread will always a fixed priority unless
you implement logic that calls lpwork_boostpriority() to raise the
priority of the lower priority worker thread (typically called
before scheduling the work) and then call the matching
lpwork_restorepriority() when the work is completed (typically
called within the work handler at the completion of the work).
Currently, only the NuttX asynchronous I/O logic uses this dynamic
prioritization feature.
The higher priority worker thread, on the other hand, is intended
to serve as the "bottom" half for device drivers. As a consequence
it must run at a very high, fixed priority. Typically, it should
be the highest priority thread in your system.
config SCHED_LPWORKPRIOMAX
int "Low priority worker thread maximum priority"
default 176
depends on PRIORITY_INHERITANCE
---help---
The maximum execution priority of the lower priority worker thread.
The lower priority worker thread is intended support application-
oriented functions. The lower priority work queue runs at a lower
priority, of course, but has the added advantage that it supports
"priority inheritance" (if PRIORITY_INHERITANCE is also selected):
The priority of the lower priority worker thread can then be
adjusted to match the highest priority client.
The higher priority worker thread, on the other hand, is intended
to serve as the "bottom" half for device drivers. As a consequence
it must run at a very high, fixed priority. Typically, it should
be the highest priority thread in your system.
This function provides an upper limit on the priority of the lower
priority worker thread. This would be necessary, for example, if
the higher priority worker thread were to defer work to the lower
priority thread. Clearly, in such a case, you would want to limit
the maximum priority of the lower priority work thread. Default:
176
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
if BUILD_PROTECTED || BUILD_KERNEL
config SCHED_USRWORK
bool "User mode worker thread"
default n
depends on !DISABLE_SIGNALS
---help---
User space work queues can also be made available for deferred processing in the NuttX kernel build.
User space work queues can also be made available for deferred
processing in the NuttX kernel build.
if SCHED_USRWORK
@ -585,7 +426,6 @@ config SCHED_USRWORKSTACKSIZE
endif # SCHED_USRWORK
endif # BUILD_PROTECTED
endif # SCHED_WORKQUEUE
config LIB_KBDCODEC
bool "Keyboard CODEC"

View File

@ -33,7 +33,7 @@
#
############################################################################
ifeq ($(CONFIG_SCHED_WORKQUEUE),y)
ifeq ($(CONFIG_SCHED_USRWORK),y)
# Add the work queue C files to the build

View File

@ -48,8 +48,7 @@
#include "wqueue/wqueue.h"
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK) && \
!defined(__KERNEL__)
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -163,4 +162,4 @@ int work_cancel(int qid, FAR struct work_s *work)
}
}
#endif /* CONFIG_SCHED_WORKQUEUE && CONFIG_SCHED_USRWORK && !__KERNEL__ */
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__ */

View File

@ -46,8 +46,7 @@
#include "wqueue/wqueue.h"
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK) && \
!defined(__KERNEL__)
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -136,4 +135,4 @@ void work_unlock(void)
#endif
}
#endif /* CONFIG_SCHED_WORKQUEUE && CONFIG_SCHED_USRWORK && !__KERNEL__*/
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__*/

View File

@ -50,8 +50,7 @@
#include "wqueue/wqueue.h"
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK) && \
!defined(__KERNEL__)
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -175,4 +174,4 @@ int work_queue(int qid, FAR struct work_s *work, worker_t worker,
}
}
#endif /* CONFIG_SCHED_WORKQUEUE && CONFIG_SCHED_USRWORK && !__KERNEL__ */
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__ */

View File

@ -46,7 +46,7 @@
#include "wqueue/wqueue.h"
#ifdef CONFIG_SCHED_WORKQUEUE
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -113,4 +113,3 @@ int work_signal(int qid)
}
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__ */
#endif /* CONFIG_SCHED_WORKQUEUE */

View File

@ -52,8 +52,7 @@
#include "wqueue/wqueue.h"
#if defined(CONFIG_SCHED_WORKQUEUE) && defined(CONFIG_SCHED_USRWORK) && \
!defined(__KERNEL__)
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -404,4 +403,4 @@ int work_usrstart(void)
#endif
}
#endif /* CONFIG_SCHED_WORKQUEUE && CONFIG_SCHED_USRWORK && !__KERNEL__*/
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__*/

View File

@ -47,7 +47,7 @@
#include <nuttx/wqueue.h>
#ifdef CONFIG_SCHED_WORKQUEUE
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/****************************************************************************
* Pre-processor Definitions
@ -70,7 +70,6 @@ struct usr_wqueue_s
* Public Data
****************************************************************************/
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
/* The state of the user mode work queue */
extern struct usr_wqueue_s g_usrwork;
@ -105,9 +104,7 @@ extern pthread_mutex_t g_usrmutex;
*
****************************************************************************/
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
int work_lock(void);
#endif
/****************************************************************************
* Name: work_unlock
@ -123,9 +120,7 @@ int work_lock(void);
*
****************************************************************************/
#if defined(CONFIG_SCHED_USRWORK) && !defined(__KERNEL__)
void work_unlock(void);
#endif
#endif /* CONFIG_SCHED_WORKQUEUE */
#endif /* CONFIG_SCHED_USRWORK && !__KERNEL__*/
#endif /* __LIBC_WQUEUE_WQUEUE_H */

View File

@ -786,7 +786,7 @@ config SIG_SIGCONDTIMEDOUT
config SIG_SIGWORK
int "SIGWORK"
default 17
depends on SCHED_WORKQUEUE
depends on SCHED_WORKQUEUE || SCHED_USRWORK
---help---
SIGWORK is a non-standard signal used to wake up the internal NuttX
worker thread. This setting specifies the signal number that will be
@ -813,6 +813,175 @@ config MQ_MAXMSGSIZE
endmenu # POSIX Message Queue Options
menu "Work Queue Support"
config SCHED_WORKQUEUE
# bool "Enable worker thread"
bool
default n
depends on !DISABLE_SIGNALS
---help---
Create dedicated "worker" threads to handle delayed or asynchronous
processing.
config SCHED_HPWORK
bool "High priority (kernel) worker thread"
default y
depends on !DISABLE_SIGNALS
select SCHED_WORKQUEUE
---help---
Create a dedicated high-priority "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 high priority worker thread also performs garbage
collection -- completing any delayed memory deallocations from
interrupt handlers. If the high-priority worker thread is disabled,
then that clean up will be performed either by (1) the low-priority
worker thread, if enabled, and if not (2) the IDLE thread instead
(which runs at the lowest of priority and may not be appropriate if
memory reclamation is of high priority)
For other, less-critical asynchronous or delayed process, the
low-priority worker thread is recommended.
if SCHED_HPWORK
config SCHED_WORKPRIORITY
int "High priority worker thread priority"
default 224
---help---
The execution priority of the higher priority worker thread.
The higher priority worker thread is intended to serve as the
"bottom" half for device drivers. As a consequence it must run at
a very high, fixed priority. Typically, it should be the highest
priority thread in your system. Default: 192
For lower priority, application oriented worker thread support,
please consider enabling the lower priority work queue. The lower
priority work queue runs at a lower priority, of course, but has
the added advantage that it supports "priority inheritance" (if
PRIORITY_INHERITANCE is also selected): The priority of the lower
priority worker thread can then be adjusted to match the highest
priority client.
config SCHED_WORKPERIOD
int "High priority worker thread period"
default 100000 if SCHED_LPWORK
default 50000 if !SCHED_LPWORK
---help---
How often the worker thread checks for work in units of microseconds.
Default: If the high priority worker thread is performing garbage
collection, then the default is 50*1000 (50 MS). Otherwise, if the
lower priority worker thread is performing garbage collection, the
default is 100*1000.
config SCHED_WORKSTACKSIZE
int "High priority worker thread stack size"
default 2048
---help---
The stack size allocated for the worker thread. Default: 2K.
endif # SCHED_HPWORK
config SCHED_LPWORK
bool "Low priority (kernel) worker thread"
default n
depends on !DISABLE_SIGNALS
select SCHED_WORKQUEUE
---help---
If SCHED_LPWORK is defined then a lower-priority work queue will
be created. This lower priority work queue is better suited for
more extended, application oriented processing (such as file system
clean-up operations or asynchronous I/O)
if SCHED_LPWORK
config SCHED_LPNTHREADS
int "Number of low-priority worker threads"
default 1 if !FS_AIO
default 4 if FS_AIO
---help---
This options selects multiple, low-priority threads. This is
essentially a "thread pool" that provides multi-threaded service
of the low-priority work thread. This breaks the serialization
of the "queue" (hence, it is no longer a queue at all).
This options is required to support, for example, I/O operations
that stall waiting for input. If there is only a single thread,
then the entire low-priority queue processing stalls in such cases.
Such behvior must be support for asynchronous I/O, AIO (for example).
config SCHED_LPWORKPRIORITY
int "Low priority worker thread priority"
default 50
---help---
The minimum execution priority of the lower priority worker thread.
The lower priority worker thread is intended support application-
oriented functions. The lower priority work queue runs at a lower
priority, of course, but has the added advantage that it supports
"priority inheritance" (if PRIORITY_INHERITANCE is also selected):
The priority of the lower priority worker thread can then be
adjusted to match the highest priority client. Default: 50
NOTE: This priority inheritance feature is not automatic. The
lower priority worker thread will always a fixed priority unless
you implement logic that calls lpwork_boostpriority() to raise the
priority of the lower priority worker thread (typically called
before scheduling the work) and then call the matching
lpwork_restorepriority() when the work is completed (typically
called within the work handler at the completion of the work).
Currently, only the NuttX asynchronous I/O logic uses this dynamic
prioritization feature.
The higher priority worker thread, on the other hand, is intended
to serve as the "bottom" half for device drivers. As a consequence
it must run at a very high, fixed priority. Typically, it should
be the highest priority thread in your system.
config SCHED_LPWORKPRIOMAX
int "Low priority worker thread maximum priority"
default 176
depends on PRIORITY_INHERITANCE
---help---
The maximum execution priority of the lower priority worker thread.
The lower priority worker thread is intended support application-
oriented functions. The lower priority work queue runs at a lower
priority, of course, but has the added advantage that it supports
"priority inheritance" (if PRIORITY_INHERITANCE is also selected):
The priority of the lower priority worker thread can then be
adjusted to match the highest priority client.
The higher priority worker thread, on the other hand, is intended
to serve as the "bottom" half for device drivers. As a consequence
it must run at a very high, fixed priority. Typically, it should
be the highest priority thread in your system.
This function provides an upper limit on the priority of the lower
priority worker thread. This would be necessary, for example, if
the higher priority worker thread were to defer work to the lower
priority thread. Clearly, in such a case, you would want to limit
the maximum priority of the lower priority work thread. Default:
176
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
endmenu # Work Queue Support
menu "Stack and heap information"
config IDLETHREAD_STACKSIZE