Skip to content

Commit

Permalink
Two basic structures for consideration
Browse files Browse the repository at this point in the history
This is not a mergeable commit, as it includes modifications
to things that should not be committed upstream.
  • Loading branch information
Greg Link committed Jan 9, 2025
1 parent 485a02f commit 80dab41
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 49 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ target_sources(freertos-threadx
)
target_link_libraries(freertos-threadx PUBLIC threadx)


set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/custom_tx_user.h" CACHE PATH "Path to custom tx_user.h")

# If the user provided an override, copy it to the custom directory
if (NOT TX_USER_FILE)
message(STATUS "Using default tx_user.h file")
Expand All @@ -55,7 +58,7 @@ target_include_directories(${PROJECT_NAME}
PUBLIC
${CUSTOM_INC_DIR}
)
target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_INCLUDE_USER_DEFINE_FILE" )
target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_INCLUDE_USER_DEFINE_FILE" "TX_ENABLE_THREAD_SYSTEM_RESUME_EXTENSION")

# Enable a build target that produces a ZIP file of all sources
set(CPACK_SOURCE_GENERATOR "ZIP")
Expand Down
1 change: 1 addition & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_handler.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_notify.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_suspend.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_suspend_resume_extension.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_preempt_check.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_resume.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_suspend.c
Expand Down
23 changes: 21 additions & 2 deletions common/inc/tx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* tx_api.h PORTABLE C */
/* 6.4.1 */
/* 6.4.2 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
Expand Down Expand Up @@ -106,7 +106,10 @@
/* 03-01-2024 Tiejun Zhou Modified comment(s), */
/* update version number, */
/* resulting in version 6.4.1 */
/* */
/* XX-XX-2025 Greg Link Modified comment(s), */
/* update version number, */
/* add resume/suspend hooks, */
/* resulting in version 6.4.2 */
/**************************************************************************/

#ifndef TX_API_H
Expand Down Expand Up @@ -1779,6 +1782,22 @@ UINT _tx_thread_terminate(TX_THREAD *thread_ptr);
UINT _tx_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice);
UINT _tx_thread_wait_abort(TX_THREAD *thread_ptr);

/* Two alternative ways to include the proposed extensions of Issue 426.
The first expects the extension to always have the same function prototype,
but it is a proper function, while the second uses a #define in tx_user.h
to extend the functionality instead. */

#ifdef TX_ENABLE_THREAD_SYSTEM_RESUME_EXTENSION
UINT _tx_thread_system_resume_extension(TX_THREAD *thread_ptr);
#define TX_THREAD_SYSTEM_RESUME_EXTENSION(a) _tx_thread_system_resume_extension(a)
#else
#warning TX_ENABLE_THREAD_SYSTEM_RESUME_EXTENSION is disabled
#define TX_THREAD_SYSTEM_RESUME_EXTENSION(a) ((void)(a))
#endif

#ifndef TX_THREAD_SYSTEM_SUSPEND_EXTENSION
#define TX_THREAD_SYSTEM_SUSPEND_EXTENSION(a) ((void)(a))
#endif

/* Define error checking shells for API services. These are only referenced by the
application. */
Expand Down
95 changes: 49 additions & 46 deletions common/src/tx_thread_resume.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,29 @@ TX_THREAD *saved_thread_ptr;
UINT saved_threshold = ((UINT) 0);

#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
UINT priority;
ULONG priority_bit;
TX_THREAD *head_ptr;
TX_THREAD *tail_ptr;
TX_THREAD *execute_ptr;
TX_THREAD *current_thread;
ULONG combined_flags;
UINT priority;
ULONG priority_bit;
TX_THREAD *head_ptr;
TX_THREAD *tail_ptr;
TX_THREAD *execute_ptr;
TX_THREAD *current_thread;
ULONG combined_flags;

