Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kernel: Improve single thread (CONFIG_MULTITHREADING=n) support #34279

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1d33fbb
kernel: Move k_busy_wait from thread to timeout
nordic-krch Apr 14, 2021
02452c8
kernel: Move _kernel from sched to init
nordic-krch Apr 16, 2021
4fa1ab5
kernel: timer: Adding support to CONFIG_MULTITHREADING=n
nordic-krch Apr 14, 2021
65c0cc1
kernel: mem_slab: Add support to no multithreading
nordic-krch Apr 19, 2021
5d191a7
kernel: heap: Add support for CONFIG_MULTITHREADING=n
nordic-krch Apr 19, 2021
7c80eb2
kernel: fatal: Avoid thread api access when no multithreading
nordic-krch Apr 14, 2021
7ad0210
kernel: Limit kernel files when CONFIG_MULTITHREADING=n
nordic-krch Apr 14, 2021
6965b10
testsuite: ztest: Add support for CONFIG_MULTITHREADING=n
nordic-krch Apr 14, 2021
349b356
tests: kernel: timer: timer_api: Extend with CONFIG_MULTITHREADING=n …
nordic-krch Apr 14, 2021
bbd1f21
tests: kernel: threads: no-multithreading: Extend test
nordic-krch Apr 14, 2021
7c238a7
tests: kernel: mem_slab: Add no multithreading support
nordic-krch Apr 19, 2021
392b1ac
tests: kernel: mem_heap: Add CONFIG_MULTITHREADING=n configuration
nordic-krch Apr 19, 2021
c3ffc27
Revert "kernel: Deprecate CONFIG_MULTITHREADING"
nordic-krch Apr 14, 2021
125f988
doc: kernel: document general policy for Zephyr without threads
pabigot Oct 19, 2020
e521a75
debug: Allow spin lock validation only with multithreading
nordic-krch Apr 15, 2021
fa1be85
drivers: clock_control: nrf: Supoprt no multithreading
nordic-krch Apr 15, 2021
beb9073
drivers: serial: nrf_uarte: Support for no multithreading
nordic-krch Apr 15, 2021
547ae66
logging: Fix support for no multithreading
nordic-krch Apr 19, 2021
8f72731
soc: arm: nordic: Do not use PM when no multithreading
nordic-krch Apr 15, 2021
1726756
tests: kernel: fatal: Add no multithreading test
nordic-krch Apr 15, 2021
f2ed72e
boards: arm: qemu_cortex_m0: use LFXTAL
nordic-krch Apr 16, 2021
0519100
irq_offload: Remove ifdef from the api
nordic-krch Apr 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions boards/arm/qemu_cortex_m0/qemu_cortex_m0_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ CONFIG_QEMU_ICOUNT_SHIFT=6
CONFIG_GPIO=y

# clock control
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y

# enable uart driver
CONFIG_SERIAL=y
Expand Down
5 changes: 5 additions & 0 deletions doc/reference/kernel/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@ synchronization.
scheduling/index.rst
threads/system_threads.rst
threads/workqueue.rst
threads/nothread.rst
other/interrupts.rst
other/polling.rst
synchronization/semaphores.rst
synchronization/mutexes.rst
synchronization/condvar.rst
smp/smp.rst

.. _kernel_data_passing_api:

Data Passing
************

Expand Down Expand Up @@ -83,6 +86,8 @@ argument.
data_passing/mailboxes.rst
data_passing/pipes.rst

.. _kernel_memory_management_api:

Memory Management
*****************

Expand Down
3 changes: 3 additions & 0 deletions doc/reference/kernel/threads/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
Threads
#######

.. note::
There is also limited support for using :ref:`nothread`.

.. contents::
:local:
:depth: 2
Expand Down
121 changes: 121 additions & 0 deletions doc/reference/kernel/threads/nothread.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
.. _nothread:

Zephyr Without Threads
######################

Thread support is not necessary in some applications:

* Bootloaders
* Simple event-driven applications
* Examples intended to demonstrate core functionality

Thread support can be disabled in Zephyr by setting
:option:`CONFIG_MULTITHREADING` to ``n``. Since this configuration has
a significant impact on Zephyr's functionality and testing of it has
been limited, there are conditions on what can be expected to work in
this configuration.

What Can be Expected to Work
****************************

These core capabilities shall function correctly when
:option:`CONFIG_MULTITHREADING` is disabled:

* The :ref:`build system <application>`

* The ability to boot the application to ``main()``

* :ref:`Interrupt management <interrupts_v2>`

* The system clock including :c:func:`k_uptime_get`

* Timers, i.e. :c:func:`k_timer`

* Non-sleeping delays e.g. :c:func:`k_busy_wait`.

* Sleeping :c:func:`k_cpu_idle`.

