1 /**
2  * @file stack.h
3  * Stack usage analysis helpers
4  */
5 
6 /*
7  * Copyright (c) 2015 Intel Corporation
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #ifndef _MISC_STACK_H_
13 #define _MISC_STACK_H_
14 
15 #include <misc/printk.h>
16 
17 #if defined(CONFIG_INIT_STACKS)
stack_unused_space_get(const char * stack,size_t size)18 static inline size_t stack_unused_space_get(const char *stack, size_t size)
19 {
20 	size_t unused = 0;
21 	int i;
22 
23 	/* TODO Currently all supported platforms have stack growth down and
24 	 * there is no Kconfig option to configure it so this always build
25 	 * "else" branch.  When support for platform with stack direction up
26 	 * (or configurable direction) is added this check should be confirmed
27 	 * that correct Kconfig option is used.
28 	 */
29 #if defined(STACK_GROWS_UP)
30 	for (i = size - 1; i >= 0; i--) {
31 		if ((unsigned char)stack[i] == 0xaa) {
32 			unused++;
33 		} else {
34 			break;
35 		}
36 	}
37 #else
38 	for (i = 0; i < size; i++) {
39 		if ((unsigned char)stack[i] == 0xaa) {
40 			unused++;
41 		} else {
42 			break;
43 		}
44 	}
45 #endif
46 	return unused;
47 }
48 #else
stack_unused_space_get(const char * stack,size_t size)49 static inline size_t stack_unused_space_get(const char *stack, size_t size)
50 {
51 	return 0;
52 }
53 #endif
54 
55 #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_PRINTK)
stack_analyze(const char * name,const char * stack,unsigned int size)56 static inline void stack_analyze(const char *name, const char *stack,
57 				 unsigned int size)
58 {
59 	unsigned int pcnt, unused = 0;
60 
61 	unused = stack_unused_space_get(stack, size);
62 
63 	/* Calculate the real size reserved for the stack */
64 	pcnt = ((size - unused) * 100) / size;
65 
66 	printk("%s (real size %u):\tunused %u\tusage %u / %u (%u %%)\n", name,
67 	       size, unused, size - unused, size, pcnt);
68 }
69 #else
stack_analyze(const char * name,const char * stack,unsigned int size)70 static inline void stack_analyze(const char *name, const char *stack,
71 				 unsigned int size)
72 {
73 }
74 #endif
75 
76 #define STACK_ANALYZE(name, sym) \
77 	stack_analyze(name, K_THREAD_STACK_BUFFER(sym), \
78 		      K_THREAD_STACK_SIZEOF(sym))
79 
80 #endif /* _MISC_STACK_H_ */
81