#ifdef TX_ENABLE_EVENT_TRACE
TX_TRACE_BUFFER_ENTRY *entry_ptr;
ULONG time_stamp = ((ULONG) 0);
#endif
#ifdef TX_ENABLE_EVENT_TRACE
TX_TRACE_BUFFER_ENTRY *entry_ptr;
ULONG time_stamp = ((ULONG) 0);
#endif

#if TX_MAX_PRIORITIES > 32
UINT map_index;
#endif
#if TX_MAX_PRIORITIES > 32
UINT map_index;
#endif


#ifdef TX_ENABLE_STACK_CHECKING
#ifdef TX_ENABLE_STACK_CHECKING

/* Check this thread's stack. */
TX_THREAD_STACK_CHECK(thread_ptr)
#endif
/* Check this thread's stack. */
TX_THREAD_STACK_CHECK(thread_ptr)
#endif
#endif

/* Lockout interrupts while the thread is being resumed. */
Expand Down Expand Up @@ -156,14 +156,14 @@ UINT map_index;

#ifndef TX_INLINE_THREAD_RESUME_SUSPEND

#ifdef TX_NOT_INTERRUPTABLE
#ifdef TX_NOT_INTERRUPTABLE

/* Resume the thread! */
_tx_thread_system_ni_resume(thread_ptr);

/* Restore interrupts. */
TX_RESTORE
#else
#else

/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
Expand All @@ -173,7 +173,7 @@ UINT map_index;

/* Call the actual resume service to resume the thread. */
_tx_thread_system_resume(thread_ptr);
#endif
#endif

/* Determine if the thread's preemption-threshold needs to be restored. */
if (saved_thread_ptr != TX_NULL)
Expand All @@ -184,18 +184,18 @@ UINT map_index;
saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
}

#ifdef TX_MISRA_ENABLE
#ifdef TX_MISRA_ENABLE

/* Disable interrupts. */
TX_DISABLE

/* Setup successful return status. */
status = TX_SUCCESS;
#else
#else

/* Return successful completion. */
return(TX_SUCCESS);
#endif
#endif


#else
Expand All @@ -205,16 +205,16 @@ UINT map_index;

/* Resume the thread! */

#ifdef TX_ENABLE_EVENT_TRACE
#ifdef TX_ENABLE_EVENT_TRACE

/* If trace is enabled, save the current event pointer. */
entry_ptr = _tx_trace_buffer_current_ptr;
#endif
#endif

/* Log the thread status change. */
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&execute_ptr), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS)

#ifdef TX_ENABLE_EVENT_TRACE
#ifdef TX_ENABLE_EVENT_TRACE

/* Save the time stamp for later comparison to verify that
the event hasn't been overwritten by the time we have
Expand All @@ -225,7 +225,7 @@ UINT map_index;
/* Save time stamp. */
time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
}
#endif
#endif

/* Make this thread ready. */

Expand All @@ -241,14 +241,17 @@ UINT map_index;
/* Log the thread status change. */
TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)

#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
/* Handle the thread resume extension, if defined*/
TX_THREAD_SYSTEM_RESUME_EXTENSION(thread_ptr);

#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO

/* Increment the total number of thread resumptions. */
_tx_thread_performance_resume_count++;

/* Increment this thread's resume count. */
thread_ptr -> tx_thread_performance_resume_count++;
#endif
#endif

/* Determine if there are other threads at this priority that are
ready. */
Expand All @@ -261,15 +264,15 @@ UINT map_index;
thread_ptr -> tx_thread_ready_next = thread_ptr;
thread_ptr -> tx_thread_ready_previous = thread_ptr;

#if TX_MAX_PRIORITIES > 32
#if TX_MAX_PRIORITIES > 32

/* Calculate the index into the bit map array. */
map_index = priority/((UINT) 32);

/* Set the active bit to remember that the priority map has something set. */
TX_DIV32_BIT_SET(priority, priority_bit)
_tx_thread_priority_map_active = _tx_thread_priority_map_active | priority_bit;
#endif
#endif

