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_APPLICATION_MEMORY=y
|
||||||
CONFIG_X86_PAE_MODE=y
|
CONFIG_X86_PAE_MODE=y
|
||||||
CONFIG_DEBUG_INFO=y
|
CONFIG_DEBUG_INFO=y
|
||||||
CONFIG_SCHED_DUMB=n
|
CONFIG_SCHED_SCALABLE=y
|
||||||
CONFIG_WAITQ_FAST=y
|
CONFIG_WAITQ_SCALABLE=y
|
||||||
|
|
|
@ -73,7 +73,7 @@ extern "C" {
|
||||||
#define K_HIGHEST_APPLICATION_THREAD_PRIO (K_HIGHEST_THREAD_PRIO)
|
#define K_HIGHEST_APPLICATION_THREAD_PRIO (K_HIGHEST_THREAD_PRIO)
|
||||||
#define K_LOWEST_APPLICATION_THREAD_PRIO (K_LOWEST_THREAD_PRIO - 1)
|
#define K_LOWEST_APPLICATION_THREAD_PRIO (K_LOWEST_THREAD_PRIO - 1)
|
||||||
|
|
||||||
#ifdef CONFIG_WAITQ_FAST
|
#ifdef CONFIG_WAITQ_SCALABLE
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct _priq_rb waitq;
|
struct _priq_rb waitq;
|
||||||
|
@ -406,7 +406,7 @@ struct _thread_base {
|
||||||
struct rbnode qnode_rb;
|
struct rbnode qnode_rb;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_WAITQ_FAST
|
#ifdef CONFIG_WAITQ_SCALABLE
|
||||||
/* wait queue on which the thread is pended (needed only for
|
/* wait queue on which the thread is pended (needed only for
|
||||||
* trees, not dumb lists)
|
* trees, not dumb lists)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -195,23 +195,17 @@ config APPLICATION_MEMORY
|
||||||
will have the project-level application objects and any libraries
|
will have the project-level application objects and any libraries
|
||||||
including the C library in it.
|
including the C library in it.
|
||||||
|
|
||||||
config WAITQ_FAST
|
choice SCHED_ALGORITHM
|
||||||
bool
|
prompt "Scheduler priority queue algorithm"
|
||||||
prompt "Use scalable wait_q implementation"
|
default SCHED_DUMB
|
||||||
help
|
help
|
||||||
When selected, the wait_q abstraction used in IPC primitives
|
The kernel can be built with with several choices for the
|
||||||
to pend threads for wakeup later will be implemented with a
|
ready queue implementation, offering different choices between
|
||||||
balanced tree instead of a linear list. Choose this if you
|
code size, constant factor runtime overhead and performance
|
||||||
expect to have many threads waiting on individual
|
scaling when many threads are added.
|
||||||
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).
|
|
||||||
|
|
||||||
config SCHED_DUMB
|
config SCHED_DUMB
|
||||||
bool
|
bool "Simple linked-list ready queue"
|
||||||
prompt "Use a simple linked list scheduler"
|
|
||||||
default y
|
|
||||||
help
|
help
|
||||||
When selected, the scheduler ready queue will be implemented
|
When selected, the scheduler ready queue will be implemented
|
||||||
as a simple unordered list, with very fast constant time
|
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
|
(that are not otherwise using the red/black tree) this
|
||||||
results in a savings of ~2k of code size.
|
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"
|
menu "Kernel Debugging and Metrics"
|
||||||
|
|
||||||
config INIT_STACKS
|
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)
|
#define _get_next_timeout_expiry() (K_FOREVER)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_WAITQ_FAST
|
#ifdef CONFIG_WAITQ_SCALABLE
|
||||||
|
|
||||||
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
||||||
RB_FOR_EACH_CONTAINER(&(wq)->waitq.tree, thread_ptr, base.qnode_rb)
|
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);
|
return (void *)rb_get_min(&w->waitq.tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_WAITQ_FAST: */
|
#else /* !CONFIG_WAITQ_SCALABLE: */
|
||||||
|
|
||||||
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
|
||||||
SYS_DLIST_FOR_EACH_CONTAINER(&((wq)->waitq), 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);
|
return (void *)sys_dlist_peek_head(&w->waitq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_WAITQ_FAST */
|
#endif /* !CONFIG_WAITQ_SCALABLE */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,21 @@
|
||||||
#include <kernel_arch_func.h>
|
#include <kernel_arch_func.h>
|
||||||
#include <syscall_handler.h>
|
#include <syscall_handler.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_DUMB
|
#if defined(CONFIG_SCHED_DUMB)
|
||||||
#define _priq_run_add _priq_dumb_add
|
#define _priq_run_add _priq_dumb_add
|
||||||
#define _priq_run_remove _priq_dumb_remove
|
#define _priq_run_remove _priq_dumb_remove
|
||||||
#define _priq_run_best _priq_dumb_best
|
#define _priq_run_best _priq_dumb_best
|
||||||
#else
|
#elif defined(CONFIG_SCHED_SCALABLE)
|
||||||
#define _priq_run_add _priq_rb_add
|
#define _priq_run_add _priq_rb_add
|
||||||
#define _priq_run_remove _priq_rb_remove
|
#define _priq_run_remove _priq_rb_remove
|
||||||
#define _priq_run_best _priq_rb_best
|
#define _priq_run_best _priq_rb_best
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_WAITQ_FAST
|
#if defined(CONFIG_WAITQ_SCALABLE)
|
||||||
#define _priq_wait_add _priq_rb_add
|
#define _priq_wait_add _priq_rb_add
|
||||||
#define _priq_wait_remove _priq_rb_remove
|
#define _priq_wait_remove _priq_rb_remove
|
||||||
#define _priq_wait_best _priq_rb_best
|
#define _priq_wait_best _priq_rb_best
|
||||||
#else
|
#elif defined(CONFIG_WAITQ_DUMB)
|
||||||
#define _priq_wait_add _priq_dumb_add
|
#define _priq_wait_add _priq_dumb_add
|
||||||
#define _priq_wait_remove _priq_dumb_remove
|
#define _priq_wait_remove _priq_dumb_remove
|
||||||
#define _priq_wait_best _priq_dumb_best
|
#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) {
|
if (wait_q) {
|
||||||
#ifdef CONFIG_WAITQ_FAST
|
#ifdef CONFIG_WAITQ_SCALABLE
|
||||||
thread->base.pended_on = wait_q;
|
thread->base.pended_on = wait_q;
|
||||||
#endif
|
#endif
|
||||||
_priq_wait_add(&wait_q->waitq, thread);
|
_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)
|
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);
|
__ASSERT_NO_MSG(thread->base.pended_on);
|
||||||
|
|
||||||
return 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);
|
_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;
|
thread->base.pended_on = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue