Skip to content

Commit 4cc958a

Browse files
Alexander pinheiro paschoalettoalexpaschoaletto
authored andcommitted
kernel: CBS: Adding support for Constant Bandwidth Server (CBS)
This commit introduces kernel support for the Constant Bandwidth Server (CBS), 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 configured timing constraints, thus acting as a fail-safe for EDF overruns. Signed-off-by: Alexander pinheiro paschoaletto <1222703@isep.ipp.pt>
1 parent 3142c51 commit 4cc958a

File tree

12 files changed

+784
-0
lines changed

12 files changed

+784
-0
lines changed

include/zephyr/kernel/thread.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ struct k_thread {
372372
_wait_q_t halt_queue;
373373
#endif /* CONFIG_SMP */
374374

375+
#ifdef CONFIG_CBS
376+
/** Constant Bandwidth Server (CBS) struct */
377+
void *cbs;
378+
#endif
379+
375380
/** arch-specifics: must always be at the end */
376381
struct _thread_arch arch;
377382
};

include/zephyr/sched_server/cbs.h

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* Copyright (c) 2024 Instituto Superior de Engenharia do Porto (ISEP)
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
/**
7+
* @file
8+
*
9+
* @brief Constant Bandwidth Server (CBS) public API
10+
*/
11+
12+
#ifndef ZEPHYR_CBS
13+
#define ZEPHYR_CBS
14+
15+
#include <zephyr/kernel.h>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
#ifdef CONFIG_CBS
22+
23+
/**
24+
* @defgroup cbs_apis Constant Bandwidth Server (CBS) APIs
25+
* @ingroup kernel_apis
26+
* @{
27+
*/
28+
29+
/**
30+
* @brief CBS job format.
31+
*
32+
* A job pushed to a CBS is a regular function that must
33+
* have a void pointer as an argument (can be NULL if not
34+
* needed) and return nothing. jobs are pushed to the CBS by
35+
* invoking k_cbs_push_job().
36+
*/
37+
typedef void (*cbs_callback_t)(void *arg);
38+
39+
/**
40+
* @cond INTERNAL_HIDDEN
41+
*/
42+
43+
#ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER
44+
typedef uint64_t cbs_cycle_t;
45+
#else
46+
typedef uint32_t cbs_cycle_t;
47+
#endif
48+
49+
struct cbs_job {
50+
cbs_callback_t function;
51+
void *arg;
52+
};
53+
54+
struct cbs_budget {
55+
cbs_cycle_t current;
56+
cbs_cycle_t max;
57+
};
58+
59+
struct cbs_arg {
60+
k_timeout_t budget;
61+
k_timeout_t period;
62+
};
63+
64+
struct k_cbs {
65+
struct k_timer timer;
66+
struct k_msgq *queue;
67+
struct k_thread *thread;
68+
struct cbs_budget budget;
69+
cbs_cycle_t period;
70+
cbs_cycle_t abs_deadline;
71+
cbs_cycle_t start_cycle;
72+
cbs_cycle_t bandwidth;
73+
bool is_active;
74+
unsigned int left_shift;
75+
#ifdef CONFIG_CBS_LOG
76+
char name[CONFIG_CBS_THREAD_MAX_NAME_LEN];
77+
#endif
78+
};
79+
80+
extern void cbs_thread(void *job_queue, void *cbs_struct, void *unused);
81+
82+
/** @endcond */
83+
84+
/**
85+
* @brief pushes a job to a CBS queue.
86+
*
87+
* This routine inserts a job (i.e. a regular C function) in a CBS queue,
88+
* which will eventually execute it when the CBS deadline becomes the
89+
* earliest of the taskset. Inserted jobs are always served in a FIFO
90+
* manner. The job queue can store up to @kconfig{CONFIG_CBS_QUEUE_LENGTH}
91+
* jobs at once.
92+
*
93+
* @param cbs Name of the CBS.
94+
* @param job_function Function of the job.
95+
* @param job_arg Argument to be passed to the job function.
96+
* @param timeout Waiting period to push the job, or one of the special
97+
* values K_NO_WAIT and K_FOREVER.
98+
*
99+
* @retval 0 the job was pushed to the CBS queue.
100+
* @retval -ENOMSG if CBS is not defined, returned without waiting or CBS queue purged.
101+
* @retval -EAGAIN if waiting period timed out.
102+
*/
103+
int k_cbs_push_job(struct k_cbs *cbs, cbs_callback_t job_function, void *job_arg,
104+
k_timeout_t timeout);
105+
106+
/**
107+
* @brief Statically define and initialize a Constant Bandwidth Server (CBS).
108+
*
109+
* A CBS is an extension of the Earliest Deadline First (EDF) scheduler
110+
* that allows tasks to be executed virtually isolated from each other,
111+
* in a way that if a task executes for longer than expected it doesn’t
112+
* interfere on the execution of the others. In other words, the CBS
113+
* prevents that a task misbehavior causes other tasks to miss their
114+
* own deadlines.
115+
*
116+
* In a nutshell, the CBS is a work-conserving wrapper for the tasks
117+
* that automatically recalculates their deadlines when they exceed their
118+
* allowed execution time slice. This time slice is known as the CBS "budget".
119+
* The value used to recalculate the deadline is known as the CBS "period".
120+
*
121+
* When a task instance (i.e. job) runs within a CBS, it consumes the "budget".
122+
* When the "budget" runs out, the deadline is postponed by "period" time units
123+
* and the "budget" is replenished to its maximum capacity. when there are no jobs
124+
* left for a CBS to execute, it remains idle and takes no CPU time.
125+
*
126+
* Finally, whenever a new job is pushed to an idle server, the kernel verifies
127+
* if the current pair of (budget, deadline) are proportionally compatible with
128+
* the configured values. If not, the deadline is also recalculated here.
129+
* These two procedures ensure the CBS will never use the CPU more than
130+
* what was configured, and that it will not endanger other thread's deadlines.
131+
*
132+
* Once created, the CBS can be referenced through its name:
133+
*
134+
* @code extern const struct k_cbs <cbs_name>; @endcode
135+
*
136+
* @param cbs_name Name of the CBS.
137+
* @param cbs_budget Budget of the CBS thread, in system ticks.
138+
* Used for triggering deadline recalculations.
139+
* @param cbs_period Period of the CBS thread. in system ticks.
140+
* Used for recalculating the absolute deadline.
141+
* @param cbs_static_priority Static priority of the CBS thread.
142+
*
143+
* @note The CBS is meant to be used alongside the EDF policy, which in Zephyr
144+
* is effectively used as a "tie-breaker" when two threads of equal static priorities
145+
* are ready for execution. Therefore it is recommended that all user threads feature
146+
* the same preemptive static priority (e.g. 5) in order to ensure the scheduling
147+
* to work as expected, and that this same value is passed as @a cbs_static_priority.
148+
*
149+
* @note you should have @kconfig{CONFIG_CBS} enabled in your project to use the CBS.
150+
*/
151+
#define K_CBS_DEFINE(cbs_name, cbs_budget, cbs_period, cbs_static_priority) \
152+
K_MSGQ_DEFINE(queue_##cbs_name, sizeof(struct cbs_job), CONFIG_CBS_QUEUE_LENGTH, 1); \
153+
static struct k_cbs cbs_name = { \
154+
.queue = &queue_##cbs_name, \
155+
.is_active = false, \
156+
}; \
157+
static struct cbs_arg args_##cbs_name = {.budget = cbs_budget, .period = cbs_period}; \
158+
K_THREAD_DEFINE(thread_##cbs_name, CONFIG_CBS_THREAD_STACK_SIZE, cbs_thread, \
159+
(void *)STRINGIFY(cbs_name), (void *)&cbs_name, (void *)&args_##cbs_name, \
160+
cbs_static_priority, 0, CONFIG_CBS_INITIAL_DELAY)
161+
/** @} */ /* end of Constant Bandwidth Server (CBS) APIs */
162+
163+
#endif /* CONFIG_CBS */
164+
165+
#ifdef __cplusplus
166+
}
167+
#endif
168+
169+
#endif /* ZEPHYR_CBS */

