This macro is slated for complete removal, as it's not possible on arches with an MPU stack guard to know the true buffer bounds without also knowing the runtime state of its associated thread. As removing this completely would be invasive to where we are in the 1.14 release, demote to a private kernel Z_ API instead. The current way that the macro is being used internally will not cause any undue harm, we just don't want any external code depending on it. The final work to remove this (and overhaul stack specification in general) will take place in 1.15 in the context of #14269 Fixes: #14766 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
92 lines
2.1 KiB
C
92 lines
2.1 KiB
C
/**
|
|
* @file stack.h
|
|
* Stack usage analysis helpers
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2015 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_MISC_STACK_H_
|
|
#define ZEPHYR_INCLUDE_MISC_STACK_H_
|
|
|
|
#include <logging/log.h>
|
|
#include <stdbool.h>
|
|
|
|
static inline size_t stack_unused_space_get(const char *stack, size_t size)
|
|
{
|
|
size_t unused = 0;
|
|
|
|
if (IS_ENABLED(CONFIG_INIT_STACKS)) {
|
|
const unsigned char *checked_stack =
|
|
(const unsigned char *)stack;
|
|
|
|
if (IS_ENABLED(CONFIG_STACK_SENTINEL)) {
|
|
/* First 4 bytes of the stack buffer reserved for the
|
|
* sentinel value, it won't be 0xAAAAAAAA for thread
|
|
* stacks.
|
|
*/
|
|
checked_stack += 4;
|
|
}
|
|
|
|
/* TODO Currently all supported platforms have stack growth down
|
|
* and there is no Kconfig option to configure it so this always
|
|
* build "else" branch.
|
|
* When support for platform with stack direction up
|
|
* (or configurable direction) is added this check should be
|
|
* confirmed that correct Kconfig option is used.
|
|
*/
|
|
if (IS_ENABLED(CONFIG_STACK_GROWS_UP)) {
|
|
for (size_t i = size; i > 0; i--) {
|
|
if (checked_stack[i - 1] == 0xaaU) {
|
|
unused++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (checked_stack[i] == 0xaaU) {
|
|
unused++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return unused;
|
|
}
|
|
|
|
static inline void stack_analyze(const char *name, const char *stack,
|
|
unsigned int size)
|
|
{
|
|
if (IS_ENABLED(CONFIG_INIT_STACKS)) {
|
|
LOG_MODULE_DECLARE(kernel, CONFIG_KERNEL_LOG_LEVEL);
|
|
|
|
unsigned int unused = stack_unused_space_get(stack, size);
|
|
unsigned int pcnt = ((size - unused) * 100U) / size;
|
|
|
|
LOG_INF("%s :\tunused %u\tusage %u / %u (%u %%)",
|
|
name, unused, size - unused, size, pcnt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Analyze stacks.
|
|
*
|
|
* Use this macro to get information about stack usage.
|
|
*
|
|
* @param name Name of the stack
|
|
* @param sym The symbol of the stack
|
|
*/
|
|
#define STACK_ANALYZE(name, sym) \
|
|
do { \
|
|
stack_analyze(name, \
|
|
Z_THREAD_STACK_BUFFER(sym), \
|
|
K_THREAD_STACK_SIZEOF(sym)); \
|
|
} while (false)
|
|
|
|
#endif /* ZEPHYR_INCLUDE_MISC_STACK_H_ */
|