/* Or in the thread's priority bit. */
TX_MOD32_BIT_SET(priority, priority_bit)
Expand Down Expand Up @@ -304,21 +307,21 @@ UINT map_index;
if (priority < execute_ptr -> tx_thread_preempt_threshold)
{

#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD

/* Determine if the preempted thread had preemption-threshold set. */
if (execute_ptr -> tx_thread_preempt_threshold != execute_ptr -> tx_thread_priority)
{

#if TX_MAX_PRIORITIES > 32
#if TX_MAX_PRIORITIES > 32

/* Calculate the index into the bit map array. */
map_index = (execute_ptr -> tx_thread_priority)/((UINT) 32);

/* Set the active bit to remember that the preempt map has something set. */
TX_DIV32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit)
_tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit;
#endif
#endif

/* Remember that this thread was preempted by a thread above the thread's threshold. */
TX_MOD32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit)
Expand Down Expand Up @@ -372,7 +375,7 @@ UINT map_index;
saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
}

#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO

/* Is the execute pointer different? */
if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr)
Expand All @@ -392,9 +395,9 @@ UINT map_index;
/* Log the new execute pointer. */
_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
}
#endif
#endif

#ifdef TX_ENABLE_EVENT_TRACE
#ifdef TX_ENABLE_EVENT_TRACE

/* Check that the event time stamp is unchanged. A different
timestamp means that a later event wrote over the thread
Expand All @@ -411,31 +414,31 @@ UINT map_index;
entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
}
}
#endif
#endif

/* Restore interrupts. */
TX_RESTORE

#ifdef TX_ENABLE_STACK_CHECKING
#ifdef TX_ENABLE_STACK_CHECKING

/* Pickup the next execute pointer. */
thread_ptr = _tx_thread_execute_ptr;

/* Check this thread's stack. */
TX_THREAD_STACK_CHECK(thread_ptr)
#endif
#endif

/* Now determine if preemption should take place. This is only possible if the current thread pointer is
not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */
TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags)
if (combined_flags == ((ULONG) 0))
{

#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO

/* There is another thread ready to run and will be scheduled upon return. */
_tx_thread_performance_non_idle_return_count++;
#endif
#endif

/* Preemption is needed - return to the system! */
_tx_thread_system_return();
Expand Down Expand Up @@ -499,11 +502,11 @@ UINT map_index;

/* Timestamp is the same, set the "next thread pointer" to NULL. This can
be used by the trace analysis tool to show idle system conditions. */
#ifdef TX_MISRA_ENABLE
#ifdef TX_MISRA_ENABLE
entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
#else
#else
entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
#endif
#endif
}
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions common/src/tx_thread_suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ ULONG time_stamp = ((ULONG) 0);
/* Log the thread status change. */
TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state)


/* Handle the thread suspend extension, if defined*/
TX_THREAD_SYSTEM_SUSPEND_EXTENSION(thread_ptr);

#ifdef TX_ENABLE_EVENT_TRACE

/* If trace is enabled, save the current event pointer. */
Expand Down
34 changes: 34 additions & 0 deletions common/src/tx_thread_suspend_resume_extension.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/***************************************************************************
* Copyright (c) 2025 Microsoft Corporation
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/

/* Include necessary system files. */

#include "tx_api.h"
#include "tx_trace.h"
#include "tx_thread.h"
#include "tx_initialize.h"

/* Test only, demo of user extension. If the below is not defined,
no need to include this function at all - it will never be called */
#ifdef TX_ENABLE_THREAD_SYSTEM_RESUME_EXTENSION

UINT _tx_thread_system_resume_extension(TX_THREAD *thread_ptr)
{
UINT status = 0;
if (!thread_ptr->resume_recorded)
{
thread_ptr->resume_recorded_at += 1;
}

/* Return completion status. */
return(status);
}

#endif //TX_ENABLE_THREAD_SYSTEM_RESUME_EXTENSION
Loading

0 comments on commit 80dab41

Please sign in to comment.