kernel/Kconfig: Reorgnize wait_q and sched algorithm choices
Make these "choice" items instead of a single boolean that implies the element unset. Also renames WAITQ_FAST to WAITQ_SCALABLE, as the rbtree is really only "fast" for large queue sizes (it's constant factor overhead is bigger than a list's!) Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
ec6b6c9f0c
commit
225c74bbdf
5 changed files with 67 additions and 28 deletions
|
@ -22,5 +22,5 @@ CONFIG_USERSPACE=y
|
|||
CONFIG_APPLICATION_MEMORY=y
|
||||
CONFIG_X86_PAE_MODE=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_SCHED_DUMB=n
|
||||
CONFIG_WAITQ_FAST=y
|
||||
CONFIG_SCHED_SCALABLE=y
|
||||
CONFIG_WAITQ_SCALABLE=y
|
||||
|
|
|
@ -73,7 +73,7 @@ extern "C" {
|
|||
#define K_HIGHEST_APPLICATION_THREAD_PRIO (K_HIGHEST_THREAD_PRIO)
|
||||
#define K_LOWEST_APPLICATION_THREAD_PRIO (K_LOWEST_THREAD_PRIO - 1)
|
||||
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#ifdef CONFIG_WAITQ_SCALABLE
|
||||
|
||||
typedef struct {
|
||||
struct _priq_rb waitq;
|
||||
|
@ -406,7 +406,7 @@ struct _thread_base {
|
|||
struct rbnode qnode_rb;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#ifdef CONFIG_WAITQ_SCALABLE
|
||||
/* wait queue on which the thread is pended (needed only for
|
||||
* trees, not dumb lists)
|
||||
*/
|
||||
|
|
|
@ -195,23 +195,17 @@ config APPLICATION_MEMORY
|
|||
will have the project-level application objects and any libraries
|
||||
including the C library in it.
|
||||
|
||||
config WAITQ_FAST
|
||||
bool
|
||||
prompt "Use scalable wait_q implementation"
|
||||
choice SCHED_ALGORITHM
|
||||
prompt "Scheduler priority queue algorithm"
|
||||
default SCHED_DUMB
|
||||
help
|
||||
When selected, the wait_q abstraction used in IPC primitives
|
||||
to pend threads for wakeup later will be implemented with a
|
||||
balanced tree instead of a linear list. Choose this if you
|
||||
expect to have many threads waiting on individual
|
||||
primitives, or if you have already included the red/black
|
||||
tree code in the build for some other purpose (in which case
|
||||
this results in less code size increase than the default
|
||||
implementation).
|
||||
The kernel can be built with with several choices for the
|
||||
ready queue implementation, offering different choices between
|
||||
code size, constant factor runtime overhead and performance
|
||||
scaling when many threads are added.
|
||||
|
||||
config SCHED_DUMB
|
||||
bool
|
||||
prompt "Use a simple linked list scheduler"
|
||||
default y
|
||||
bool "Simple linked-list ready queue"
|
||||
help
|
||||
When selected, the scheduler ready queue will be implemented
|
||||
as a simple unordered list, with very fast constant time
|
||||
|
@ -222,6 +216,51 @@ config SCHED_DUMB
|
|||
(that are not otherwise using the red/black tree) this
|
||||
results in a savings of ~2k of code size.
|
||||
|
||||
config SCHED_SCALABLE
|
||||
bool "Red/black tree ready queue"
|
||||
help
|
||||
When selected, the scheduler ready queue will be implemented
|
||||
as a red/black tree. This has rather slower constant-time
|
||||
insertion and removal overhead, and on most platforms (that
|
||||
are not otherwise using the rbtree somehwere) requires an
|
||||
extra ~2kb of code. But the resulting behavior will scale
|
||||
cleanly and quickly into the many thousands of threads. Use
|
||||
this on platforms where you may have MANY threads marked as
|
||||
runnable at a given time. Most applications don't want this.
|
||||
|
||||
endchoice # SCHED_ALGORITHM
|
||||
|
||||
choice WAITQ_ALGORITHM
|
||||
prompt "Wait queue priority algorithm"
|
||||
default WAITQ_DUMB
|
||||
help
|
||||
The wait_q abstraction used in IPC primitives to pend threads
|
||||
for later wakeup shares the same backend data structure
|
||||
choices as the scheduler, and can use the same options.
|
||||
|
||||
config WAITQ_SCALABLE
|
||||
bool
|
||||
prompt "Use scalable wait_q implementation"
|
||||
help
|
||||
When selected, the wait_q will be implemented with a
|
||||
balanced tree. Choose this if you expect to have many
|
||||
threads waiting on individual primitives. There is a ~2kb
|
||||
code size increase over WAITQ_DUMB (which may be shared with
|
||||
SCHED_SCALABLE) if the rbtree is not used elsewhere in the
|
||||
application, and pend/unpend operations on "small" queues
|
||||
will be somewhat slower (though this is not generally a
|
||||
performance path).
|
||||
|
||||
config WAITQ_DUMB
|
||||
bool
|
||||
prompt "Simple linked-list wait_q"
|
||||
help
|
||||
When selected, the wait_q will be implemented with a
|
||||
doubly-linked list. Choose this if you expect to have only
|
||||
a few threads blocked on any single IPC primitive.
|
||||
|
||||
endchoice # WAITQ_ALGORITHM
|
||||
|
||||
menu "Kernel Debugging and Metrics"
|
||||
|
||||
config INIT_STACKS
|
||||
|
|
|
@ -44,7 +44,7 @@ static ALWAYS_INLINE int _abort_thread_timeout(struct k_thread *thread)
|
|||
#define _get_next_timeout_expiry() (K_FOREVER)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#ifdef CONFIG_WAITQ_SCALABLE
|
||||
|
||||
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
||||
RB_FOR_EACH_CONTAINER(&(wq)->waitq.tree, thread_ptr, base.qnode_rb)
|
||||
|
@ -63,7 +63,7 @@ static inline struct k_thread *_waitq_head(_wait_q_t *w)
|
|||
return (void *)rb_get_min(&w->waitq.tree);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_WAITQ_FAST: */
|
||||
#else /* !CONFIG_WAITQ_SCALABLE: */
|
||||
|
||||
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
||||
SYS_DLIST_FOR_EACH_CONTAINER(&((wq)->waitq), thread_ptr, \
|
||||
|
@ -79,7 +79,7 @@ static inline struct k_thread *_waitq_head(_wait_q_t *w)
|
|||
return (void *)sys_dlist_peek_head(&w->waitq);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_WAITQ_FAST */
|
||||
#endif /* !CONFIG_WAITQ_SCALABLE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -12,21 +12,21 @@
|
|||
#include <kernel_arch_func.h>
|
||||
#include <syscall_handler.h>
|
||||
|
||||
#ifdef CONFIG_SCHED_DUMB
|
||||
#if defined(CONFIG_SCHED_DUMB)
|
||||
#define _priq_run_add _priq_dumb_add
|
||||
#define _priq_run_remove _priq_dumb_remove
|
||||
#define _priq_run_best _priq_dumb_best
|
||||
#else
|
||||
#elif defined(CONFIG_SCHED_SCALABLE)
|
||||
#define _priq_run_add _priq_rb_add
|
||||
#define _priq_run_remove _priq_rb_remove
|
||||
#define _priq_run_best _priq_rb_best
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#if defined(CONFIG_WAITQ_SCALABLE)
|
||||
#define _priq_wait_add _priq_rb_add
|
||||
#define _priq_wait_remove _priq_rb_remove
|
||||
#define _priq_wait_best _priq_rb_best
|
||||
#else
|
||||
#elif defined(CONFIG_WAITQ_DUMB)
|
||||
#define _priq_wait_add _priq_dumb_add
|
||||
#define _priq_wait_remove _priq_dumb_remove
|
||||
#define _priq_wait_best _priq_dumb_best
|
||||
|
@ -275,7 +275,7 @@ static void pend(struct k_thread *thread, _wait_q_t *wait_q, s32_t timeout)
|
|||
}
|
||||
|
||||
if (wait_q) {
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#ifdef CONFIG_WAITQ_SCALABLE
|
||||
thread->base.pended_on = wait_q;
|
||||
#endif
|
||||
_priq_wait_add(&wait_q->waitq, thread);
|
||||
|
@ -294,7 +294,7 @@ void _pend_thread(struct k_thread *thread, _wait_q_t *wait_q, s32_t timeout)
|
|||
|
||||
static _wait_q_t *pended_on(struct k_thread *thread)
|
||||
{
|
||||
#ifdef CONFIG_WAITQ_FAST
|
||||
#ifdef CONFIG_WAITQ_SCALABLE
|
||||
__ASSERT_NO_MSG(thread->base.pended_on);
|
||||
|
||||
return thread->base.pended_on;
|
||||
|
@ -325,7 +325,7 @@ void _unpend_thread_no_timeout(struct k_thread *thread)
|
|||
_mark_thread_as_not_pending(thread);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ASSERT) && defined(CONFIG_WAITQ_FAST)
|
||||
#if defined(CONFIG_ASSERT) && defined(CONFIG_WAITQ_SCALABLE)
|
||||
thread->base.pended_on = NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue