summaryrefslogtreecommitdiff
path: root/common/src/tx_thread_stack_analyze.c
diff options
context:
space:
mode:
authorPProvost <[email protected]>2020-05-11 08:55:07 -0600
committerPProvost <[email protected]>2020-05-11 08:55:07 -0600
commit852421fda03a7722d7adb45b187235cd66fa264e (patch)
treeb117e1339a047347a3d7ebf3eeb1891168cc9b9b /common/src/tx_thread_stack_analyze.c
Initial commit
Diffstat (limited to 'common/src/tx_thread_stack_analyze.c')
-rw-r--r--common/src/tx_thread_stack_analyze.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/common/src/tx_thread_stack_analyze.c b/common/src/tx_thread_stack_analyze.c
new file mode 100644
index 00000000..c690724d
--- /dev/null
+++ b/common/src/tx_thread_stack_analyze.c
@@ -0,0 +1,181 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_analyze PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function analyzes the stack to calculate the highest stack */
+/* pointer in the thread's stack. This can then be used to derive the */
+/* minimum amount of stack left for any given thread. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX internal code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG *stack_ptr;
+ULONG *stack_lowest;
+ULONG *stack_highest;
+ULONG size;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if the thread pointer is NULL. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Determine if the thread ID is invalid. */
+ if (thread_ptr -> tx_thread_id == TX_THREAD_ID)
+ {
+
+ /* Pickup the current stack variables. */
+ stack_lowest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start);
+
+ /* Determine if the pointer is null. */
+ if (stack_lowest != TX_NULL)
+ {
+
+ /* Pickup the highest stack pointer. */
+ stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr);
+
+ /* Determine if the pointer is null. */
+ if (stack_highest != TX_NULL)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* We need to binary search the remaining stack for missing 0xEFEFEFEF 32-bit data pattern.
+ This is a best effort algorithm to find the highest stack usage. */
+ do
+ {
+
+ /* Calculate the size again. */
+ size = (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2);
+ stack_ptr = TX_ULONG_POINTER_ADD(stack_lowest, size);
+
+ /* Determine if the pattern is still there. */
+ if (*stack_ptr != TX_STACK_FILL)
+ {
+
+ /* Update the stack highest, since we need to look in the upper half now. */
+ stack_highest = stack_ptr;
+ }
+ else
+ {
+
+ /* Update the stack lowest, since we need to look in the lower half now. */
+ stack_lowest = stack_ptr;
+ }
+
+ } while(size > ((ULONG) 1));
+
+ /* Position to first used word - at this point we are within a few words. */
+ while (*stack_ptr == TX_STACK_FILL)
+ {
+
+ /* Position to next word in stack. */
+ stack_ptr = TX_ULONG_POINTER_ADD(stack_ptr, 1);
+ }
+
+ /* Optional processing extension. */
+ TX_THREAD_STACK_ANALYZE_EXTENSION
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Check to see if the thread is still created. */
+ if (thread_ptr -> tx_thread_id == TX_THREAD_ID)
+ {
+
+ /* Yes, thread is still created. */
+
+ /* Now check the new highest stack pointer is past the stack start. */
+ if (stack_ptr > (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start)))
+ {
+
+ /* Yes, now check that the new highest stack pointer is less than the previous highest stack pointer. */
+ if (stack_ptr < (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr)))
+ {
+
+ /* Yes, is the current highest stack pointer pointing at used memory? */
+ if (*stack_ptr != TX_STACK_FILL)
+ {
+
+ /* Yes, setup the highest stack usage. */
+ thread_ptr -> tx_thread_stack_highest_ptr = stack_ptr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+