From 7f36c4e97ba75c79d5e3d6234f809c5c14e2eb5b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 7 Oct 2014 17:11:26 -0600 Subject: [PATCH] Update some Kconfig comments; Add a upper limit on the lower priority worker thread for priority inheritance --- include/nuttx/wqueue.h | 27 ++++++++++++- libc/Kconfig | 77 +++++++++++++++++++++++++++++++++---- sched/wqueue/work_inherit.c | 14 +++++++ 3 files changed, 109 insertions(+), 9 deletions(-) diff --git a/include/nuttx/wqueue.h b/include/nuttx/wqueue.h index 424373a175..036ea0da31 100644 --- a/include/nuttx/wqueue.h +++ b/include/nuttx/wqueue.h @@ -79,8 +79,10 @@ * 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 - The execution priority of the lower priority - * worker thread. Default: 50 + * CONFIG_SCHED_LPWORKPRIORITY - The minimum execution priority of the lower + * priority worker thread. Default: 50 + * CONFIG_SCHED_LPWORKPRIOMAX - The maximum execution priority of the lower + * priority worker thread. Default: 176 * CONFIG_SCHED_LPWORKPERIOD - How often the lower priority worker thread * checks for work in units of microseconds. Default: 50*1000 (50 MS). * CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower @@ -175,6 +177,27 @@ # define CONFIG_SCHED_LPWORKPRIORITY 50 # endif +# ifndef CONFIG_SCHED_LPWORKPRIOMAX +# ifdef CONFIG_SCHED_HPWORK +# define CONFIG_SCHED_LPWORKPRIOMAX (CONFIG_SCHED_WORKPRIORITY-16) +# else +# define CONFIG_SCHED_LPWORKPRIOMAX 176 +# endif +# endif + +# ifdef CONFIG_SCHED_HPWORK +# if CONFIG_SCHED_LPWORKPRIORITY >= CONFIG_SCHED_WORKPRIORITY +# error CONFIG_SCHED_LPWORKPRIORITY >= CONFIG_SCHED_WORKPRIORITY +# endif +# if CONFIG_SCHED_LPWORKPRIOMAX >= CONFIG_SCHED_WORKPRIORITY +# error CONFIG_SCHED_LPWORKPRIOMAX >= CONFIG_SCHED_WORKPRIORITY +# endif +# endif + +# if CONFIG_SCHED_LPWORKPRIORITY > CONFIG_SCHED_LPWORKPRIOMAX +# error CONFIG_SCHED_LPWORKPRIORITY > CONFIG_SCHED_LPWORKPRIOMAX +# endif + # ifndef CONFIG_SCHED_LPWORKPERIOD # define CONFIG_SCHED_LPWORKPERIOD (50*1000) /* 50 milliseconds */ # endif diff --git a/libc/Kconfig b/libc/Kconfig index 6961cc62c1..eba38e0b6d 100644 --- a/libc/Kconfig +++ b/libc/Kconfig @@ -412,9 +412,10 @@ 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_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 @@ -422,7 +423,20 @@ config SCHED_WORKPRIORITY int "High priority worker thread priority" default 192 ---help--- - The execution priority of the worker thread. Default: 192 + 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" @@ -445,8 +459,9 @@ config SCHED_LPWORK 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) + queue is better suited for more extended, application oriented + processing (such as file system clean-up operations or asynchronous + I/O) if SCHED_LPWORK @@ -454,7 +469,55 @@ config SCHED_LPWORKPRIORITY int "Low priority worker thread priority" default 50 ---help--- - The execution priority of the lopwer priority worker thread. Default: 50 + 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" diff --git a/sched/wqueue/work_inherit.c b/sched/wqueue/work_inherit.c index 864fd86bf4..14c012ea51 100644 --- a/sched/wqueue/work_inherit.c +++ b/sched/wqueue/work_inherit.c @@ -78,6 +78,13 @@ void lpwork_boostpriority(uint8_t reqprio) irqstate_t flags; pid_t wpid; + /* Clip to the configured maximum priority */ + + if (reqprio > CONFIG_SCHED_LPWORKPRIOMAX) + { + reqprio = CONFIG_SCHED_LPWORKPRIOMAX; + } + /* Get the process ID of the low priority worker thread from the low * priority work queue. Then get the TCB of the low priority worker * thread from the process ID. @@ -194,6 +201,13 @@ void lpwork_restorepriority(uint8_t reqprio) int index; int selected; + /* Clip to the configured maximum priority */ + + if (reqprio > CONFIG_SCHED_LPWORKPRIOMAX) + { + reqprio = CONFIG_SCHED_LPWORKPRIOMAX; + } + /* Get the process ID of the low priority worker thread from the low * priority work queue. Then get the TCB of the low priority worker * thread from the process ID.