* Pre ``main()`` drivers and subsystems initialization e.g. :c:macro:`SYS_INIT`.

* :ref:`kernel_memory_management_api`

* Specifically identified drivers in certain subsystems, listed below.

The expectations above affect selection of other features; for example
:option:`CONFIG_SYS_CLOCK_EXISTS` cannot be set to ``n``.

What Cannot be Expected to Work
*******************************

Functionality that will not work with :option:`CONFIG_MULTITHREADING`
includes majority of the kernel API:

* :ref:`threads_v2`

* :ref:`scheduling_v2`

* :ref:`workqueues_v2`

* :ref:`polling_v2`

* :ref:`semaphores_v2`

* :ref:`mutexes_v2`

* :ref:`condvar`

* :ref:`kernel_data_passing_api`

.. contents::
:local:
:depth: 1

Subsystem Behavior Without Thread Support
*****************************************

The sections below list driver and functional subsystems that are
expected to work to some degree when :option:`CONFIG_MULTITHREADING` is
disabled. Subsystems that are not listed here should not be expected to
work.

Some existing drivers within the listed subsystems do not work when
threading is disabled, but are within scope based on their subsystem, or
may be sufficiently isolated that supporting them on a particular
platform is low-impact. Enhancements to add support to existing
capabilities that were not originally implemented to work with threads
disabled will be considered.

Flash
=====

The :ref:`flash_api` is expected to work for all SoC flash peripheral
drivers. Bus-accessed devices like serial memories may not be
supported.

*List/table of supported drivers to go here*

GPIO
====

The :ref:`gpio_api` is expected to work for all SoC GPIO peripheral
drivers. Bus-accessed devices like GPIO extenders may not be supported.

*List/table of supported drivers to go here*

UART
====

A subset of the :ref:`uart_api` is expected to work for all SoC UART
peripheral drivers.

* Applications that select :option:`CONFIG_UART_INTERRUPT_DRIVEN` may
work, depending on driver implementation.

* Applications that select :option:`CONFIG_UART_ASYNC_API` may
work, depending on driver implementation.

* Applications that do not select either :option:`CONFIG_UART_ASYNC_API`
or :option:`CONFIG_UART_INTERRUPT_DRIVEN` are expected to work.

*List/table of supported drivers to go here, including which API options
are supported*
2 changes: 1 addition & 1 deletion drivers/clock_control/clock_control_nrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ static void lfclk_spinwait(enum nrf_lfclk_start_mode mode)
* happen before calling idle. That would lead to deadlock.
*/
if (!IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
if (isr_mode) {
if (isr_mode || !IS_ENABLED(CONFIG_MULTITHREADING)) {
k_cpu_atomic_idle(key);
} else {
k_msleep(1);
Expand Down
12 changes: 8 additions & 4 deletions drivers/serial/uart_nrfx_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,14 @@ static void uart_nrfx_poll_out(const struct device *dev, unsigned char c)
while (atomic_cas((atomic_t *) lock,
(atomic_val_t) 0,
(atomic_val_t) 1) == false) {
/* k_sleep allows other threads to execute and finish
* their transactions.
*/
k_msleep(1);
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
/* k_sleep allows other threads to execute and finish
* their transactions.
*/
k_msleep(1);
} else {
k_busy_wait(1000);
}
if (--safety_cnt == 0) {
break;
}
Expand Down
4 changes: 3 additions & 1 deletion drivers/serial/uart_nrfx_uarte.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,9 @@ static int wait_tx_ready(const struct device *dev)

irq_unlock(key);
}
k_msleep(1);
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_msleep(1);
}
} while (1);