kernel/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ list(APPEND kernel_files
115115
)
116116
endif()
117117

118+
if(CONFIG_CBS)
119+
list(APPEND kernel_files
120+
sched_server/cbs.c
121+
)
122+
if(CONFIG_CBS_LOG)
123+
list(APPEND kernel_files
124+
sched_server/cbs_log.c
125+
)
126+
endif() # CONFIG_CBS_LOG
127+
endif()
118128

119129
if(CONFIG_THREAD_MONITOR)
120130
list(APPEND kernel_files

kernel/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,3 +1083,4 @@ endmenu
10831083
rsource "Kconfig.device"
10841084
rsource "Kconfig.vm"
10851085
rsource "Kconfig.init"
1086+
rsource "Kconfig.sched_server"

kernel/Kconfig.sched_server

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# config options for Scheduling Servers
2+
#
3+
# Copyright (c) 2024 Instituto Superior de Engenharia do Porto (ISEP)
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
menu "Constant Bandwidth Server (CBS)"
7+
8+
config CBS
9+
bool "Constant Bandwidth Server (CBS)"
10+
depends on USE_SWITCH
11+
select SCHED_DEADLINE
12+
default n
13+
help
14+
Enables the Constant Bandwidth Server (CBS), an extension
15+
of the Earliest Deadline First (EDF) scheduler that allows
16+
tasks to execute with guaranteed bandwidth. Selecting
17+
this option automatically enables the EDF scheduler
18+
(CONFIG_SCHED_DEADLINE=y). The CBS is also currently
19+
supported only in targets that use the _arch_switch
20+
context switching primitive (CONFIG_USE_SWITCH=y).
21+
22+
config CBS_LOG
23+
bool "CBS event logging"
24+
depends on CBS
25+
select LOG
26+
default n
27+
help
28+
Enables logging of Constant Bandwidth Server (CBS) events,
29+
such as jobs being pushed to the server, budget consumpion
30+
and CBS thread switching in/out of the CPU. This option
31+
requires CONFIG_CBS to be included within the project.
32+
33+
if CBS_LOG
34+
menu "CBS events to be logged"
35+
36+
config CBS_LOG_JOB_PUSH
37+
bool "J_PUSH log"
38+
default y
39+
help
40+
Enables logging of when
41+
a job is pushed to a CBS.
42+
43+
config CBS_LOG_JOB_COMPLETE
44+
bool "J_COMP log"
45+
default y
46+
help
47+
Enables logging of when
48+
a job is completed.
49+
50+
config CBS_LOG_BUDGET_CONDITION
51+
bool "B_COND log"
52+
default y
53+
help
54+
Enables logging of when
55+
the CBS condition gets met,
56+
causing the CBS deadline to
57+
be updated and the budget to
58+
be replenished.
59+
60+
config CBS_LOG_BUDGET_RAN_OUT
61+
bool "B_ROUT log"
62+
default y
63+
help
64+
Enables logging of when
65+
the CBS budget runs out,
66+
causing the CBS deadline to
67+
be postponed and the budget to
68+
be replenished.
69+
70+
config CBS_LOG_SWITCHED_IN
71+
bool "SWT_TO log"
72+
default y
73+
help
74+
Enables logging of when
75+
the CBS thread enters the
76+
CPU for execution of jobs.
77+
78+
config CBS_LOG_SWITCHED_OUT
79+
bool "SWT_AY log"
80+
default y
81+
help
82+
Enables logging of when
83+
the CBS thread leaves the
84+
CPU after completing a job
85+
or being preempted by
86+
another thread.
87+
88+
endmenu
89+
endif
90+
91+
if CBS
92+
menu "CBS constants"
93+
94+
config CBS_THREAD_STACK_SIZE
95+
int "CBS thread memory"
96+
default 2048
97+
help
98+
The amount of memory to be
99+
allocated for the CBS thread.
100+
101+
config CBS_QUEUE_LENGTH
102+
int "CBS job queue length"
103+
default 16
104+
help
105+
The highest number of jobs that can
106+
be pushed to a CBS job queue at once.
107+
108+
config CBS_INITIAL_DELAY
109+
int "CBS thread initial delay"
110+
default 0
111+
help
112+
Scheduling delay (in milliseconds) for the CBS thread.
113+
114+
if CBS_LOG
115+
config CBS_THREAD_MAX_NAME_LEN
116+
int "Max length of the CBS thread name"
117+
default 20
118+
help
119+
CBS thread names are the same as the variables created with
120+
K_CBS_DEFINE and get stored in the k_cbs struct. This option
121+
indicates the maximum name length of the CBS server to be
122+
displayed on log events, including the terminating NULL byte.
123+
Reducing this value wil help conserving memory, but as a tradeoff
124+
it might chop a portion the server name on the aforementioned logs.
125+
endif
126+
127+
endmenu
128+
endif
129+
130+
endmenu # Constant Bandwidth Server (CBS)

kernel/include/kswap.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <zephyr/sys/barrier.h>
1212
#include <kernel_arch_func.h>
1313

14+
#ifdef CONFIG_CBS
15+
#include <sched_server/cbs_internal.h>
16+
#endif
17+
1418
#ifdef CONFIG_STACK_SENTINEL
1519
extern void z_check_stack_sentinel(void);
1620
#else
@@ -130,9 +134,21 @@ static ALWAYS_INLINE unsigned int do_swap(unsigned int key,
130134
z_smp_release_global_lock(new_thread);
131135
}
132136
#endif /* CONFIG_SMP */
137+
#ifdef CONFIG_CBS
138+
/* if old_thread belongs to an active CBS, stop its budget timer */
139+
if (old_thread->cbs) {
140+
cbs_switched_out(old_thread->cbs);
141+
}
142+
#endif
133143
z_thread_mark_switched_out();
134144
z_sched_switch_spin(new_thread);
135145
z_current_thread_set(new_thread);
146+
#ifdef CONFIG_CBS
147+
/* if new_thread belongs to an active CBS, start its budget timer */
148+
if (new_thread->cbs) {
149+
cbs_switched_in(new_thread->cbs);
150+
}
151+
#endif
136152

137153
#ifdef CONFIG_TIMESLICING
138154
z_reset_time_slice(new_thread);

0 commit comments

Comments
 (0)