summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorJoel Sherrill <joel@rtems.org>2021-10-07 17:28:26 -0500
committerJoel Sherrill <joel@rtems.org>2021-10-11 08:42:25 -0500
commit822ebb4cae2bb8bc9fe55915bd4acc4942fcd8ce (patch)
treed8b9f10c2f96ca59e190964557f8ab3b0c50af2a /cpukit
parentscore: _Thread_queue_Surrender_priority_ceiling() (diff)
downloadrtems-822ebb4cae2bb8bc9fe55915bd4acc4942fcd8ce.tar.bz2
Add support for IDLE Thread stack allocator
Add a stack allocator hook specifically for allocation of IDLE thread stacks. This allows the user to decide if IDLE thread stacks are statically allocated or handled by the same custom allocator mechanism as other thread stacks. Closes #4524.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/include/rtems/confdefs/percpu.h18
-rw-r--r--cpukit/include/rtems/confdefs/wkspace.h16
-rw-r--r--cpukit/include/rtems/config.h12
-rw-r--r--cpukit/include/rtems/score/stack.h24
-rw-r--r--cpukit/score/src/stackallocatorforidle.c59
-rw-r--r--cpukit/score/src/threadcreateidle.c12
6 files changed, 133 insertions, 8 deletions
diff --git a/cpukit/include/rtems/confdefs/percpu.h b/cpukit/include/rtems/confdefs/percpu.h
index badb616988..3bea8340cb 100644
--- a/cpukit/include/rtems/confdefs/percpu.h
+++ b/cpukit/include/rtems/confdefs/percpu.h
@@ -134,11 +134,19 @@ RTEMS_DEFINE_GLOBAL_SYMBOL(
const size_t _Thread_Idle_stack_size = CONFIGURE_IDLE_TASK_STACK_SIZE;
-char _Thread_Idle_stacks[
- _CONFIGURE_MAXIMUM_PROCESSORS
- * ( CONFIGURE_IDLE_TASK_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE )
-] RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
-RTEMS_SECTION( ".rtemsstack.idle" );
+/*
+ * If the user provides a custom idle stack allocator, then we do not need
+ * memory reserved for the stacks but the symbol is still referenced in
+ * threadcreateidle.c. The code path just never uses it. Make it minimal
+ * size to proceed.
+ */
+#ifndef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
+ char _Thread_Idle_stacks[
+ _CONFIGURE_MAXIMUM_PROCESSORS
+ * ( CONFIGURE_IDLE_TASK_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE )
+ ] RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
+ RTEMS_SECTION( ".rtemsstack.idle" );
+#endif
#if defined(CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION) && \
!defined(CONFIGURE_IDLE_TASK_BODY)
diff --git a/cpukit/include/rtems/confdefs/wkspace.h b/cpukit/include/rtems/confdefs/wkspace.h
index 1db4f2d09d..82de8633bf 100644
--- a/cpukit/include/rtems/confdefs/wkspace.h
+++ b/cpukit/include/rtems/confdefs/wkspace.h
@@ -167,12 +167,14 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wtautological-pointer-compare"
+ /* Custom allocator may or may not use the work space. */
#ifdef CONFIGURE_TASK_STACK_ALLOCATOR_AVOIDS_WORK_SPACE
const bool _Stack_Allocator_avoids_workspace = true;
#else
const bool _Stack_Allocator_avoids_workspace = false;
#endif
+ /* Custom allocator may or may not need initialization. */
#ifdef CONFIGURE_TASK_STACK_ALLOCATOR_INIT
const Stack_Allocator_initialize _Stack_Allocator_initialize =
_CONFIGURE_ASSERT_NOT_NULL(
@@ -187,6 +189,7 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
);
#endif
+ /* Custom allocator must include allocate and free */
const Stack_Allocator_allocate _Stack_Allocator_allocate =
_CONFIGURE_ASSERT_NOT_NULL(
Stack_Allocator_allocate,
@@ -200,11 +203,24 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
);
#pragma GCC diagnostic pop
+
+/*
+ * Must provide both a custom stack allocator and deallocator
+ */
#elif defined(CONFIGURE_TASK_STACK_ALLOCATOR) \
|| defined(CONFIGURE_TASK_STACK_DEALLOCATOR)
#error "CONFIGURE_TASK_STACK_ALLOCATOR and CONFIGURE_TASK_STACK_DEALLOCATOR must be both defined or both undefined"
#endif
+/*
+ * Custom IDLE thread stacks allocator. If this is provided, it is assumed
+ * that the allocator is providing its own memory for these stacks.
+ */
+#ifdef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
+ const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
+ CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE;
+#endif
+
#ifdef CONFIGURE_DIRTY_MEMORY
RTEMS_SYSINIT_ITEM(
_Memory_Dirty_free_areas,
diff --git a/cpukit/include/rtems/config.h b/cpukit/include/rtems/config.h
index afcee4381b..7b15bc34a2 100644
--- a/cpukit/include/rtems/config.h
+++ b/cpukit/include/rtems/config.h
@@ -368,6 +368,18 @@ uint32_t rtems_configuration_get_maximum_extensions( void );
*/
#define rtems_configuration_get_stack_free_hook() _Stack_Allocator_free
+/**
+ * @ingroup RTEMSAPIConfig
+ *
+ * @brief Gets the IDLE thread stack allocator hook configured for this
+ * application.
+ *
+ * @return Returns the IDLE thread stack allocator hook configured for this
+ * application.
+ */
+#define rtems_configuration_get_stack_allocate_for_idle_hook() \
+ (_Stack_Allocator_allocate_for_idle)
+
/* Generated from spec:/rtems/config/if/get-stack-space-size */
/**
diff --git a/cpukit/include/rtems/score/stack.h b/cpukit/include/rtems/score/stack.h
index 23421cf7ae..ffa6368ba5 100644
--- a/cpukit/include/rtems/score/stack.h
+++ b/cpukit/include/rtems/score/stack.h
@@ -81,6 +81,23 @@ typedef void *( *Stack_Allocator_allocate )( size_t stack_size );
typedef void ( *Stack_Allocator_free )( void *addr );
/**
+ * @brief Stack allocator allocate for idle handler.
+ *
+ * The allocate for idle handler is optional even when the user thread stack
+ * allocator and deallocator are configured.
+ *
+ * @param cpu Index of the CPU for the IDLE thread using this stack
+ * @param stack_size The size of the stack area to allocate in bytes.
+ *
+ * @retval NULL Not enough memory.
+ * @retval other Pointer to begin of stack area.
+ */
+typedef void *( *Stack_Allocator_allocate_for_idle )(
+ uint32_t cpu,
+ size_t stack_size
+);
+
+/**
* @brief The minimum stack size.
*
* Application provided via <rtems/confdefs.h>.
@@ -130,6 +147,13 @@ extern const Stack_Allocator_free _Stack_Allocator_free;
void _Stack_Allocator_do_initialize( void );
/** @} */
+/**
+ * @brief The stack allocator allocate stack for idle thread handler.
+ *
+ * Application provided via <rtems/confdefs.h>.
+ */
+extern const Stack_Allocator_allocate_for_idle
+ _Stack_Allocator_allocate_for_idle;
#ifdef __cplusplus
}
diff --git a/cpukit/score/src/stackallocatorforidle.c b/cpukit/score/src/stackallocatorforidle.c
new file mode 100644
index 0000000000..7c4fd10c7d
--- /dev/null
+++ b/cpukit/score/src/stackallocatorforidle.c
@@ -0,0 +1,59 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2021 OAR Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/stack.h>
+#include <rtems/score/thread.h>
+
+/**
+ * @brief Default stack allocator allocate for idle handler.
+ *
+ * The allocate for idle handler is optional even when the user thread stack
+ * allocator and deallocator are configured.
+ *
+ * The default allocator for IDLE thread stacks gets the memory from a
+ * statically allocated area provided via confdefs.h.
+ *
+ * @param cpu Index of the CPU for the IDLE thread using this stack
+ * @param stack_size The size of the stack area to allocate in bytes.
+ *
+ * @retval NULL Not enough memory (never returned).
+ * @retval other Pointer to begin of stack area.
+ */
+static void *_Stack_Allocator_allocate_for_idle_default(
+ uint32_t cpu,
+ size_t stack_size
+)
+{
+ return &_Thread_Idle_stacks[ cpu * stack_size ];
+}
+
+const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
+ _Stack_Allocator_allocate_for_idle_default;
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index f5ffc9bad8..86e117e70f 100644
--- a/cpukit/score/src/threadcreateidle.c
+++ b/cpukit/score/src/threadcreateidle.c
@@ -49,9 +49,15 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
config.is_preemptible = true;
config.stack_size = _Thread_Idle_stack_size
+ CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE;
- config.stack_area = &_Thread_Idle_stacks[
- _Per_CPU_Get_index( cpu ) * config.stack_size
- ];
+
+ /*
+ * The IDLE thread stacks may be statically allocated or there may be a
+ * custom allocator provided just as with user threads.
+ */
+ config.stack_area = (*_Stack_Allocator_allocate_for_idle)(
+ _Per_CPU_Get_index( cpu ),
+ config.stack_size
+ );
/*
* The entire workspace is zeroed during its initialization. Thus, all