Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | /** * @file debug/stack.h * Stack usage analysis helpers */ /* * Copyright (c) 2015 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_DEBUG_STACK_H_ #define ZEPHYR_INCLUDE_DEBUG_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; } __deprecated static inline void stack_analyze(const char *name, const char *stack, unsigned int size) { if (IS_ENABLED(CONFIG_INIT_STACKS)) { LOG_MODULE_DECLARE(os, 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) DEPRECATED_MACRO \ do { \ stack_analyze(name, \ Z_THREAD_STACK_BUFFER(sym), \ K_THREAD_STACK_SIZEOF(sym)); \ } while (false) static inline void log_stack_usage(const struct k_thread *thread) { #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_THREAD_STACK_INFO) size_t unused, size = thread->stack_info.size; LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); if (k_thread_stack_space_get(thread, &unused) == 0) { unsigned int pcnt = ((size - unused) * 100U) / size; const char *tname; tname = k_thread_name_get((k_tid_t)thread); if (tname == NULL) { tname = "unknown"; } LOG_INF("%p (%s):\tunused %zu\tusage %zu / %zu (%u %%)", thread, log_strdup(tname), unused, size - unused, size, pcnt); } #endif } #endif /* ZEPHYR_INCLUDE_DEBUG_STACK_H_ */ |