MISRA C:2012 Rule 8.2 requires every parameter in a function type to be
named, including the parameters of function pointer parameters.
The C++ ABI __cxa_atexit() stub, its local prototype in the ARM
__aeabi_atexit() wrapper and that wrapper itself left the destructor's
parameter unnamed.
Name them after the arguments the documentation or the
definitions already use. No functional change.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Remove remaining uses of the internal __ASSERT_ON macro. Let __ASSERT()
handle disabled assertions, mark assert-only values as unused where needed,
and use CONFIG_ASSERT for assertion-only state.
Signed-off-by: Måns Ansgariusson <mansgariusson@gmail.com>
sys_hash32_murmur3() is declared in <zephyr/sys/hash_function.h> as
taking a `const void *`, but is defined taking a `const char *`. The
mismatch goes unnoticed because the implementation does not include the
header declaring the function, so the two declarations are never seen in
the same translation unit.
Include the header and match the declared prototype.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
k_sleep() and k_usleep() resolve to an out of line implementation living in
another translation unit, a system call under CONFIG_USERSPACE and a plain
call otherwise. Either way the compiler sees neither whether the requested
duration is a constant nor whether the caller cares about the returned
value, so it always emits the tick to millisecond and microsecond
conversions. Those conversions are the only thing that drags the 64 bit
division helper into many small builds: CONFIG_SYS_CLOCK_TICKS_PER_SEC
defaults to 10000 on tickless platforms, which lands in the integer
division path and divides a 64 bit value by ten, something GCC will not
strength reduce on a 32 bit target.
Promote the former z_tick_sleep() helper to a k_sleep_ticks() system call
that reports the remaining time in ticks, and rebuild k_sleep() and
k_usleep() as inlines on top of it. The conversions now live at the call
site where the compiler can fold or discard them. Nearly every caller
discards them: of the 4036 sleep call sites in the tree, exactly six use
the returned value, and only three of those are outside of tests.
What this removes is best seen in the two out of line entry points that
disappear, which on a nucleo_f030r8 (Cortex-M0, 10000 ticks/s) were the
only two callers of the 64 bit division helper in the whole image:
08002594 <z_impl_k_sleep>:
bl 8001... <z_tick_sleep>
...
movs r0, #9 /* the ceil() bias, 10 - 1 */
adds r0, r0, r2
adcs r1, r3
movs r2, #10 /* ticks / 10 -> milliseconds */
bl 8000180 <__aeabi_uldivmod>
080025c0 <z_impl_k_usleep>:
movs r0, #99 /* the ceil() bias, 100 - 1 */
...
movs r2, #100 /* microseconds / 100 -> ticks */
bl 8000180 <__aeabi_uldivmod>
bl 8001... <z_tick_sleep>
Both are gone, and so are __aeabi_uldivmod and __udivmoddi4, which are no
longer referenced anywhere. A k_usleep(250) call site now passes the
literal 3 ticks the compiler worked out on its own, where it used to pass
250 microseconds to a helper that divided by 100 at runtime. For a loop
calling k_msleep(100), k_sleep(K_SECONDS(1)) and k_usleep(250) without
using the results, FLASH drops from 11028 to 10600 bytes.
No trace point is emitted here. The existing sleep hooks take a duration
in milliseconds or microseconds, which no longer describes what this
function is handed, and tracing cannot live in the inlines either: every
tracing backend header includes kernel.h, so a translation unit reaching a
backend header first would expand SYS_PORT_TRACING_* before those macros
exist. The following commit gives k_sleep_ticks() a hook of its own.
The duration goes through Z_TIMEOUT_US() rather than an open coded
conversion. That clamps a negative argument to zero, which k_usleep()
never did: it used to truncate the 64 bit conversion into an int32_t
first, which hid the worst of it, and passing it through whole would turn a
negative duration into a sleep of roughly 1.8e17 ticks rather than a bogus
absolute deadline. The macro also carries the cast to k_ticks_t that C++
needs, since Z_TIMEOUT_TICKS_INIT() is a braced initializer there and an
unsigned to signed conversion inside one is a narrowing error.
This also removes a potential link error. k_usleep() had no
implementation at all with CONFIG_MULTITHREADING=n, since nothread.c only
ever provided z_impl_k_sleep(), so any caller failed to link. Nothing in
the tree happens to call it in that configuration, which is presumably why
it went unnoticed; a single z_impl_k_sleep_ticks() now serves both.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
vprintk_unlocked() formats straight to the character output hook, which
lives in kernel memory and cannot be reached from a user thread. Since
assert_print() uses it, an assert taken in user mode faults instead of
printing. tests/ztest/error_hook times out on qemu_arc/qemu_arc_em and
dies on qemu_x86.
Use the same buffered path vprintk() already uses for user threads,
handing the result to the kernel through k_str_out(), and route
printk_unlocked() through vprintk_unlocked() so both variants agree.
The lock free property is kept: k_str_out() skips the lock once
printk_panic() has been called.
Introduced by commit 0ecb6caf0f ("lib: os: assert: print the
assertion message unlocked").
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
printk_unlocked() serves callers that know they cannot lock, not the ones
that find out too late. A fault taken inside printk() leaves the spinlock
held by a context about to die, so every later printk() blocks and the
crash report is lost along with everything after it. CONFIG_SPIN_VALIDATE
makes it louder rather than better: validation fails, the assertion is
reported through printk, and the system spins there repeating itself.
That happens on a uniprocessor too, where the lock is uncontended but
still recorded as held.
Converting call sites cannot fix it, because code reached after the
failure does not know it is in a crash. So make printk() itself aware:
printk_panic() switches it to the unlocked path and the reporting paths
call it before emitting anything.
The switch is one way. Clearing it would also require releasing the
orphaned lock, and telling "orphaned" from "held by a CPU that is still
running" needs the owner, which only CONFIG_SPIN_VALIDATE records. So a
system that has reported a fatal error keeps unserialized output for the
rest of its life, which costs interleaving and no content.
Linux does the same: bust_spinlocks(), called from its oops and panic
paths, raises oops_in_progress so printk skips console locking. This
mechanism is narrower, printk simply stops locking, but the reasoning is
identical.
Because it cannot be undone, it must only be thrown once the fault is
terminal, which rules out the architecture entry points: several return.
z_arm64_fatal_error() resumes once demand paging has serviced the fault,
so switching there would cost a paging system its printk locking on the
first page fault. EXCEPTION_DUMP() runs only after the recoverable cases
are ruled out and also covers arch-specific dumps such as the Cortex-M
one behind PR_FAULT_INFO, and z_fatal_error() covers reports with no
dump, like k_panic() from a failed assertion. OpenRISC switches at entry
because it reports with LOG_ERR(), which is safe there since its handler
never returns.
k_str_out() shares the lock and honours the switch, so crashes reported
through printf() or puts() are covered too.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
An assertion can fire from inside printk()'s own locked region, where
reporting through vprintk() takes a spinlock this CPU already holds. The
lock is not recursive, so the message never appears and the CPU hangs
where it was supposed to say what went wrong. CONFIG_SPIN_VALIDATE makes
that worse: the validation failure is itself reported through
assert_print(), so it recurses until the stack is gone. The lock may
equally be held by another CPU that cannot release it, which is the
situation an assertion is likely reporting.
Use vprintk_unlocked() so the message goes out regardless.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
printk() is unusable where its spinlock cannot be taken, and Zephyr has
no answer for any of the three cases. A fatal error or failed assertion
may happen with the lock held, by the failing context itself or by a CPU
that will never release it, so reporting hangs instead of printing. An
assertion firing mid-message deadlocks on the same non-recursive lock.
And on some architectures the atomics a spinlock is built from do not
work until the MMU is on, so an early printk() faults.
Add printk_unlocked() and vprintk_unlocked(). They never take the lock,
and bypass the logging subsystem and the user mode buffer because those
have locks of their own, going straight to the platform's character
output hook. Output may interleave with a concurrent printk(), which
beats deadlocking or losing it.
Formatting is factored into vprintk_core() and shared with printk(), so
both produce identical text and only the locking differs. Nothing changes
for existing callers.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Add prompt to CBPRINTF_CONVERT_CHECK_PTR and extend the description.
Runtime string validation takes ~500 bytes of code (on riscv32) and
additional time when creating a log message so there are cases where
user would like to disable it.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
Refactor function to gain code space. Function takes significant
amount of code due to suboptimal implemention. Refactor to
reduce code (1200->800 on riscv32).
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
User code should not re-define prototypes defined in C library headers,
but, for prototypes of extensions (like strnlen()) should reuqest them
by setting the appropriate feature test macro.
So, instead of defining the strnlen() prototype in the user code, let's
set the appropriate SOURCE macro and get the prototype from its header
(string.h).
Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
The commented out CHECK() definition is an instruction to whoever
debugs the rbtree code, not code that is meant to be restored as is,
and MISRA C:2012 Directive 4.4 does not allow commented out code.
Fold it into the surrounding comment as a sentence. The empty CHECK()
definition that is actually compiled is unchanged.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
k_sleep() and k_usleep() resolve to an out of line implementation living in
another translation unit, a system call under CONFIG_USERSPACE and a plain
call otherwise. Either way the compiler sees neither whether the requested
duration is a constant nor whether the caller cares about the returned
value, so it always emits the tick to millisecond and microsecond
conversions. Those conversions are the only thing that drags the 64 bit
division helper into many small builds: CONFIG_SYS_CLOCK_TICKS_PER_SEC
defaults to 10000 on tickless platforms, which lands in the integer
division path and divides a 64 bit value by ten, something GCC will not
strength reduce on a 32 bit target.
Promote the former z_tick_sleep() helper to a k_sleep_ticks() system call
that reports the remaining time in ticks, and rebuild k_sleep() and
k_usleep() as inlines on top of it. The conversions now live at the call
site where the compiler can fold or discard them. Nearly every caller
discards them: of the 4036 sleep call sites in the tree, exactly six use
the returned value, and only three of those are outside of tests.
What this removes is best seen in the two out of line entry points that
disappear, which on a nucleo_f030r8 (Cortex-M0, 10000 ticks/s) were the
only two callers of the 64 bit division helper in the whole image:
08002594 <z_impl_k_sleep>:
bl 8001... <z_tick_sleep>
...
movs r0, #9 /* the ceil() bias, 10 - 1 */
adds r0, r0, r2
adcs r1, r3
movs r2, #10 /* ticks / 10 -> milliseconds */
bl 8000180 <__aeabi_uldivmod>
080025c0 <z_impl_k_usleep>:
movs r0, #99 /* the ceil() bias, 100 - 1 */
...
movs r2, #100 /* microseconds / 100 -> ticks */
bl 8000180 <__aeabi_uldivmod>
bl 8001... <z_tick_sleep>
Both are gone, and so are __aeabi_uldivmod and __udivmoddi4, which are no
longer referenced anywhere. A k_usleep(250) call site now passes the
literal 3 ticks the compiler worked out on its own, where it used to pass
250 microseconds to a helper that divided by 100 at runtime. For a loop
calling k_msleep(100), k_sleep(K_SECONDS(1)) and k_usleep(250) without
using the results, FLASH drops from 11028 to 10600 bytes.
Tracing stays in the out of line implementation. It cannot move into the
inlines because every tracing backend header includes kernel.h, so a
translation unit that reaches a backend header first would expand
SYS_PORT_TRACING_* before those macros exist. A consequence is that the
sleep_exit hook now reports ticks rather than milliseconds and the usleep
hook is no longer emitted; both are covered in a following commit.
The microsecond duration is clamped to zero the way Z_TIMEOUT_US() already
does. k_usleep() never did that, but it used to truncate the 64 bit
conversion into an int32_t before handing it over, which hid the worst of
it.
Passing the conversion through whole would turn a negative duration into a
sleep of roughly 1.8e17 ticks rather than a bogus absolute deadline.
This also removes a potential link error. k_usleep() had no
implementation at all with CONFIG_MULTITHREADING=n, since nothread.c only
ever provided z_impl_k_sleep(), so any caller failed to link. Nothing in
the tree happens to call it in that configuration, which is presumably why
it went unnoticed; a single z_impl_k_sleep_ticks() now serves both.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
MISRA C:2012 Rule 8.2 requires every parameter in a function type to
be named, including the parameters of function pointer parameters.
The object core walk callbacks, fnmatch() and the stdout hook were
declared with unnamed parameters.
Name them after the arguments the documentation already describes.
Declarations only, no functional change.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
'time' is reserved by the C standard for any use, so the locals in
timeutil_timegm64() and timeutil_timegm() violate MISRA C:2012
Rule 21.2 and shadow the <time.h> function.
Rename both to 'secs', which says what they hold. Pure rename.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
'round' is a standard library identifier reserved for any use, so
naming a local after it violates MISRA C:2012 Rule 21.2.
Rename it to 'rounding', which also reads better next to the comment
about rounding to the last printed digit. Pure rename.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The previous commit made the raw net_buf_simple add/push/pull/remove_mem
primitives fail-closed (return NULL) under CONFIG_NET_BUF_HARDENING, but
the typed scalar accessors that build on them still dereferenced the
returned pointer unconditionally: net_buf_simple_add_*/push_* store via
sys_put_*() into the add()/push() result, net_buf_simple_remove_* read
through the remove_mem() result, and net_buf_simple_pull_* read buf->data
before calling pull() (so pull()'s own guard came too late). On a
corrupted or overflowing buffer these turned the fail-closed NULL into a
NULL write/read (or, for pull_*, an out-of-bounds read), leaving a hole in
the hardening guarantee.
Route every typed accessor through the guard: add_*/push_* skip the store,
remove_*/pull_* return 0, and the pull_* helpers now read via the already
checked pull_mem() instead of touching buf->data first. Two small helper
macros keep the change mechanical and expand to the bare pointer when
hardening is disabled, so the non-hardened fast path is unchanged.
The fragmented net_buf_*_u8/le*/be* helpers only wrap the net_buf_simple_*
versions, so they inherit the protection with no further changes.
Add unit tests covering the add/pull/remove scalar accessors under a
corrupted length.
Assisted-by: Claude:opus-4.8
Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
Add CONFIG_NET_BUF_HARDENING, an opt-in (default off) set of always-on
integrity checks on the net_buf_simple length/pointer fields, evaluated
before a buffer is mutated. If a buffer's metadata has been corrupted so
that it no longer fits within its own storage -- for example len wrapped
to a large value, or data moved outside __buf..__buf+size -- the mutating
primitive is rejected fail-closed and returns NULL instead of reading or
writing out of bounds.
This turns a would-be out-of-bounds access (in particular the
tailroom-underflow that lets net_buf_add() overrun the buffer once len is
corrupt) into a controlled failure. net_buf_simple_is_valid() /
net_buf_is_valid() expose the check, and net_buf_simple_add()/add_mem()/
remove_mem()/push()/push_mem()/pull()/pull_mem() consult it. When the
option is disabled the fast path keeps the previous assert-only behaviour.
Add unit tests covering the validator (in-bounds, len boundary, wrapped
len, out-of-range data pointer) plus a hardening scenario that exercises
the fail-closed add/add_mem/pull paths.
Assisted-by: Claude:opus-4.8
Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
Add json_obj_separate_parse_init() and json_obj_next_key_value() to
walk a JSON object's top-level members without a compile-time
descriptor, returning each value as a raw span (scalars as their text,
objects and arrays as the whole balanced {...} / [...]). This serves
callers that dispatch each member to a handler chosen at run time,
where no single descriptor for the whole object exists. Built over the
existing object lexer; existing APIs unchanged.
Signed-off-by: Paulo Santos <pauloxrms@gmail.com>
In CONFIG_SCHED_CPU_MASK_PIN_ONLY mode a thread must always have
exactly one CPU bit set in its mask. The static_init() code was
unconditionally calling k_thread_cpu_mask_clear() for threads with
K_P4WQ_USER_CPU_MASK, which zeroes the mask and violates the
PIN_ONLY invariant.
After commit 7798570a03 this violation triggers an assertion in
cpu_mask_mod(), preventing SOF (and any other PIN_ONLY user of p4wq
with USER_CPU_MASK) from booting.
Fix by guarding the k_thread_cpu_mask_clear() call with
!CONFIG_SCHED_CPU_MASK_PIN_ONLY. Under PIN_ONLY the thread keeps
its default pin (CPU 0) until k_p4wq_enable_static_thread() sets the
real affinity via k_thread_cpu_pin().
Fixes: 7798570a03 ("kernel: sched: enforce non-zero CPU mask invariant
in PIN_ONLY mode")
Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
The store to 'max' immediately preceding the break in the exact/first
match branch is never read afterwards.
Remove it; 'max' remains initialized and read in the else-if comparison.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The periodic report and the threshold callback sampled cpu_load_get(),
i.e. the CPU that the timer happened to expire on. Which CPU that is on
SMP is arbitrary, and it is usually not the loaded one, so the reported
load and the callbacks described a CPU picked at random.
Iterate over the CPUs instead and report each one, so the report says
something well defined on SMP and the threshold callback fires for the
CPU that actually crossed it. On a single-CPU system this is exactly what
it did before, one report per period.
The initialization only resets the current CPU: SYS_INIT runs at
POST_KERNEL, while the secondary CPUs are brought up at INIT_LEVEL_SMP,
so their per-CPU kernel state does not exist yet and touching it faults.
The other CPUs simply start their first window at the first report.
Bound the iteration with arch_num_cpus() rather than the configured
maximum, so only CPUs that actually exist are sampled.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Idle time was only added to a CPU's total once its idle window closed. A
CPU that is idle right now still has an open window, so a reader on
another CPU saw no idle time at all for it and reported a 100% load for a
CPU that was doing nothing.
Fold the still-open window into the value returned by cpu_load_get_cpu(),
and re-open it at the sampling point when the window is reset so the idle
time just accounted for is not counted twice when it eventually closes.
This can only happen for a CPU other than the reader's own, which is by
definition not idle.
Two locking fixes come with it, both only reachable now that another CPU
can sample an open window:
- The idle-enter hook publishes enter_ts and the open flag under the
per-CPU lock, so a reader cannot observe a half-updated window.
- The idle-exit hook takes its timestamp under the lock. A reader that
moves enter_ts forward between the stamp and the lock would otherwise
make the delta go negative and wrap.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The idle-hook backend closed its idle window from the idle-exit hook that
the architecture runs after the wait instruction. That only works on
architectures which wait with interrupts locked (Arm, RISC-V): the wait
returns without servicing the interrupt, so the exit hook runs before any
ISR.
Architectures that wait with interrupts enabled (x86 "sti; hlt", Xtensa
"waiti 0") let the wake-up ISR run first, and it can reschedule away from
the idle thread. The idle-exit hook is then deferred until the idle thread
is next scheduled, long after idle actually ended, so the busy time in
between is attributed to idle. Measured on qemu_xtensa, a window that was
100% idle reported a load of 1000 per mille instead of 0.
Make closing the window idempotent and also drive it from the ISR entry
hook, sys_trace_isr_enter().
The first interrupt after the CPU went idle is exactly the instant idle
ended, so closing there is accurate; a deferred idle-exit hook then finds
the window already closed and does nothing. Interrupts that did not
interrupt idle only pay one flag test.
Architectures that wait with interrupts locked are unaffected: their
idle-exit hook still closes the window before any ISR runs.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The idle-hook CPU load backend kept a single global set of idle-tracking
state (enter_ts, cyc_start, ticks_idle), so it could only ever describe
one CPU and would race if several CPUs entered idle concurrently. That
is why it depended on !SMP.
Make the state per-CPU. The idle enter/exit hooks run on the idle CPU
with interrupts locked, so each CPU only mutates its own slot; a per-CPU
spinlock serializes the accumulation done in the exit hook against a
reader on another CPU calling cpu_load_get_cpu(). The !SMP dependency is
dropped.
The optional hardware counter path stays single-CPU, as a single shared
counter cannot track the idle time of several CPUs concurrently, so
CPU_LOAD_USE_COUNTER now depends on !SMP.
Replace the hard-coded architecture allowlist with a dependency on the
new ARCH_HAS_CPU_IDLE_HOOKS capability, which expresses the actual
requirement. Also guard against a division by zero when the measurement
window is empty, which back-to-back resets now make reachable.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The two CPU load modules that previously lived side by side (the
scheduler-runtime-statistics metric in lib/os/cpu_load_metric and the
idle-hook measurement in lib/os/cpu_load) are merged into a single
CONFIG_CPU_LOAD module with a pluggable backend selected through the
CPU_LOAD_BACKEND choice:
- CPU_LOAD_BACKEND_RUNTIME_STATS: scheduler runtime statistics,
portable and multi-CPU capable (formerly CPU_LOAD_METRIC).
- CPU_LOAD_BACKEND_IDLE_HOOK: architecture idle hooks, low overhead
with an optional hardware counter, single CPU.
A shared feature layer above the backends provides the current-CPU
getter, the periodic report timer and the threshold callback, so both
backends gain the periodic logging and callback features. The unified
getter pair returns the load in per mille:
int cpu_load_get(bool reset); /* current CPU */
int cpu_load_get_cpu(unsigned int cpu_id, bool reset);
CONFIG_CPU_LOAD_METRIC and cpu_load_metric_get() are kept as deprecated
compatibility wrappers; the latter returns percent as before. The
<zephyr/sys/cpu_load_metric.h> header now just includes
<zephyr/sys/cpu_load.h>. The tracing backends now gate the idle
accounting on CPU_LOAD_BACKEND_IDLE_HOOK rather than CPU_LOAD, since the
idle hooks only exist for that backend.
The cpu_freq on-demand policy is migrated to cpu_load_get_cpu() and
selects CPU_LOAD together with the new CPU_LOAD_MULTICPU helper to pull
in the runtime-statistics backend.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The idle-hook based CPU load module lived under subsys/debug, required
CONFIG_TRACING, and exposed its API through <zephyr/debug/cpu_load.h>.
It does not conceptually belong to the debug subsystem, and its only
dependency on tracing was the idle notification hooks, now available
through CONFIG_SYS_IDLE_HOOKS.
Move the module to lib/os/cpu_load with its own CMakeLists and Kconfig,
relocate the public header to <zephyr/sys/cpu_load.h>, and select
SYS_IDLE_HOOKS instead of TRACING. Update all includers (the tracing
backends, samples and tests) to the new header path.
CONFIG_CPU_LOAD now builds and runs without the tracing subsystem.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
The scheduler-runtime-stats based CPU load module lived in
lib/os/cpu_load and exposed cpu_load_metric_get() through
<zephyr/sys/cpu_load.h>. Its logging module name (CPU_LOAD) collided
with the idle-hook based CPU load module, and the shared directory and
header name made the two hard to tell apart.
Move the module to lib/os/cpu_load_metric, rename the source and public
header to cpu_load_metric.c and <zephyr/sys/cpu_load_metric.h>, and give
it its own log module (CPU_LOAD_METRIC) so the two no longer share a log
level symbol. Update the cpu_freq on-demand policy and its sample and
test to include the renamed header and use
CONFIG_CPU_LOAD_METRIC_LOG_LEVEL_DBG.
This frees the lib/os/cpu_load directory and the sys/cpu_load.h header
for the idle-hook based module, which moves there next.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Adds sys_ prefix to functions and typedef of the
word granular access library, as it is a sys API.
Signed-off-by: Lauren Murphy <lauren.murphy@intel.com>
The `cbprintf_cb` callback function taken by `cbvprintf()` may return a
negative number to indicate an I/O error. The `str_out()` function can
never error (it just copies the input to a buffer), but it always returns
its input. For regular ASCII input, this is merely nonsense; however, when
writing out a character with its MSB set (e.g., UTF-8-encoded text), the
character is sign-extended, and the function returns a negative number.
This is interpreted as an error by `outs()` (in `cbprintf_complete.c`), and
so printing concludes after a single character.
For example, prior to this change, the assertion in this snippet fails:
char buf[16];
int len = snprintfcb(buf, sizeof(buf), "\xED\xA0\xBD\xED\xB1\x8D");
assert(len == 6);
Signed-off-by: Samuel Coleman <samuel.coleman@rbr-global.com>
the boot banner is printed at the end of
the init process with
``SYS_INIT(boot_banner, APPLICATION, 0);``
we don't need the early console for it.
When CONFIG_EARLY_CONSOLE is enabled,
the console will init with PRE_KERNEL_1, otherwise
with POST_KERNEL. Both are before APPLICATION.
For compatibility `EARLY_CONSOLE` will now be enabled by default,
as it was selected by the boot banner before, that is also
enabled by default.
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
Adds library with memcpy and memset functions for
use with word granular access memory.
Signed-off-by: Lauren Murphy <lauren.murphy@intel.com>
Signed-off-by: Anthony Giardina <anthony.giardina@intel.com>
Added option CONFIG_LOG_PRINTK_STATIC which redirects printk's to
logging macro which creates message during compilation by examining
argument types using _Generic keyword. When this option is enabled
printk format string is not accessed in runtime so it can be removed
(e.g. in dictionary based logging). When this option is enabled printk
is much faster. Option is implied when dictionary based logging is
enabled.
The only condition that must be met to use build time message creation
macros is that format string is a string literal and not a variable.
That is the case for printk because it is using __printf_like gcc
extension to validate that.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
Lightweight write sanitizer for sys_heap. Uses
-fsanitize=kernel-address compiler instrumentation combined with a
per-heap shadow bitarray (one bit per granule) to detect buffer
overflows, underflows, and use-after-free on write accesses.
Ships its own lightweight sanitizer runtime (__asan_store* callbacks);
does not depend on an external ASAN library and supports debugging on
real embedded targets.
Instrumentation is opt-in per CMake target via
zephyr_target_enable_heap_kasan(), or per directory via
zephyr_heap_kasan_enable_directory(). Only writes are checked
(-asan-instrument-reads=0). Bulk-write library calls (memset,
memcpy, str*, printf family) are redirected to checked wrappers at
compile time via -Dfoo=__asan_foo, requiring no source changes in
application code.
Heap tracking is likewise opt-in: register each heap with
SYS_HEAP_KASAN_ENABLE() / K_HEAP_KASAN_ENABLE(), or enable
CONFIG_SYS_HEAP_KASAN_MALLOC / CONFIG_SYS_HEAP_KASAN_SYSTEM for the
common libc malloc and kernel system heaps.
Usage:
CONFIG_SYS_HEAP_KASAN=y
CONFIG_SYS_HEAP_KASAN_MALLOC=y # auto-track malloc/free
CONFIG_SYS_HEAP_KASAN_SYSTEM=y # auto-track k_malloc/k_free
# Instrument all sources of <target> (CMakeLists.txt)
zephyr_target_enable_heap_kasan(app)
# Or instrument sources under <dir>
zephyr_heap_kasan_enable_directory(src/mymodule)
/* Opt-in tracking for a custom heap */
K_HEAP_DEFINE(my_heap, 4096);
K_HEAP_KASAN_ENABLE(my_heap, 4096);
Signed-off-by: Jinming Zhao <jinmzhao@qti.qualcomm.com>
Change these (back) to the single use version, they have been changed
recently for "consistency" reasons but that seems to be incorrect.
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
Add a sys_heap sanitizer backend behind the SYS_HEAP_SANITIZER_HOOKS.
The backend integrates the toolchain's Address Sanitizer (ASAN) runtime
for use on native simulator based platforms.
The backend (heap_sanitizer_asan.c) implements the three hook entry
points as thin wrappers over the ASAN manual poisoning runtime:
sys_heap_init poisons the whole heap buffer, a successful allocation
unpoisons exactly the user-requested region and a free re-poisons the
usable region. Accesses to freed, never-allocated or out-of-bounds heap
memory are then reported by ASAN with a full backtrace and shadow dump.
The init hook runs at the end of sys_heap_init (after the bucket array
has been zeroed), so the chunk headers and internal metadata stay
poisoned for the lifetime of the heap and act as permanent redzones.
The heap implementation owns the bytes it poisons (chunk headers,
free-list links, canaries), so the heap internal sources are excluded
from ASAN instrumentation with -fno-sanitize=address. Those sources are
added to the root-scoped "zephyr" target, so the COMPILE_OPTIONS
property is set with TARGET_DIRECTORY; a plain
set_source_files_properties() in this directory does not reach the
target and leaves the sources instrumented.
SYS_HEAP_SANITIZER_ASAN requires the big-heap chunk format so the user
pointer and the end of the usable region are 8-byte aligned, matching
ASAN's shadow granularity (implied on 64-bit, explicit on 32-bit). The
runtime API and manual poisoning interface are common to GCC (libasan)
and Clang/LLVM (compiler-rt), so the feature is not tied to a single
compiler.
Verified on native_sim: in-bounds allocation and access across a range
of sizes is clean (no false positives) and a use-after-free is reported,
with both the host GCC and host LLVM toolchains.
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Introduce a single set of hook points so a heap memory sanitizer can be
plugged into sys_heap without scattering backend-specific conditionals
through heap.c.
A new internal header lib/heap/heap_sanitizer.h declares three entry
points:
heap_sanitizer_on_init (heap, mem, bytes) poison the whole heap buffer
heap_sanitizer_on_alloc(heap, mem, bytes) unpoison [mem, mem+bytes)
heap_sanitizer_on_free (heap, mem, bytes) re-poison the usable region
heap.c calls them at the public-API boundary (sys_heap_init,
sys_heap_alloc, sys_heap_aligned_alloc, sys_heap_free) gated on a hidden
CONFIG_SYS_HEAP_SANITIZER_HOOKS symbol that a backend selects. In-place
realloc is expressed as on_free(old_usable) followed by on_alloc(new),
which produces the correct shadow for both grow and shrink without a
dedicated re-poison helper.
The allocate-and-copy realloc fallback re-grants access to the source
block's full usable region around the internal memcpy (which a
reads-checking backend would otherwise keep poisoned past the requested
size) and lets the subsequent free re-poison it.
No backend is provided here, so CONFIG_SYS_HEAP_SANITIZER_HOOKS is
unset and the hooks compile to nothing: no functional change. Verified
that tests/lib/heap still passes on native_sim.
Assisted-by: Copilot:claude-opus-4.8
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Replace lowercase min() with the standard Zephyr MIN() macro
in sys_heap_realloc() and sys_heap_aligned_realloc() for
consistency with the rest of the codebase.
No functional change.
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
make_endpoint_info() and make_function_block_info() populate only the
first two words of the 128-bit UMP, leaving the remaining two words
uninitialised. They are sent verbatim, leaking 8 bytes of stack to any
UMP peer per request.
Zero-initialise the struct.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Similarly to the existing CONFIG_ZVFS_OPEN_ADD_SIZE_* mechanism used to
size the file descriptor table, allow subsystems to declare their eventfd
count requirements via CONFIG_ZVFS_EVENTFD_ADD_SIZE_* Kconfig options.
These are summed up at build time and compared against
CONFIG_ZVFS_EVENTFD_MAX, with the larger of the two values used to size
the eventfd table, exposed as the ZVFS_EVENTFD_SIZE compile definition.
A new CONFIG_ZVFS_EVENTFD_IGNORE_MIN option allows to override the
calculated requirement and use CONFIG_ZVFS_EVENTFD_MAX as-is.
As each eventfd also consumes a file descriptor, the resulting eventfd
count is now reserved in the file descriptor table as well, replacing the
former CONFIG_ZVFS_OPEN_ADD_SIZE_EVENTFD option which only accounted for
CONFIG_ZVFS_EVENTFD_MAX.
The WPA supplicant requirement is moved from a CONFIG_ZVFS_EVENTFD_MAX
default into a dedicated
CONFIG_ZVFS_EVENTFD_ADD_SIZE_WIFI_NM_WPA_SUPPLICANT option.
Assisted-by: Cursor:Claude Opus 4.8
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Replace z_unpend_first_thread() with z_unpend_first_thread_locked() and
migrate every caller across the kernel. The old function dropped the
scheduler spinlock before returning, exposing a race window between
its caller's "arch_thread_return_value_set + z_ready_thread" pair and
a still-in-flight timeout handler that could ready the thread first --
the woken thread might then run on another CPU and see an uninitialized
swap_retval. Pre-1b8c7a3 the dticks-cancel check made the handler bail;
here we fix it cleanly by requiring the caller to hold _sched_spinlock
across the entire wake, so the handler is blocked for the duration and
runs as a no-op afterwards.
z_unpend_first_thread_locked() requires the caller to be inside a
locked region and must be paired with z_sched_ready_locked() (and
whatever return-value setup is needed) under the same lock acquisition.
Sites migrated:
Simple "set retval [+ swap_data] and ready" callers use the existing
z_sched_wake() convenience wrapper, refactored to use the new
helper internally:
sem (give, reset), mem_slab (free), stack (push),
condvar (signal, broadcast), msgq (purge),
queue (cancel_wait, queue_insert, append_list),
futex (wake).
Sites that need additional setup on the woken thread use
LOCK_SCHED_SPINLOCK + z_unpend_first_thread_locked() + custom wake:
mutex (unlock -- needs the thread reference to track new owner),
msgq put / get (needs memcpy into the receiver's swap_data
buffer before the return value is set).
The dticks-cancel check in z_thread_timeout() is left in place; it is
no longer load-bearing once z_abort_thread_timeout() has no callers,
and is removed in the next commit.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Picolibc selects printf variants (minimal, integer, long-long, float)
via --defsym linker directives generated by GCC's picolibc.specs file.
Clang does not support specs files, so the -DPICOLIBC_*_PRINTF_SCANF
flags passed at link time were silently ignored, causing vfprintf to
always resolve to the full implementation regardless of configuration.
Signed-off-by: Adarsha Regmi <aregmi@qti.qualcomm.com>
The MWDT toolchain's <string.h> does not declare strsignal(),
which is a POSIX XSI extension. Without a declaration the
compiler treats calls to strsignal() as implicit int-returning
functions, causing the return value to be passed as a pointer:
error: incompatible integer to pointer conversion passing
'int' to parameter of type 'const void *'
Add the declaration alongside the existing strnlen() declaration.
The implementation is already provided by Zephyr's POSIX
portability subsystem in subsys/portability/posix/options/signal.c.
Signed-off-by: Mohamed Moawad <moawad@synopsys.com>