return key;
Expand Down
4 changes: 1 addition & 3 deletions include/irq_offload.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
extern "C" {
#endif

#ifdef CONFIG_IRQ_OFFLOAD
typedef void (*irq_offload_routine_t)(const void *parameter);
typedef void (*irq_offload_routine_t)(const void *parameter);

/**
* @brief Run a function in interrupt context
Expand All @@ -31,7 +30,6 @@ extern "C" {
* interrupt
*/
void irq_offload(irq_offload_routine_t routine, const void *parameter);
#endif

#ifdef __cplusplus
}
Expand Down
3 changes: 3 additions & 0 deletions include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -4841,6 +4841,7 @@ extern int k_mem_slab_init(struct k_mem_slab *slab, void *buffer,
* This routine allocates a memory block from a memory slab.
*
* @note @a timeout must be set to K_NO_WAIT if called from ISR.
* @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT.
*
* @funcprops \isr_ok
*
Expand Down Expand Up @@ -4961,6 +4962,7 @@ void k_heap_init(struct k_heap *h, void *mem, size_t bytes);
* k_heap_free().
*
* @note @a timeout must be set to K_NO_WAIT if called from ISR.
* @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT.
*
* @funcprops \isr_ok
*
Expand All @@ -4984,6 +4986,7 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes,
* the timeout, NULL will be returned.
*
* @note @a timeout must be set to K_NO_WAIT if called from ISR.
* @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT.
*
* @funcprops \isr_ok
*
Expand Down
23 changes: 12 additions & 11 deletions kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,34 @@
# should not be --whole-archive'd

list(APPEND kernel_files
banner.c
device.c
errno.c
fatal.c
idle.c
init.c
kheap.c
mailbox.c
mem_slab.c
thread.c
version.c
)

if(CONFIG_MULTITHREADING)
list(APPEND kernel_files
idle.c
mailbox.c
msg_q.c
mutex.c
pipes.c
queue.c
sched.c
sem.c
stack.c
system_work_q.c
thread.c
version.c
condvar.c
work.c
smp.c
banner.c
sched.c
condvar.c
)
endif()

if(CONFIG_XIP)
list(APPEND kernel_files
Expand Down Expand Up @@ -60,10 +65,6 @@ if(${CONFIG_KERNEL_MEM_POOL})
target_sources(kernel PRIVATE mempool.c)
endif()

if(NOT CONFIG_MULTITHREADING)
message(WARNING "Single threaded mode (CONFIG_MULTITHREADING=n) is deprecated")
endif()

# The last 2 files inside the target_sources_ifdef should be
# userspace_handler.c and userspace.c. If not the linker would complain.
# This order has to be maintained. Any new file should be placed
Expand Down
9 changes: 1 addition & 8 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ module-str = kernel
source "subsys/logging/Kconfig.template.log_config"

config MULTITHREADING
bool "Multi-threading (DEPRECATED)"
bool "Multi-threading"
default y
help
Disabling this option is DEPRECATED.

If disabled, only the main thread is available, so a main() function
must be provided. Interrupts are available. Kernel objects will most
probably not behave as expected, especially with regards to pending,
Expand All @@ -25,11 +23,6 @@ config MULTITHREADING
set to 'n'; disable only when you REALLY know what you are
doing.

if !MULTITHREADING
comment "*** WARNING ***"
comment "Single threaded mode (MULTITHREADING option disabled) is deprecated"
endif

config NUM_COOP_PRIORITIES
int "Number of coop priorities" if MULTITHREADING
default 1 if !MULTITHREADING
Expand Down
8 changes: 6 additions & 2 deletions kernel/fatal.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
* appropriate.
*/
unsigned int key = arch_irq_lock();
struct k_thread *thread = k_current_get();
struct k_thread *thread = IS_ENABLED(CONFIG_MULTITHREADING) ?
k_current_get() : NULL;

/* twister looks for the "ZEPHYR FATAL ERROR" string, don't
* change it without also updating twister
Expand Down Expand Up @@ -179,5 +180,8 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
}

arch_irq_unlock(key);
k_thread_abort(thread);

if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_thread_abort(thread);
}
}
3 changes: 3 additions & 0 deletions kernel/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ uint32_t __noinit z_timestamp_main; /* timestamp when main task starts */
uint32_t __noinit z_timestamp_idle; /* timestamp when CPU goes idle */
#endif

/* the only struct z_kernel instance */
struct z_kernel _kernel;

/* init/main and idle threads */
K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
struct k_thread z_main_thread;
Expand Down
5 changes: 3 additions & 2 deletions kernel/kheap.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes,
ret = sys_heap_aligned_alloc(&h->heap, align, bytes);

now = sys_clock_tick_get();
if ((ret != NULL) || ((end - now) <= 0)) {
if (!IS_ENABLED(CONFIG_MULTITHREADING) ||
(ret != NULL) || ((end - now) <= 0)) {
break;
}

Expand All @@ -58,7 +59,7 @@ void k_heap_free(struct k_heap *h, void *mem)

sys_heap_free(&h->heap, mem);

if (z_unpend_all(&h->wait_q) != 0) {
if (IS_ENABLED(CONFIG_MULTITHREADING) && z_unpend_all(&h->wait_q) != 0) {
z_reschedule(&h->lock, key);
} else {
k_spin_unlock(&h->lock, key);
Expand Down
5 changes: 3 additions & 2 deletions kernel/mem_slab.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout)
#endif

result = 0;
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT) ||
!IS_ENABLED(CONFIG_MULTITHREADING)) {
/* don't wait for a free block to become available */
*mem = NULL;
result = -ENOMEM;
Expand All @@ -143,7 +144,7 @@ void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
{
k_spinlock_key_t key = k_spin_lock(&slab->lock);

if (slab->free_list == NULL) {
if (slab->free_list == NULL && IS_ENABLED(CONFIG_MULTITHREADING)) {
struct k_thread *pending_thread = z_unpend_first_thread(&slab->wait_q);

if (pending_thread != NULL) {
Expand Down
Loading