1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** ThreadX Component */
17 /** */
18 /** Thread */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define TX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "tx_api.h"
29 #include "tx_thread.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _tx_thread_stack_analyze PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* William E. Lamie, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function analyzes the stack to calculate the highest stack */
45 /* pointer in the thread's stack. This can then be used to derive the */
46 /* minimum amount of stack left for any given thread. */
47 /* */
48 /* INPUT */
49 /* */
50 /* thread_ptr Thread control block pointer */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* None */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* ThreadX internal code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
69 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* */
72 /**************************************************************************/
_tx_thread_stack_analyze(TX_THREAD * thread_ptr)73 VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr)
74 {
75
76 TX_INTERRUPT_SAVE_AREA
77
78 ULONG *stack_ptr;
79 ULONG *stack_lowest;
80 ULONG *stack_highest;
81 ULONG size;
82
83
84 /* Disable interrupts. */
85 TX_DISABLE
86
87 /* Determine if the thread pointer is NULL. */
88 if (thread_ptr != TX_NULL)
89 {
90
91 /* Determine if the thread ID is invalid. */
92 if (thread_ptr -> tx_thread_id == TX_THREAD_ID)
93 {
94
95 /* Pickup the current stack variables. */
96 stack_lowest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start);
97
98 /* Determine if the pointer is null. */
99 if (stack_lowest != TX_NULL)
100 {
101
102 /* Pickup the highest stack pointer. */
103 stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr);
104
105 /* Determine if the pointer is null. */
106 if (stack_highest != TX_NULL)
107 {
108
109 /* Restore interrupts. */
110 TX_RESTORE
111
112 /* We need to binary search the remaining stack for missing 0xEFEFEFEF 32-bit data pattern.
113 This is a best effort algorithm to find the highest stack usage. */
114 do
115 {
116
117 /* Calculate the size again. */
118 size = (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2);
119 stack_ptr = TX_ULONG_POINTER_ADD(stack_lowest, size);
120
121 /* Determine if the pattern is still there. */
122 if (*stack_ptr != TX_STACK_FILL)
123 {
124
125 /* Update the stack highest, since we need to look in the upper half now. */
126 stack_highest = stack_ptr;
127 }
128 else
129 {
130
131 /* Update the stack lowest, since we need to look in the lower half now. */
132 stack_lowest = stack_ptr;
133 }
134
135 } while(size > ((ULONG) 1));
136
137 /* Position to first used word - at this point we are within a few words. */
138 while (*stack_ptr == TX_STACK_FILL)
139 {
140
141 /* Position to next word in stack. */
142 stack_ptr = TX_ULONG_POINTER_ADD(stack_ptr, 1);
143 }
144
145 /* Optional processing extension. */
146 TX_THREAD_STACK_ANALYZE_EXTENSION
147
148 /* Disable interrupts. */
149 TX_DISABLE
150
151 /* Check to see if the thread is still created. */
152 if (thread_ptr -> tx_thread_id == TX_THREAD_ID)
153 {
154
155 /* Yes, thread is still created. */
156
157 /* Now check the new highest stack pointer is past the stack start. */
158 if (stack_ptr > (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start)))
159 {
160
161 /* Yes, now check that the new highest stack pointer is less than the previous highest stack pointer. */
162 if (stack_ptr < (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr)))
163 {
164
165 /* Yes, is the current highest stack pointer pointing at used memory? */
166 if (*stack_ptr != TX_STACK_FILL)
167 {
168
169 /* Yes, setup the highest stack usage. */
170 thread_ptr -> tx_thread_stack_highest_ptr = stack_ptr;
171 }
172 }
173 }
174 }
175 }
176 }
177 }
178 }
179
180 /* Restore interrupts. */
181 TX_RESTORE
182 }
183
184