diff options
Diffstat (limited to 'common_smp/src/tx_thread_stack_analyze.c')
| -rw-r--r-- | common_smp/src/tx_thread_stack_analyze.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/common_smp/src/tx_thread_stack_analyze.c b/common_smp/src/tx_thread_stack_analyze.c index 080d0052..ecd7ee13 100644 --- a/common_smp/src/tx_thread_stack_analyze.c +++ b/common_smp/src/tx_thread_stack_analyze.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -70,6 +72,10 @@ TX_INTERRUPT_SAVE_AREA ULONG *stack_ptr; ULONG *stack_lowest; ULONG *stack_highest; +ULONG *probe_ptr; +ULONG *stack_limit; +ULONG probe_count; +UINT fill_present; ULONG size; @@ -94,10 +100,16 @@ ULONG size; /* 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) + /* Determine if the pointer is null or if the highest stack pointer is not above the + start of the stack. The latter indicates a stack overflow or a corrupted thread + control block, and the unsigned pointer arithmetic in the binary search below would + wrap around and never converge, hanging the caller. */ + if ((stack_highest != TX_NULL) && (stack_highest > stack_lowest)) { + /* Remember the upper bound of the search so the scan below cannot run past it. */ + stack_limit = stack_highest; + /* Restore interrupts. */ TX_RESTORE @@ -110,8 +122,49 @@ ULONG size; 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) + /* Determine if the pattern is still there. To avoid stopping on an + unwritten hole inside an otherwise used region, require several + consecutive fill words, working towards the lowest address. The scan + stops at the lowest known fill location, since everything at or below + that point is already known to hold the fill pattern. */ + fill_present = TX_TRUE; + probe_ptr = stack_ptr; + probe_count = TX_THREAD_STACK_ANALYZE_FILL_WORDS; + while (probe_count != ((ULONG) 0)) + { + + /* Determine if this word still holds the fill pattern. */ + if (*probe_ptr != TX_STACK_FILL) + { + + /* No, the probe location is in use. */ + fill_present = TX_FALSE; + probe_count = ((ULONG) 0); + } + else + { + + /* Yes, account for this word. */ + probe_count--; + + /* Determine if the lowest known fill location has been reached. */ + if (probe_ptr <= stack_lowest) + { + + /* Yes, nothing further to check. */ + probe_count = ((ULONG) 0); + } + else + { + + /* Position to the previous word in the stack. */ + probe_ptr = TX_ULONG_POINTER_SUB(probe_ptr, 1); + } + } + } + + /* Determine if the probe location is in use. */ + if (fill_present == TX_FALSE) { /* Update the stack highest, since we need to look in the upper half now. */ @@ -127,7 +180,7 @@ ULONG size; } while(size > ((ULONG) 1)); /* Position to first used word - at this point we are within a few words. */ - while (*stack_ptr == TX_STACK_FILL) + while ((stack_ptr < stack_limit) && (*stack_ptr == TX_STACK_FILL)) { /* Position to next word in stack. */ |
