-
Notifications
You must be signed in to change notification settings - Fork 7.7k
kernel: cbs: adding support for the Constant Bandwidth Server (CBS) #83601
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/* | ||
* Copyright (c) 2024 Instituto Superior de Engenharia do Porto (ISEP) | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @file | ||
* | ||
* @brief Constant Bandwidth Server (CBS) public API | ||
*/ | ||
|
||
#ifndef ZEPHYR_CBS | ||
#define ZEPHYR_CBS | ||
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use the full path of the function in header guards like in other header files? I realize it's a bit verbose, but it's conventional and unique. |
||
|
||
#include <zephyr/kernel.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifdef CONFIG_CBS | ||
|
||
/** | ||
* @defgroup cbs_apis Constant Bandwidth Server (CBS) APIs | ||
* @ingroup kernel_apis | ||
* @{ | ||
*/ | ||
|
||
/** | ||
* @brief CBS job format. | ||
* | ||
* A job pushed to a CBS is a regular function that must | ||
* have a void pointer as an argument (can be NULL if not | ||
* needed) and return nothing. jobs are pushed to the CBS by | ||
* invoking k_cbs_push_job(). | ||
*/ | ||
typedef void (*cbs_callback_t)(void *arg); | ||
|
||
/** | ||
* @cond INTERNAL_HIDDEN | ||
*/ | ||
|
||
#ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER | ||
typedef uint64_t cbs_cycle_t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a little surprised we don't already have a cycle counter type like this. can you prefix this with a |
||
#else | ||
typedef uint32_t cbs_cycle_t; | ||
#endif | ||
|
||
struct cbs_job { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefix all of these structs with |
||
cbs_callback_t function; | ||
void *arg; | ||
}; | ||
|
||
struct cbs_budget { | ||
cbs_cycle_t current; | ||
cbs_cycle_t max; | ||
}; | ||
|
||
struct cbs_arg { | ||
k_timeout_t budget; | ||
k_timeout_t period; | ||
}; | ||
|
||
struct k_cbs { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this supposed to be a special thread structure for CBS? The main reason I ask is because Zephyr already has some Kconfig options or defines for specifying maximum thread name length and whether or not there is a field for thread name. I guess the other reason is to see if there is a convention for naming used by other schedulers for similar types. The name of the struct leaves me wondering and could maybe be expanded a bit to be more descriptive |
||
struct k_timer timer; | ||
struct k_msgq *queue; | ||
struct k_thread *thread; | ||
struct cbs_budget budget; | ||
cbs_cycle_t period; | ||
cbs_cycle_t abs_deadline; | ||
cbs_cycle_t start_cycle; | ||
cbs_cycle_t bandwidth; | ||
bool is_active; | ||
unsigned int left_shift; | ||
#ifdef CONFIG_CBS_LOG | ||
char name[CONFIG_CBS_THREAD_MAX_NAME_LEN]; | ||
#endif | ||
}; | ||
|
||
extern void cbs_thread(void *job_queue, void *cbs_struct, void *unused); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also should be prefixed with Is it possible for the job queue use named struct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can do the prefix thing, sure. But I don't know if I understood the second request, though. Do you want type |
||
|
||
/** @endcond */ | ||
|
||
/** | ||
* @brief pushes a job to a CBS queue. | ||
* | ||
* This routine inserts a job (i.e. a regular C function) in a CBS queue, | ||
* which will eventually execute it when the CBS deadline becomes the | ||
* earliest of the taskset. Inserted jobs are always served in a FIFO | ||
* manner. The job queue can store up to @kconfig{CONFIG_CBS_QUEUE_LENGTH} | ||
* jobs at once. | ||
* | ||
* @param cbs Name of the CBS. | ||
* @param job_function Function of the job. | ||
* @param job_arg Argument to be passed to the job function. | ||
* @param timeout Waiting period to push the job, or one of the special | ||
* values K_NO_WAIT and K_FOREVER. | ||
* | ||
* @retval 0 the job was pushed to the CBS queue. | ||
* @retval -ENOMSG if CBS is not defined, returned without waiting or CBS queue purged. | ||
* @retval -EAGAIN if waiting period timed out. | ||
*/ | ||
int k_cbs_push_job(struct k_cbs *cbs, cbs_callback_t job_function, void *job_arg, | ||
k_timeout_t timeout); | ||
|
||
/** | ||
* @brief Statically define and initialize a Constant Bandwidth Server (CBS). | ||
* | ||
* A CBS is an extension of the Earliest Deadline First (EDF) scheduler | ||
* that allows tasks to be executed virtually isolated from each other, | ||
* in a way that if a task executes for longer than expected it doesn’t | ||
* interfere on the execution of the others. In other words, the CBS | ||
* prevents that a task misbehavior causes other tasks to miss their | ||
* own deadlines. | ||
* | ||
* In a nutshell, the CBS is a work-conserving wrapper for the tasks | ||
* that automatically recalculates their deadlines when they exceed their | ||
* allowed execution time slice. This time slice is known as the CBS "budget". | ||
* The value used to recalculate the deadline is known as the CBS "period". | ||
* | ||
* When a task instance (i.e. job) runs within a CBS, it consumes the "budget". | ||
* When the "budget" runs out, the deadline is postponed by "period" time units | ||
* and the "budget" is replenished to its maximum capacity. when there are no jobs | ||
* left for a CBS to execute, it remains idle and takes no CPU time. | ||
* | ||
* Finally, whenever a new job is pushed to an idle server, the kernel verifies | ||
* if the current pair of (budget, deadline) are proportionally compatible with | ||
* the configured values. If not, the deadline is also recalculated here. | ||
* These two procedures ensure the CBS will never use the CPU more than | ||
* what was configured, and that it will not endanger other thread's deadlines. | ||
* | ||
* Once created, the CBS can be referenced through its name: | ||
* | ||
* @code extern const struct k_cbs <cbs_name>; @endcode | ||
* | ||
* @param cbs_name Name of the CBS. | ||
* @param cbs_budget Budget of the CBS thread, in system ticks. | ||
* Used for triggering deadline recalculations. | ||
* @param cbs_period Period of the CBS thread. in system ticks. | ||
* Used for recalculating the absolute deadline. | ||
* @param cbs_static_priority Static priority of the CBS thread. | ||
* | ||
* @note The CBS is meant to be used alongside the EDF policy, which in Zephyr | ||
* is effectively used as a "tie-breaker" when two threads of equal static priorities | ||
* are ready for execution. Therefore it is recommended that all user threads feature | ||
* the same preemptive static priority (e.g. 5) in order to ensure the scheduling | ||
* to work as expected, and that this same value is passed as @a cbs_static_priority. | ||
* | ||
* @note you should have @kconfig{CONFIG_CBS} enabled in your project to use the CBS. | ||
*/ | ||
#define K_CBS_DEFINE(cbs_name, cbs_budget, cbs_period, cbs_static_priority) \ | ||
K_MSGQ_DEFINE(queue_##cbs_name, sizeof(struct cbs_job), CONFIG_CBS_QUEUE_LENGTH, 1); \ | ||
static struct k_cbs cbs_name = { \ | ||
.queue = &queue_##cbs_name, \ | ||
.is_active = false, \ | ||
}; \ | ||
static struct cbs_arg args_##cbs_name = {.budget = cbs_budget, .period = cbs_period}; \ | ||
K_THREAD_DEFINE(thread_##cbs_name, CONFIG_CBS_THREAD_STACK_SIZE, cbs_thread, \ | ||
(void *)STRINGIFY(cbs_name), (void *)&cbs_name, (void *)&args_##cbs_name, \ | ||
cbs_static_priority, 0, CONFIG_CBS_INITIAL_DELAY) | ||
/** @} */ /* end of Constant Bandwidth Server (CBS) APIs */ | ||
|
||
#endif /* CONFIG_CBS */ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* ZEPHYR_CBS */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1083,3 +1083,4 @@ endmenu | |
rsource "Kconfig.device" | ||
rsource "Kconfig.vm" | ||
rsource "Kconfig.init" | ||
rsource "Kconfig.sched_server" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# config options for Scheduling Servers | ||
# | ||
# Copyright (c) 2024 Instituto Superior de Engenharia do Porto (ISEP) | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
menu "Constant Bandwidth Server (CBS)" | ||
|
||
config CBS | ||
bool "Constant Bandwidth Server (CBS)" | ||
depends on USE_SWITCH | ||
select SCHED_DEADLINE | ||
default n | ||
help | ||
Enables the Constant Bandwidth Server (CBS), an extension | ||
of the Earliest Deadline First (EDF) scheduler that allows | ||
tasks to execute with guaranteed bandwidth. Selecting | ||
this option automatically enables the EDF scheduler | ||
(CONFIG_SCHED_DEADLINE=y). The CBS is also currently | ||
supported only in targets that use the _arch_switch | ||
context switching primitive (CONFIG_USE_SWITCH=y). | ||
|
||
config CBS_LOG | ||
bool "CBS event logging" | ||
depends on CBS | ||
select LOG | ||
default n | ||
help | ||
Enables logging of Constant Bandwidth Server (CBS) events, | ||
such as jobs being pushed to the server, budget consumpion | ||
and CBS thread switching in/out of the CPU. This option | ||
requires CONFIG_CBS to be included within the project. | ||
|
||
if CBS_LOG | ||
menu "CBS events to be logged" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The events being recorded here really seem like they would fit better with Zephyr's tracing subsystem. Can they use that mechanism instead? |
||
|
||
config CBS_LOG_JOB_PUSH | ||
bool "J_PUSH log" | ||
default y | ||
help | ||
Enables logging of when | ||
a job is pushed to a CBS. | ||
|
||
config CBS_LOG_JOB_COMPLETE | ||
bool "J_COMP log" | ||
default y | ||
help | ||
Enables logging of when | ||
a job is completed. | ||
|
||
config CBS_LOG_BUDGET_CONDITION | ||
bool "B_COND log" | ||
default y | ||
help | ||
Enables logging of when | ||
the CBS condition gets met, | ||
causing the CBS deadline to | ||
be updated and the budget to | ||
be replenished. | ||
|
||
config CBS_LOG_BUDGET_RAN_OUT | ||
bool "B_ROUT log" | ||
default y | ||
help | ||
Enables logging of when | ||
the CBS budget runs out, | ||
causing the CBS deadline to | ||
be postponed and the budget to | ||
be replenished. | ||
|
||
config CBS_LOG_SWITCHED_IN | ||
bool "SWT_TO log" | ||
default y | ||
help | ||
Enables logging of when | ||
the CBS thread enters the | ||
CPU for execution of jobs. | ||
|
||
config CBS_LOG_SWITCHED_OUT | ||
bool "SWT_AY log" | ||
default y | ||
help | ||
Enables logging of when | ||
the CBS thread leaves the | ||
CPU after completing a job | ||
or being preempted by | ||
another thread. | ||
|
||
endmenu | ||
endif | ||
|
||
if CBS | ||
menu "CBS constants" | ||
|
||
config CBS_THREAD_STACK_SIZE | ||
int "CBS thread memory" | ||
default 2048 | ||
help | ||
The amount of memory to be | ||
allocated for the CBS thread. | ||
|
||
config CBS_QUEUE_LENGTH | ||
int "CBS job queue length" | ||
default 16 | ||
help | ||
The highest number of jobs that can | ||
be pushed to a CBS job queue at once. | ||
|
||
config CBS_INITIAL_DELAY | ||
int "CBS thread initial delay" | ||
default 0 | ||
help | ||
Scheduling delay (in milliseconds) for the CBS thread. | ||
|
||
if CBS_LOG | ||
config CBS_THREAD_MAX_NAME_LEN | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This likely duplicates something that already exists in Zephyr, so I would suggest using the existing convention. |
||
int "Max length of the CBS thread name" | ||
default 20 | ||
help | ||
CBS thread names are the same as the variables created with | ||
K_CBS_DEFINE and get stored in the k_cbs struct. This option | ||
indicates the maximum name length of the CBS server to be | ||
displayed on log events, including the terminating NULL byte. | ||
Reducing this value wil help conserving memory, but as a tradeoff | ||
it might chop a portion the server name on the aforementioned logs. | ||
endif | ||
|
||
endmenu | ||
endif | ||
|
||
endmenu # Constant Bandwidth Server (CBS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be preferable to forward declare a struct and specifically type this field rather than using a void pointer.