summaryrefslogtreecommitdiff
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
Initial commit
-rwxr-xr-x.gitattributes40
-rw-r--r--.gitignore14
-rw-r--r--CMakeLists.txt44
-rw-r--r--LICENSE.txt246
-rw-r--r--LICENSED-HARDWARE.txt16
-rw-r--r--README.md1
-rw-r--r--TODO2
-rw-r--r--common/CMakeLists.txt208
-rw-r--r--common/inc/tx_api.h2208
-rw-r--r--common/inc/tx_block_pool.h146
-rw-r--r--common/inc/tx_byte_pool.h177
-rw-r--r--common/inc/tx_event_flags.h147
-rw-r--r--common/inc/tx_initialize.h111
-rw-r--r--common/inc/tx_mutex.h160
-rw-r--r--common/inc/tx_queue.h173
-rw-r--r--common/inc/tx_semaphore.h144
-rw-r--r--common/inc/tx_thread.h524
-rw-r--r--common/inc/tx_timer.h213
-rw-r--r--common/inc/tx_trace.h559
-rw-r--r--common/inc/tx_user_sample.h257
-rw-r--r--common/src/tx_block_allocate.c372
-rw-r--r--common/src/tx_block_pool_cleanup.c213
-rw-r--r--common/src/tx_block_pool_create.c213
-rw-r--r--common/src/tx_block_pool_delete.c207
-rw-r--r--common/src/tx_block_pool_info_get.c146
-rw-r--r--common/src/tx_block_pool_initialize.c129
-rw-r--r--common/src/tx_block_pool_performance_info_get.c201
-rw-r--r--common/src/tx_block_pool_performance_system_info_get.c173
-rw-r--r--common/src/tx_block_pool_prioritize.c249
-rw-r--r--common/src/tx_block_release.c204
-rw-r--r--common/src/tx_byte_allocate.c409
-rw-r--r--common/src/tx_byte_pool_cleanup.c212
-rw-r--r--common/src/tx_byte_pool_create.c197
-rw-r--r--common/src/tx_byte_pool_delete.c211
-rw-r--r--common/src/tx_byte_pool_info_get.c146
-rw-r--r--common/src/tx_byte_pool_initialize.c147
-rw-r--r--common/src/tx_byte_pool_performance_info_get.c253
-rw-r--r--common/src/tx_byte_pool_performance_system_info_get.c221
-rw-r--r--common/src/tx_byte_pool_prioritize.c249
-rw-r--r--common/src/tx_byte_pool_search.c350
-rw-r--r--common/src/tx_byte_release.c376
-rw-r--r--common/src/tx_event_flags_cleanup.c237
-rw-r--r--common/src/tx_event_flags_create.c141
-rw-r--r--common/src/tx_event_flags_delete.c207
-rw-r--r--common/src/tx_event_flags_get.c401
-rw-r--r--common/src/tx_event_flags_info_get.c143
-rw-r--r--common/src/tx_event_flags_initialize.c130
-rw-r--r--common/src/tx_event_flags_performance_info_get.c202
-rw-r--r--common/src/tx_event_flags_performance_system_info_get.c174
-rw-r--r--common/src/tx_event_flags_set.c620
-rw-r--r--common/src/tx_event_flags_set_notify.c107
-rw-r--r--common/src/tx_initialize_high_level.c150
-rw-r--r--common/src/tx_initialize_kernel_enter.c148
-rw-r--r--common/src/tx_initialize_kernel_setup.c100
-rw-r--r--common/src/tx_misra.c833
-rw-r--r--common/src/tx_mutex_cleanup.c313
-rw-r--r--common/src/tx_mutex_create.c146
-rw-r--r--common/src/tx_mutex_delete.c243
-rw-r--r--common/src/tx_mutex_get.c409
-rw-r--r--common/src/tx_mutex_info_get.c147
-rw-r--r--common/src/tx_mutex_initialize.c141
-rw-r--r--common/src/tx_mutex_performance_info_get.c230
-rw-r--r--common/src/tx_mutex_performance_system_info_get.c205
-rw-r--r--common/src/tx_mutex_prioritize.c265
-rw-r--r--common/src/tx_mutex_priority_change.c328
-rw-r--r--common/src/tx_mutex_put.c654
-rw-r--r--common/src/tx_queue_cleanup.c225
-rw-r--r--common/src/tx_queue_create.c170
-rw-r--r--common/src/tx_queue_delete.c206
-rw-r--r--common/src/tx_queue_flush.c205
-rw-r--r--common/src/tx_queue_front_send.c421
-rw-r--r--common/src/tx_queue_info_get.c145
-rw-r--r--common/src/tx_queue_initialize.c138
-rw-r--r--common/src/tx_queue_performance_info_get.c229
-rw-r--r--common/src/tx_queue_performance_system_info_get.c205
-rw-r--r--common/src/tx_queue_prioritize.c249
-rw-r--r--common/src/tx_queue_receive.c486
-rw-r--r--common/src/tx_queue_send.c426
-rw-r--r--common/src/tx_queue_send_notify.c107
-rw-r--r--common/src/tx_semaphore_ceiling_put.c243
-rw-r--r--common/src/tx_semaphore_cleanup.c215
-rw-r--r--common/src/tx_semaphore_create.c142
-rw-r--r--common/src/tx_semaphore_delete.c207
-rw-r--r--common/src/tx_semaphore_get.c232
-rw-r--r--common/src/tx_semaphore_info_get.c139
-rw-r--r--common/src/tx_semaphore_initialize.c129
-rw-r--r--common/src/tx_semaphore_performance_info_get.c201
-rw-r--r--common/src/tx_semaphore_performance_system_info_get.c174
-rw-r--r--common/src/tx_semaphore_prioritize.c251
-rw-r--r--common/src/tx_semaphore_put.c222
-rw-r--r--common/src/tx_semaphore_put_notify.c107
-rw-r--r--common/src/tx_thread_create.c360
-rw-r--r--common/src/tx_thread_delete.c166
-rw-r--r--common/src/tx_thread_entry_exit_notify.c109
-rw-r--r--common/src/tx_thread_identify.c103
-rw-r--r--common/src/tx_thread_info_get.c163
-rw-r--r--common/src/tx_thread_initialize.c448
-rw-r--r--common/src/tx_thread_performance_info_get.c297
-rw-r--r--common/src/tx_thread_performance_system_info_get.c287
-rw-r--r--common/src/tx_thread_preemption_change.c280
-rw-r--r--common/src/tx_thread_priority_change.c280
-rw-r--r--common/src/tx_thread_relinquish.c169
-rw-r--r--common/src/tx_thread_reset.c163
-rw-r--r--common/src/tx_thread_resume.c581
-rw-r--r--common/src/tx_thread_shell_entry.c201
-rw-r--r--common/src/tx_thread_sleep.c198
-rw-r--r--common/src/tx_thread_stack_analyze.c181
-rw-r--r--common/src/tx_thread_stack_error_handler.c105
-rw-r--r--common/src/tx_thread_stack_error_notify.c125
-rw-r--r--common/src/tx_thread_suspend.c843
-rw-r--r--common/src/tx_thread_system_preempt_check.c127
-rw-r--r--common/src/tx_thread_system_resume.c1002
-rw-r--r--common/src/tx_thread_system_suspend.c1218
-rw-r--r--common/src/tx_thread_terminate.c310
-rw-r--r--common/src/tx_thread_time_slice.c184
-rw-r--r--common/src/tx_thread_time_slice_change.c117
-rw-r--r--common/src/tx_thread_timeout.c164
-rw-r--r--common/src/tx_thread_wait_abort.c235
-rw-r--r--common/src/tx_time_get.c100
-rw-r--r--common/src/tx_time_set.c92
-rw-r--r--common/src/tx_timer_activate.c135
-rw-r--r--common/src/tx_timer_change.c103
-rw-r--r--common/src/tx_timer_create.c167
-rw-r--r--common/src/tx_timer_deactivate.c250
-rw-r--r--common/src/tx_timer_delete.c142
-rw-r--r--common/src/tx_timer_expiration_process.c477
-rw-r--r--common/src/tx_timer_info_get.c248
-rw-r--r--common/src/tx_timer_initialize.c304
-rw-r--r--common/src/tx_timer_performance_info_get.c214
-rw-r--r--common/src/tx_timer_performance_system_info_get.c187
-rw-r--r--common/src/tx_timer_system_activate.c164
-rw-r--r--common/src/tx_timer_system_deactivate.c132
-rw-r--r--common/src/tx_timer_thread_entry.c480
-rw-r--r--common/src/tx_trace_buffer_full_notify.c109
-rw-r--r--common/src/tx_trace_disable.c103
-rw-r--r--common/src/tx_trace_enable.c442
-rw-r--r--common/src/tx_trace_event_filter.c106
-rw-r--r--common/src/tx_trace_event_unfilter.c106
-rw-r--r--common/src/tx_trace_initialize.c152
-rw-r--r--common/src/tx_trace_interrupt_control.c104
-rw-r--r--common/src/tx_trace_isr_enter_insert.c108
-rw-r--r--common/src/tx_trace_isr_exit_insert.c108
-rw-r--r--common/src/tx_trace_object_register.c291
-rw-r--r--common/src/tx_trace_object_unregister.c131
-rw-r--r--common/src/tx_trace_user_event_insert.c160
-rw-r--r--common/src/txe_block_allocate.c160
-rw-r--r--common/src/txe_block_pool_create.c227
-rw-r--r--common/src/txe_block_pool_delete.c146
-rw-r--r--common/src/txe_block_pool_info_get.c114
-rw-r--r--common/src/txe_block_pool_prioritize.c101
-rw-r--r--common/src/txe_block_release.c123
-rw-r--r--common/src/txe_byte_allocate.c199
-rw-r--r--common/src/txe_byte_pool_create.c222
-rw-r--r--common/src/txe_byte_pool_delete.c144
-rw-r--r--common/src/txe_byte_pool_info_get.c113
-rw-r--r--common/src/txe_byte_pool_prioritize.c101
-rw-r--r--common/src/txe_byte_release.c135
-rw-r--r--common/src/txe_event_flags_create.c203
-rw-r--r--common/src/txe_event_flags_delete.c146
-rw-r--r--common/src/txe_event_flags_get.c177
-rw-r--r--common/src/txe_event_flags_info_get.c115
-rw-r--r--common/src/txe_event_flags_set.c126
-rw-r--r--common/src/txe_event_flags_set_notify.c104
-rw-r--r--common/src/txe_mutex_create.c221
-rw-r--r--common/src/txe_mutex_delete.c146
-rw-r--r--common/src/txe_mutex_get.c168
-rw-r--r--common/src/txe_mutex_info_get.c114
-rw-r--r--common/src/txe_mutex_prioritize.c101
-rw-r--r--common/src/txe_mutex_put.c124
-rw-r--r--common/src/txe_queue_create.c237
-rw-r--r--common/src/txe_queue_delete.c142
-rw-r--r--common/src/txe_queue_flush.c102
-rw-r--r--common/src/txe_queue_front_send.c158
-rw-r--r--common/src/txe_queue_info_get.c112
-rw-r--r--common/src/txe_queue_prioritize.c98
-rw-r--r--common/src/txe_queue_receive.c160
-rw-r--r--common/src/txe_queue_send.c158
-rw-r--r--common/src/txe_queue_send_notify.c103
-rw-r--r--common/src/txe_semaphore_ceiling_put.c113
-rw-r--r--common/src/txe_semaphore_create.c208
-rw-r--r--common/src/txe_semaphore_delete.c143
-rw-r--r--common/src/txe_semaphore_get.c148
-rw-r--r--common/src/txe_semaphore_info_get.c113
-rw-r--r--common/src/txe_semaphore_prioritize.c101
-rw-r--r--common/src/txe_semaphore_put.c101
-rw-r--r--common/src/txe_semaphore_put_notify.c104
-rw-r--r--common/src/txe_thread_create.c311
-rw-r--r--common/src/txe_thread_delete.c110
-rw-r--r--common/src/txe_thread_entry_exit_notify.c104
-rw-r--r--common/src/txe_thread_info_get.c117
-rw-r--r--common/src/txe_thread_preemption_change.c130
-rw-r--r--common/src/txe_thread_priority_change.c131
-rw-r--r--common/src/txe_thread_relinquish.c92
-rw-r--r--common/src/txe_thread_reset.c136
-rw-r--r--common/src/txe_thread_resume.c101
-rw-r--r--common/src/txe_thread_suspend.c103
-rw-r--r--common/src/txe_thread_terminate.c112
-rw-r--r--common/src/txe_thread_time_slice_change.c122
-rw-r--r--common/src/txe_thread_wait_abort.c101
-rw-r--r--common/src/txe_timer_activate.c101
-rw-r--r--common/src/txe_timer_change.c124
-rw-r--r--common/src/txe_timer_create.c237
-rw-r--r--common/src/txe_timer_deactivate.c102
-rw-r--r--common/src/txe_timer_delete.c143
-rw-r--r--common/src/txe_timer_info_get.c110
-rwxr-xr-xdocs/ThreadX_User_Guide.pdfbin0 -> 2836943 bytes
-rw-r--r--ports/cortex_m0/gnu/CMakeLists.txt21
-rw-r--r--ports/cortex_m0/gnu/inc/tx_port.h371
-rwxr-xr-xports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S185
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_context_restore.S96
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_context_save.S90
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_interrupt_control.S94
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S88
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S86
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_schedule.S278
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_stack_build.S149
-rwxr-xr-xports/cortex_m0/gnu/src/tx_thread_system_return.S97
-rwxr-xr-xports/cortex_m0/gnu/src/tx_timer_interrupt.S271
-rw-r--r--ports/cortex_m0/gnu/src/tx_vector_table_sample.S102
-rw-r--r--ports/cortex_m3/gnu/CMakeLists.txt19
-rw-r--r--ports/cortex_m3/gnu/inc/tx_port.h357
-rw-r--r--ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S244
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_context_restore.S96
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_context_save.S89
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S92
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_schedule.S252
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_stack_build.S148
-rw-r--r--ports/cortex_m3/gnu/src/tx_thread_system_return.S98
-rw-r--r--ports/cortex_m3/gnu/src/tx_timer_interrupt.S270
-rw-r--r--ports/cortex_m3/gnu/src/tx_vector_table_sample.S84
-rw-r--r--ports/cortex_m4/gnu/CMakeLists.txt19
-rw-r--r--ports/cortex_m4/gnu/inc/tx_port.h499
-rw-r--r--ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S240
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_context_restore.S96
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_context_save.S89
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S92
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_schedule.S296
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_stack_build.S148
-rw-r--r--ports/cortex_m4/gnu/src/tx_thread_system_return.S98
-rw-r--r--ports/cortex_m4/gnu/src/tx_timer_interrupt.S270
-rw-r--r--ports/cortex_m4/gnu/src/tx_vector_table_sample.S84
-rw-r--r--ports/cortex_m7/gnu/CMakeLists.txt17
-rw-r--r--ports/cortex_m7/gnu/inc/tx_port.h496
-rwxr-xr-xports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S239
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_context_restore.S96
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_context_save.S89
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_interrupt_control.S92
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_schedule.S296
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_stack_build.S148
-rwxr-xr-xports/cortex_m7/gnu/src/tx_thread_system_return.S98
-rwxr-xr-xports/cortex_m7/gnu/src/tx_timer_interrupt.S270
-rw-r--r--ports/cortex_m7/gnu/src/tx_vector_table_sample.S84
-rw-r--r--ports/linux/gnu/CMakeLists.txt25
-rw-r--r--ports/linux/gnu/inc/tx_port.h575
-rw-r--r--ports/linux/gnu/src/tx_initialize_low_level_sample.c443
-rw-r--r--ports/linux/gnu/src/tx_thread_context_restore.c163
-rw-r--r--ports/linux/gnu/src/tx_thread_context_save.c107
-rw-r--r--ports/linux/gnu/src/tx_thread_interrupt_control.c183
-rw-r--r--ports/linux/gnu/src/tx_thread_schedule.c264
-rw-r--r--ports/linux/gnu/src/tx_thread_stack_build.c153
-rw-r--r--ports/linux/gnu/src/tx_thread_system_return.c207
-rw-r--r--ports/linux/gnu/src/tx_timer_interrupt.c153
-rw-r--r--ports/win32/gnu/CMakeLists.txt18
-rw-r--r--samples/demo_threadx.c370
264 files changed, 54459 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100755
index 00000000..ee9315d0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,40 @@
+.git* export-ignore
+.hooks* export-ignore
+
+# Custom attribute to mark sources as using our C code style.
+[attr]our-c-style whitespace=tab-in-indent eol=lf format.clang-format-6.0
+
+# Custom attribute to mark sources as generated.
+# Do not perform whitespace checks. Do not format.
+[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-6.0
+
+bootstrap eol=lf
+configure eol=lf
+*.[1-9] eol=lf
+*.bash eol=lf
+*.sh eol=lf
+*.sh.in eol=lf
+
+*.bat eol=crlf
+*.bat.in eol=crlf
+*.sln eol=crlf
+*.vcproj eol=crlf
+
+*.pfx -text
+*.png -text
+*.png.in -text
+
+*.c our-c-style
+*.cc our-c-style
+*.cpp our-c-style
+*.cu our-c-style
+*.cxx our-c-style
+*.h our-c-style
+*.hh our-c-style
+*.hpp our-c-style
+*.hxx our-c-style
+*.notcu our-c-style
+
+*.cmake whitespace=tab-in-indent
+*.rst whitespace=tab-in-indent conflict-marker-size=79
+*.txt whitespace=tab-in-indent \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..9c33dc7f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+.vscode/
+_deps/
+build/
+CMakeFiles/
+CMakeScripts/
+CMakeLists.txt.user
+CMakeCache.txt
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..a6a08241
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
+
+# Set up the project
+project(threadx
+ VERSION 6.0.0
+ LANGUAGES C ASM
+)
+
+if(NOT DEFINED THREADX_ARCH)
+ message(FATAL_ERROR "Error: THREADX_ARCH not defined")
+endif()
+if(NOT DEFINED THREADX_TOOLCHAIN)
+ message(FATAL_ERROR "Error: THREADX_TOOLCHAIN not defined")
+endif()
+
+# Define our target library and an alias for consumers
+add_library(${PROJECT_NAME})
+add_library("azrtos::${PROJECT_NAME}" ALIAS ${PROJECT_NAME})
+
+# A place for generated/copied include files (no need to change)
+set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc)
+
+# Pick up the port specific variables and apply them
+add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN})
+
+# Pick up the common stuff
+add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common)
+
+
+
+
+# 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")
+ set(TX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/common/inc/tx_user_sample.h)
+else()
+ message(STATUS "Using custom tx_user.h file from ${UX_USER_FILE}")
+endif()
+configure_file(${TX_USER_FILE} ${CUSTOM_INC_DIR}/tx_user.h COPYONLY)
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CUSTOM_INC_DIR}
+)
+target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_INCLUDE_USER_DEFINE_FILE" )
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 00000000..76974a36
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,246 @@
+MICROSOFT SOFTWARE LICENSE TERMS
+
+MICROSOFT AZURE RTOS
+
+Shape
+
+These license terms are an agreement between you and Microsoft Corporation (or
+one of its affiliates). They apply to the software named above and any Microsoft
+services or software updates (except to the extent such services or updates are
+accompanied by new or additional terms, in which case those different terms
+apply prospectively and do not alter your or Microsoft’s rights relating to
+pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU
+HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.
+
+INSTALLATION AND USE RIGHTS.
+
+General. You may install and use the software and the included Microsoft
+applications solely for internal development, testing and evaluation purposes.
+Any distribution or production use requires a separate license as set forth in
+Section 2.
+
+Contributions. Microsoft welcomes contributions to this software. In the event
+that you make a contribution to this software you will be required to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and
+actually do, grant Microsoft the rights to use your contribution. For details,
+visit https://cla.microsoft.com.
+
+Included Microsoft Applications. The software includes other Microsoft
+applications which are governed by the licenses embedded in or made available
+with those applications.
+
+Third Party Components. The software may include third party components with
+separate legal notices or governed by other agreements, as may be described
+within the software or in the ThirdPartyNotices file(s) accompanying the
+software.
+
+Competitive Benchmarking. If you are a direct competitor, and you access or use
+the software for purposes of competitive benchmarking, analysis, or intelligence
+gathering, you waive as against Microsoft, its subsidiaries, and its affiliated
+companies (including prospectively) any competitive use, access, and
+benchmarking test restrictions in the terms governing your software to the
+extent your terms of use are, or purport to be, more restrictive than
+Microsoft’s terms. If you do not waive any such purported restrictions in the
+terms governing your software, you are not allowed to access or use this
+software, and will not do so.
+
+DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on
+microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file
+named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with
+the software you have the following rights in and to the software solely when
+used in combination with the hardware. In the event hardware is not listed in
+the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2.
+
+Distribution and Production Use Rights.
+
+You may use the software in production (e.g. program the modified or unmodified
+software to devices you own or control) and distribute (i.e. make available to
+third parties) the modified or unmodified binary image produced from this code.
+
+
+You may permit your device distributors or developers to copy and distribute the
+binary image as programmed or to be programmed to your devices.
+
+You may redistribute the unmodified or modified source to your device
+distributors or developers. Modifications must be clearly marked. Any
+redistribution in source code form must contain this license and any other
+licenses that accompany the software.
+
+Requirements. For any code you distribute, you must:
+
+when distributed in binary form, except as embedded in a device, include with
+such distribution the terms of this agreement;
+
+when distributed in source code form to distributors or developers of your
+devices, include with such distribution the terms of this agreement; and
+
+indemnify, defend and hold harmless Microsoft from any claims, including
+attorneys’ fees, related to the distribution or use of your devices, except to
+the extent that any claim is based solely on the unmodified software.
+
+Restrictions. You may not:
+
+use or modify the software to create a competing real time operating system
+software;
+
+remove any copyright notices or licenses contained in the software;
+
+use Microsoft’s trademarks or trade dress in your application in any way that
+suggests your device or application comes from or is endorsed by Microsoft;
+
+transfer individual components, specific libraries, classes, functions or code
+fragments of the software separately for purposes unrelated to the software; or
+
+use or distribute the software in any way that would subject the software or
+Microsoft’s intellectual property or technology to any other license terms.
+
+SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all
+other rights. Unless applicable law gives you more rights despite this
+limitation, you will not (and have no right to):
+
+remove, minimize, block, or modify any notices of Microsoft or its suppliers in
+the software;
+
+use the software in any way that is against the law or to create or propagate
+malware; or
+
+share, publish, distribute, or lease the software (except as permitted in
+Section 2 above), or provide the software as a stand-alone offering for others
+to use.
+
+DATA. This software may interact with other Microsoft products that collect data
+that is transmitted to Microsoft. To learn more about how Microsoft processes
+personal data we collect, please see the Microsoft Privacy Statement at
+https://go.microsoft.com/fwlink/?LinkId=248681.
+
+EXPORT RESTRICTIONS. You must comply with all domestic and international export
+laws and regulations that apply to the software, which include restrictions on
+destinations, end users, and end use. For further information on export
+restrictions, visit https://aka.ms/exporting.
+
+SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any
+support services for the software. Any support provided is “as is”, “with all
+faults”, and without warranty of any kind.
+
+UPDATES. Microsoft may periodically update the software. You may obtain updates
+only from Microsoft or Microsoft-authorized sources. Updates may not include or
+support all existing software features, services, or peripheral devices.
+
+TERMINATION. Without prejudice to any other rights, Microsoft may terminate this
+agreement if you fail to comply with any of its terms or conditions. In such
+event, you must destroy all copies of the software and all of its component
+parts.
+
+ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for
+supplements, updates, or third-party applications, is the entire agreement for
+the software. To the extent you have entered into a separate agreement with
+Microsoft relating specifically to the software, the terms in such agreement
+shall control.
+
+APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in
+the United States or Canada, the laws of the state or province where you live
+(or, if a business, where your principal place of business is located) govern
+the interpretation of this agreement, claims for its breach, and all other
+claims (including consumer protection, unfair competition, and tort claims),
+regardless of conflict of laws principles. If you acquired the software in any
+other country, its laws apply. If U.S. federal jurisdiction exists, you and
+Microsoft consent to exclusive jurisdiction and venue in the federal court in
+King County, Washington for all disputes heard in court. If not, you and
+Microsoft consent to exclusive jurisdiction and venue in the Superior Court of
+King County, Washington for all disputes heard in court.
+
+CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal
+rights. You may have other rights, including consumer rights, under the laws of
+your state or country. Separate and apart from your relationship with Microsoft,
+you may also have rights with respect to the party from which you acquired the
+software. This agreement does not change those other rights if the laws of your
+state or country do not permit it to do so. For example, if you acquired the
+software in one of the below regions, or mandatory country law applies, then the
+following provisions apply to you:
+
+Australia. You have statutory guarantees under the Australian Consumer Law and
+nothing in this agreement is intended to affect those rights.
+
+Germany and Austria.
+
+i.Warranty. The properly licensed software will perform substantially as
+described in any Microsoft materials that accompany the software. However,
+Microsoft gives no contractual guarantee in relation to the licensed software.
+
+ii.Limitation of Liability. In case of intentional conduct, gross negligence,
+claims based on the Product Liability Act, as well as, in case of death or
+personal or physical injury, Microsoft is liable according to the statutory law.
+
+
+Subject to the foregoing clause ii., Microsoft will only be liable for slight
+negligence if Microsoft is in breach of such material contractual obligations,
+the fulfillment of which facilitate the due performance of this agreement, the
+breach of which would endanger the purpose of this agreement and the compliance
+with which a party may constantly trust in (so-called "cardinal obligations").
+In other cases of slight negligence, Microsoft will not be liable for slight
+negligence.
+
+DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF
+USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO
+THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED
+WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT.
+
+LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING
+DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM
+MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT
+RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL,
+INDIRECT, OR INCIDENTAL DAMAGES.
+
+This limitation applies to (a) anything related to the software, services,
+content (including code) on third party Internet sites, or third party
+applications; and (b) claims for breach of contract, warranty, guarantee, or
+condition; strict liability, negligence, or other tort; or any other claim; in
+each case to the extent permitted by applicable law.
+
+It also applies even if Microsoft knew or should have known about the
+possibility of the damages. The above limitation or exclusion may not apply to
+you because your state, province, or country may not allow the exclusion or
+limitation of incidental, consequential, or other damages.
+
+
+
+Please note: As this software is distributed in Canada, some of the clauses in
+this agreement are provided below in French.
+
+Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce
+contrat sont fournies ci-dessous en français.
+
+EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel
+». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft
+n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits
+additionnels en vertu du droit local sur la protection des consommateurs, que ce
+contrat ne peut modifier. La ou elles sont permises par le droit locale, les
+garanties implicites de qualité marchande, d’adéquation à un usage particulier
+et d’absence de contrefaçon sont exclues.
+
+LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES
+DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une
+indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous
+ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris
+les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
+
+Cette limitation concerne:
+
+•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le
+code) figurant sur des sites Internet tiers ou dans des programmes tiers; et
+
+•les réclamations au titre de violation de contrat ou de garantie, ou au titre
+de responsabilité stricte, de négligence ou d’une autre faute dans la limite
+autorisée par la loi en vigueur.
+
+Elle s’applique également, même si Microsoft connaissait ou devrait connaître
+l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la
+limitation de responsabilité pour les dommages indirects, accessoires ou de
+quelque nature que ce soit, il se peut que la limitation ou l’exclusion
+ci-dessus ne s’appliquera pas à votre égard.
+
+EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous
+pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent
+contrat ne modifie pas les droits que vous confèrent les lois de votre pays si
+celles-ci ne le permettent pas. \ No newline at end of file
diff --git a/LICENSED-HARDWARE.txt b/LICENSED-HARDWARE.txt
new file mode 100644
index 00000000..77dd1abf
--- /dev/null
+++ b/LICENSED-HARDWARE.txt
@@ -0,0 +1,16 @@
+LICENSED HARDWARE LIST
+
+Last Updated: 2020-05-08
+
+Microsoft has entered into OEM Agreements with manufacturers of the following
+microprocessors and microcontrollers (the “hardware”) to enable those
+manufacturers to include and distribute Azure RTOS in certain hardware. If you
+have obtained and/or are developing on microprocessor(s) and/or
+microcontroller(s) (“hardware”) listed below you inherit the “Distribution and
+Production Use” rights in Section 2 of the Microsoft Software License Terms for
+Microsoft Azure RTOS. If hardware is not listed below, you do not have those
+rights.
+
+--------------------------------------------------------------------------------
+
+More coming soon. Please check back frequently for updates. \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..bf9a068d
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# ThreadX \ No newline at end of file
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..22e66890
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+TODO:
+
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
new file mode 100644
index 00000000..1df4e845
--- /dev/null
+++ b/common/CMakeLists.txt
@@ -0,0 +1,208 @@
+function(target_sources_if_not_overridden filename)
+ list(FIND TX_SRC_OVERRIDES ${filename} OVERRIDE_FOUND)
+ if( OVERRIDE_FOUND EQUAL -1 )
+ message(STATUS "** Using original ${filename} from common/src **")
+ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/${filename})
+ endif()
+endfunction()
+
+# These files can be overridden by setting them in the variable list named TX_SRC_OVERRIDES
+target_sources_if_not_overridden("tx_thread_delete.c")
+target_sources_if_not_overridden("tx_thread_reset.c")
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_release.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_search.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_release.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_high_level.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_enter.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_setup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_misra.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_priority_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_flush.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_front_send.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_receive.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_ceiling_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_cleanup.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_entry_exit_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_identify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_preemption_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_priority_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_relinquish.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_resume.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_shell_entry.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_sleep.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_analyze.c
+ ${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_system_preempt_check.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_resume.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_suspend.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_terminate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_timeout.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_wait_abort.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_set.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_activate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_deactivate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_expiration_process.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_system_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_activate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_deactivate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_thread_entry.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_buffer_full_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_disable.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_enable.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_filter.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_unfilter.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_initialize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_interrupt_control.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_enter_insert.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_exit_insert.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_register.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_unregister.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_user_event_insert.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_release.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_release.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_flush.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_front_send.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_receive.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_ceiling_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_prioritize.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_entry_exit_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_info_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_preemption_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_priority_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_relinquish.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_reset.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_resume.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_suspend.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_terminate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_time_slice_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_wait_abort.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_activate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_create.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_deactivate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_info_get.c
+
+ # {{END_TARGET_SOURCES}}
+)
+
+# Add the Common/inc directory to the project include list
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
+
diff --git a/common/inc/tx_api.h b/common/inc/tx_api.h
new file mode 100644
index 00000000..d73d995d
--- /dev/null
+++ b/common/inc/tx_api.h
@@ -0,0 +1,2208 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Application Interface (API) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* tx_api.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the basic Application Interface (API) to the */
+/* high-performance ThreadX real-time kernel. All service prototypes */
+/* and data structure definitions are defined in this file. */
+/* Please note that basic data type definitions and other architecture-*/
+/* specific information is contained in the file tx_port.h. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_API_H
+#define TX_API_H
+
+
+/* Determine if a C++ compiler is being used. If so, ensure that standard
+ C is used to process the API information. */
+
+#ifdef __cplusplus
+
+/* Yes, C++ compiler is present. Use standard C. */
+extern "C" {
+
+#endif
+
+
+/* Include the port-specific data type file. */
+
+#include "tx_port.h"
+
+
+/* Define basic constants for the ThreadX kernel. */
+
+
+/* Define the major/minor version information that can be used by the application
+ and the ThreadX source as well. */
+
+#define EL_PRODUCT_THREADX
+#define THREADX_MAJOR_VERSION 6
+#define THREADX_MINOR_VERSION 0
+
+
+/* API input parameters and general constants. */
+
+#define TX_NO_WAIT ((ULONG) 0)
+#define TX_WAIT_FOREVER ((ULONG) 0xFFFFFFFFUL)
+#define TX_AND ((UINT) 2)
+#define TX_AND_CLEAR ((UINT) 3)
+#define TX_OR ((UINT) 0)
+#define TX_OR_CLEAR ((UINT) 1)
+#define TX_1_ULONG ((UINT) 1)
+#define TX_2_ULONG ((UINT) 2)
+#define TX_4_ULONG ((UINT) 4)
+#define TX_8_ULONG ((UINT) 8)
+#define TX_16_ULONG ((UINT) 16)
+#define TX_NO_TIME_SLICE ((ULONG) 0)
+#define TX_AUTO_START ((UINT) 1)
+#define TX_DONT_START ((UINT) 0)
+#define TX_AUTO_ACTIVATE ((UINT) 1)
+#define TX_NO_ACTIVATE ((UINT) 0)
+#define TX_TRUE ((UINT) 1)
+#define TX_FALSE ((UINT) 0)
+#define TX_NULL ((void *) 0)
+#define TX_INHERIT ((UINT) 1)
+#define TX_NO_INHERIT ((UINT) 0)
+#define TX_THREAD_ENTRY ((UINT) 0)
+#define TX_THREAD_EXIT ((UINT) 1)
+#define TX_NO_SUSPENSIONS ((UINT) 0)
+#define TX_NO_MESSAGES ((UINT) 0)
+#define TX_EMPTY ((ULONG) 0)
+#define TX_CLEAR_ID ((ULONG) 0)
+#define TX_STACK_FILL ((ULONG) 0xEFEFEFEFUL)
+
+
+/* Thread execution state values. */
+
+#define TX_READY ((UINT) 0)
+#define TX_COMPLETED ((UINT) 1)
+#define TX_TERMINATED ((UINT) 2)
+#define TX_SUSPENDED ((UINT) 3)
+#define TX_SLEEP ((UINT) 4)
+#define TX_QUEUE_SUSP ((UINT) 5)
+#define TX_SEMAPHORE_SUSP ((UINT) 6)
+#define TX_EVENT_FLAG ((UINT) 7)
+#define TX_BLOCK_MEMORY ((UINT) 8)
+#define TX_BYTE_MEMORY ((UINT) 9)
+#define TX_IO_DRIVER ((UINT) 10)
+#define TX_FILE ((UINT) 11)
+#define TX_TCP_IP ((UINT) 12)
+#define TX_MUTEX_SUSP ((UINT) 13)
+
+
+/* API return values. */
+
+#define TX_SUCCESS ((UINT) 0x00)
+#define TX_DELETED ((UINT) 0x01)
+#define TX_NO_MEMORY ((UINT) 0x10)
+#define TX_POOL_ERROR ((UINT) 0x02)
+#define TX_PTR_ERROR ((UINT) 0x03)
+#define TX_WAIT_ERROR ((UINT) 0x04)
+#define TX_SIZE_ERROR ((UINT) 0x05)
+#define TX_GROUP_ERROR ((UINT) 0x06)
+#define TX_NO_EVENTS ((UINT) 0x07)
+#define TX_OPTION_ERROR ((UINT) 0x08)
+#define TX_QUEUE_ERROR ((UINT) 0x09)
+#define TX_QUEUE_EMPTY ((UINT) 0x0A)
+#define TX_QUEUE_FULL ((UINT) 0x0B)
+#define TX_SEMAPHORE_ERROR ((UINT) 0x0C)
+#define TX_NO_INSTANCE ((UINT) 0x0D)
+#define TX_THREAD_ERROR ((UINT) 0x0E)
+#define TX_PRIORITY_ERROR ((UINT) 0x0F)
+#define TX_START_ERROR ((UINT) 0x10)
+#define TX_DELETE_ERROR ((UINT) 0x11)
+#define TX_RESUME_ERROR ((UINT) 0x12)
+#define TX_CALLER_ERROR ((UINT) 0x13)
+#define TX_SUSPEND_ERROR ((UINT) 0x14)
+#define TX_TIMER_ERROR ((UINT) 0x15)
+#define TX_TICK_ERROR ((UINT) 0x16)
+#define TX_ACTIVATE_ERROR ((UINT) 0x17)
+#define TX_THRESH_ERROR ((UINT) 0x18)
+#define TX_SUSPEND_LIFTED ((UINT) 0x19)
+#define TX_WAIT_ABORTED ((UINT) 0x1A)
+#define TX_WAIT_ABORT_ERROR ((UINT) 0x1B)
+#define TX_MUTEX_ERROR ((UINT) 0x1C)
+#define TX_NOT_AVAILABLE ((UINT) 0x1D)
+#define TX_NOT_OWNED ((UINT) 0x1E)
+#define TX_INHERIT_ERROR ((UINT) 0x1F)
+#define TX_NOT_DONE ((UINT) 0x20)
+#define TX_CEILING_EXCEEDED ((UINT) 0x21)
+#define TX_INVALID_CEILING ((UINT) 0x22)
+#define TX_FEATURE_NOT_ENABLED ((UINT) 0xFF)
+
+
+/* Define the common timer tick reference for use by other middleware components. The default
+ value is 10ms, but may be replaced by a port specific version in tx_port.h or by the user
+ as a compilation option. */
+
+#ifndef TX_TIMER_TICKS_PER_SECOND
+#define TX_TIMER_TICKS_PER_SECOND ((ULONG) 100)
+#endif
+
+
+/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are:
+
+ ThreadX events: 1-199
+ FileX events: 200-299
+ NetX events: 300-599
+ USBX events: 600-999
+ GUIX events: 1000-1500
+
+ User-defined event numbers start at 4096 and continue through 65535, as defined by the constants
+ TX_TRACE_USER_EVENT_START and TX_TRACE_USER_EVENT_END, respectively. User events should be based
+ on these constants in case the user event number assignment is changed in future releases. */
+
+#define TX_TRACE_USER_EVENT_START 4096 /* I1, I2, I3, I4 are user defined */
+#define TX_TRACE_USER_EVENT_END 65535 /* I1, I2, I3, I4 are user defined */
+
+
+/* Define event filters that can be used to selectively disable certain events or groups of events. */
+
+#define TX_TRACE_ALL_EVENTS 0x000007FF /* All ThreadX events */
+#define TX_TRACE_INTERNAL_EVENTS 0x00000001 /* ThreadX internal events */
+#define TX_TRACE_BLOCK_POOL_EVENTS 0x00000002 /* ThreadX Block Pool events */
+#define TX_TRACE_BYTE_POOL_EVENTS 0x00000004 /* ThreadX Byte Pool events */
+#define TX_TRACE_EVENT_FLAGS_EVENTS 0x00000008 /* ThreadX Event Flags events */
+#define TX_TRACE_INTERRUPT_CONTROL_EVENT 0x00000010 /* ThreadX Interrupt Control events */
+#define TX_TRACE_MUTEX_EVENTS 0x00000020 /* ThreadX Mutex events */
+#define TX_TRACE_QUEUE_EVENTS 0x00000040 /* ThreadX Queue events */
+#define TX_TRACE_SEMAPHORE_EVENTS 0x00000080 /* ThreadX Semaphore events */
+#define TX_TRACE_THREAD_EVENTS 0x00000100 /* ThreadX Thread events */
+#define TX_TRACE_TIME_EVENTS 0x00000200 /* ThreadX Time events */
+#define TX_TRACE_TIMER_EVENTS 0x00000400 /* ThreadX Timer events */
+#define TX_TRACE_USER_EVENTS 0x80000000UL /* ThreadX User Events */
+
+
+/* Define basic alignment type used in block and byte pool operations. This data type must
+ be at least 32-bits in size and also be large enough to hold a pointer type. */
+
+#ifndef ALIGN_TYPE_DEFINED
+#define ALIGN_TYPE ULONG
+#endif
+
+
+/* Define the control block definitions for all system objects. */
+
+
+/* Define the basic timer management structures. These are the structures
+ used to manage thread sleep, timeout, and user timer requests. */
+
+/* Determine if the internal timer control block has an extension defined. If not,
+ define the extension to whitespace. */
+
+#ifndef TX_TIMER_INTERNAL_EXTENSION
+#define TX_TIMER_INTERNAL_EXTENSION
+#endif
+
+
+/* Define the common internal timer control block. */
+
+typedef struct TX_TIMER_INTERNAL_STRUCT
+{
+
+ /* Define the remaining ticks and re-initialization tick values. */
+ ULONG tx_timer_internal_remaining_ticks;
+ ULONG tx_timer_internal_re_initialize_ticks;
+
+ /* Define the timeout function and timeout function parameter. */
+ VOID (*tx_timer_internal_timeout_function)(ULONG id);
+ ULONG tx_timer_internal_timeout_param;
+
+
+ /* Define the next and previous internal link pointers for active
+ internal timers. */
+ struct TX_TIMER_INTERNAL_STRUCT
+ *tx_timer_internal_active_next,
+ *tx_timer_internal_active_previous;
+
+ /* Keep track of the pointer to the head of this list as well. */
+ struct TX_TIMER_INTERNAL_STRUCT
+ **tx_timer_internal_list_head;
+
+ /* Define optional extension to internal timer control block. */
+ TX_TIMER_INTERNAL_EXTENSION
+
+} TX_TIMER_INTERNAL;
+
+
+/* Determine if the timer control block has an extension defined. If not,
+ define the extension to whitespace. */
+
+#ifndef TX_TIMER_EXTENSION
+#define TX_TIMER_EXTENSION
+#endif
+
+
+/* Define the timer structure utilized by the application. */
+
+typedef struct TX_TIMER_STRUCT
+{
+
+ /* Define the timer ID used for error checking. */
+ ULONG tx_timer_id;
+
+ /* Define the timer's name. */
+ CHAR *tx_timer_name;
+
+ /* Define the actual contents of the timer. This is the block that
+ is used in the actual timer expiration processing. */
+ TX_TIMER_INTERNAL tx_timer_internal;
+
+ /* Define the pointers for the created list. */
+ struct TX_TIMER_STRUCT
+ *tx_timer_created_next,
+ *tx_timer_created_previous;
+
+ /* Define optional extension to timer control block. */
+ TX_TIMER_EXTENSION
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of timer activations. */
+ ULONG tx_timer_performance_activate_count;
+
+ /* Define the number of timer reactivations. */
+ ULONG tx_timer_performance_reactivate_count;
+
+ /* Define the number of timer deactivations. */
+ ULONG tx_timer_performance_deactivate_count;
+
+ /* Define the number of timer expirations. */
+ ULONG tx_timer_performance_expiration_count;
+
+ /* Define the total number of timer expiration adjustments. */
+ ULONG tx_timer_performance__expiration_adjust_count;
+#endif
+
+} TX_TIMER;
+
+
+/* ThreadX thread control block structure follows. Additional fields
+ can be added providing they are added after the information that is
+ referenced in the port-specific assembly code. */
+
+typedef struct TX_THREAD_STRUCT
+{
+ /* The first section of the control block contains critical
+ information that is referenced by the port-specific
+ assembly language code. Any changes in this section could
+ necessitate changes in the assembly language. */
+
+ ULONG tx_thread_id; /* Control block ID */
+ ULONG tx_thread_run_count; /* Thread's run counter */
+ VOID *tx_thread_stack_ptr; /* Thread's stack pointer */
+ VOID *tx_thread_stack_start; /* Stack starting address */
+ VOID *tx_thread_stack_end; /* Stack ending address */
+ ULONG tx_thread_stack_size; /* Stack size */
+ ULONG tx_thread_time_slice; /* Current time-slice */
+ ULONG tx_thread_new_time_slice; /* New time-slice */
+
+ /* Define pointers to the next and previous ready threads. */
+ struct TX_THREAD_STRUCT
+ *tx_thread_ready_next,
+ *tx_thread_ready_previous;
+
+ /***************************************************************/
+
+ /* Define the first port extension in the thread control block. This
+ is typically defined to whitespace or a pointer type in tx_port.h. */
+ TX_THREAD_EXTENSION_0
+
+ CHAR *tx_thread_name; /* Pointer to thread's name */
+ UINT tx_thread_priority; /* Priority of thread (0-1023) */
+ UINT tx_thread_state; /* Thread's execution state */
+ UINT tx_thread_delayed_suspend; /* Delayed suspend flag */
+ UINT tx_thread_suspending; /* Thread suspending flag */
+ UINT tx_thread_preempt_threshold; /* Preemption threshold */
+
+ /* Define the thread schedule hook. The usage of this is port/application specific,
+ but when used, the function pointer designated is called whenever the thread is
+ scheduled and unscheduled. */
+ VOID (*tx_thread_schedule_hook)(struct TX_THREAD_STRUCT *thread_ptr, ULONG id);
+
+ /* Nothing after this point is referenced by the target-specific
+ assembly language. Hence, information after this point can
+ be added to the control block providing the complete system
+ is recompiled. */
+
+ /* Define the thread's entry point and input parameter. */
+ VOID (*tx_thread_entry)(ULONG id);
+ ULONG tx_thread_entry_parameter;
+
+ /* Define the thread's timer block. This is used for thread
+ sleep and timeout requests. */
+ TX_TIMER_INTERNAL tx_thread_timer;
+
+ /* Define the thread's cleanup function and associated data. This
+ is used to cleanup various data structures when a thread
+ suspension is lifted or terminated either by the user or
+ a timeout. */
+ VOID (*tx_thread_suspend_cleanup)(struct TX_THREAD_STRUCT *thread_ptr, ULONG suspension_sequence);
+ VOID *tx_thread_suspend_control_block;
+ struct TX_THREAD_STRUCT
+ *tx_thread_suspended_next,
+ *tx_thread_suspended_previous;
+ ULONG tx_thread_suspend_info;
+ VOID *tx_thread_additional_suspend_info;
+ UINT tx_thread_suspend_option;
+ UINT tx_thread_suspend_status;
+
+ /* Define the second port extension in the thread control block. This
+ is typically defined to whitespace or a pointer type in tx_port.h. */
+ TX_THREAD_EXTENSION_1
+
+ /* Define pointers to the next and previous threads in the
+ created list. */
+ struct TX_THREAD_STRUCT
+ *tx_thread_created_next,
+ *tx_thread_created_previous;
+
+ /* Define the third port extension in the thread control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_THREAD_EXTENSION_2
+
+ /* Define a pointer type for FileX extensions. */
+ VOID *tx_thread_filex_ptr;
+
+ /* Define the priority inheritance variables. These will be used
+ to manage priority inheritance changes applied to this thread
+ as a result of mutex get operations. */
+ UINT tx_thread_user_priority;
+ UINT tx_thread_user_preempt_threshold;
+ UINT tx_thread_inherit_priority;
+
+ /* Define the owned mutex count and list head pointer. */
+ UINT tx_thread_owned_mutex_count;
+ struct TX_MUTEX_STRUCT
+ *tx_thread_owned_mutex_list;
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of times this thread is resumed. */
+ ULONG tx_thread_performance_resume_count;
+
+ /* Define the number of times this thread suspends. */
+ ULONG tx_thread_performance_suspend_count;
+
+ /* Define the number of times this thread is preempted by calling
+ a ThreadX API service. */
+ ULONG tx_thread_performance_solicited_preemption_count;
+
+ /* Define the number of times this thread is preempted by an
+ ISR calling a ThreadX API service. */
+ ULONG tx_thread_performance_interrupt_preemption_count;
+
+ /* Define the number of priority inversions for this thread. */
+ ULONG tx_thread_performance_priority_inversion_count;
+
+ /* Define the last thread pointer to preempt this thread. */
+ struct TX_THREAD_STRUCT
+ *tx_thread_performance_last_preempting_thread;
+
+ /* Define the total number of times this thread was time-sliced. */
+ ULONG tx_thread_performance_time_slice_count;
+
+ /* Define the total number of times this thread relinquishes. */
+ ULONG tx_thread_performance_relinquish_count;
+
+ /* Define the total number of times this thread had a timeout. */
+ ULONG tx_thread_performance_timeout_count;
+
+ /* Define the total number of times this thread had suspension lifted
+ because of the tx_thread_wait_abort service. */
+ ULONG tx_thread_performance_wait_abort_count;
+#endif
+
+ /* Define the highest stack pointer variable. */
+ VOID *tx_thread_stack_highest_ptr; /* Stack highest usage pointer */
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Define the application callback routine used to notify the application when
+ the thread is entered or exits. */
+ VOID (*tx_thread_entry_exit_notify)(struct TX_THREAD_STRUCT *thread_ptr, UINT type);
+#endif
+
+ /* Define the fourth port extension in the thread control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_THREAD_EXTENSION_3
+
+ /* Define suspension sequence number. This is used to ensure suspension is still valid when
+ cleanup routine executes. */
+ ULONG tx_thread_suspension_sequence;
+
+ /* Define the user extension field. This typically is defined
+ to white space, but some ports of ThreadX may need to have
+ additional fields in the thread control block. This is
+ defined in the file tx_port.h. */
+ TX_THREAD_USER_EXTENSION
+
+} TX_THREAD;
+
+
+/* Define the block memory pool structure utilized by the application. */
+
+typedef struct TX_BLOCK_POOL_STRUCT
+{
+
+ /* Define the block pool ID used for error checking. */
+ ULONG tx_block_pool_id;
+
+ /* Define the block pool's name. */
+ CHAR *tx_block_pool_name;
+
+ /* Define the number of available memory blocks in the pool. */
+ UINT tx_block_pool_available;
+
+ /* Save the initial number of blocks. */
+ UINT tx_block_pool_total;
+
+ /* Define the head pointer of the available block pool. */
+ UCHAR *tx_block_pool_available_list;
+
+ /* Save the start address of the block pool's memory area. */
+ UCHAR *tx_block_pool_start;
+
+ /* Save the block pool's size in bytes. */
+ ULONG tx_block_pool_size;
+
+ /* Save the individual memory block size - rounded for alignment. */
+ UINT tx_block_pool_block_size;
+
+ /* Define the block pool suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_block_pool_suspension_list;
+ UINT tx_block_pool_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_BLOCK_POOL_STRUCT
+ *tx_block_pool_created_next,
+ *tx_block_pool_created_previous;
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of block allocates. */
+ ULONG tx_block_pool_performance_allocate_count;
+
+ /* Define the number of block releases. */
+ ULONG tx_block_pool_performance_release_count;
+
+ /* Define the number of block pool suspensions. */
+ ULONG tx_block_pool_performance_suspension_count;
+
+ /* Define the number of block pool timeouts. */
+ ULONG tx_block_pool_performance_timeout_count;
+#endif
+
+ /* Define the port extension in the block pool control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_BLOCK_POOL_EXTENSION
+
+} TX_BLOCK_POOL;
+
+
+/* Determine if the byte allocate extension is defined. If not, define the
+ extension to whitespace. */
+
+#ifndef TX_BYTE_ALLOCATE_EXTENSION
+#define TX_BYTE_ALLOCATE_EXTENSION
+#endif
+
+
+/* Determine if the byte release extension is defined. If not, define the
+ extension to whitespace. */
+
+#ifndef TX_BYTE_RELEASE_EXTENSION
+#define TX_BYTE_RELEASE_EXTENSION
+#endif
+
+
+/* Define the byte memory pool structure utilized by the application. */
+
+typedef struct TX_BYTE_POOL_STRUCT
+{
+
+ /* Define the byte pool ID used for error checking. */
+ ULONG tx_byte_pool_id;
+
+ /* Define the byte pool's name. */
+ CHAR *tx_byte_pool_name;
+
+ /* Define the number of available bytes in the pool. */
+ ULONG tx_byte_pool_available;
+
+ /* Define the number of fragments in the pool. */
+ UINT tx_byte_pool_fragments;
+
+ /* Define the head pointer of byte pool. */
+ UCHAR *tx_byte_pool_list;
+
+ /* Define the search pointer used for initial searching for memory
+ in a byte pool. */
+ UCHAR *tx_byte_pool_search;
+
+ /* Save the start address of the byte pool's memory area. */
+ UCHAR *tx_byte_pool_start;
+
+ /* Save the byte pool's size in bytes. */
+ ULONG tx_byte_pool_size;
+
+ /* This is used to mark the owner of the byte memory pool during
+ a search. If this value changes during the search, the local search
+ pointer must be reset. */
+ struct TX_THREAD_STRUCT
+ *tx_byte_pool_owner;
+
+ /* Define the byte pool suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_byte_pool_suspension_list;
+ UINT tx_byte_pool_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_BYTE_POOL_STRUCT
+ *tx_byte_pool_created_next,
+ *tx_byte_pool_created_previous;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of allocates. */
+ ULONG tx_byte_pool_performance_allocate_count;
+
+ /* Define the number of releases. */
+ ULONG tx_byte_pool_performance_release_count;
+
+ /* Define the number of adjacent memory fragment merges. */
+ ULONG tx_byte_pool_performance_merge_count;
+
+ /* Define the number of memory fragment splits. */
+ ULONG tx_byte_pool_performance_split_count;
+
+ /* Define the number of memory fragments searched that either were not free or could not satisfy the
+ request. */
+ ULONG tx_byte_pool_performance_search_count;
+
+ /* Define the number of byte pool suspensions. */
+ ULONG tx_byte_pool_performance_suspension_count;
+
+ /* Define the number of byte pool timeouts. */
+ ULONG tx_byte_pool_performance_timeout_count;
+#endif
+
+ /* Define the port extension in the byte pool control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_BYTE_POOL_EXTENSION
+
+} TX_BYTE_POOL;
+
+
+/* Define the event flags group structure utilized by the application. */
+
+typedef struct TX_EVENT_FLAGS_GROUP_STRUCT
+{
+
+ /* Define the event flags group ID used for error checking. */
+ ULONG tx_event_flags_group_id;
+
+ /* Define the event flags group's name. */
+ CHAR *tx_event_flags_group_name;
+
+ /* Define the actual current event flags in this group. A zero in a
+ particular bit indicates the event flag is not set. */
+ ULONG tx_event_flags_group_current;
+
+ /* Define the reset search flag that is set when an ISR sets flags during
+ the search of the suspended threads list. */
+ UINT tx_event_flags_group_reset_search;
+
+ /* Define the event flags group suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_event_flags_group_suspension_list;
+ UINT tx_event_flags_group_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_EVENT_FLAGS_GROUP_STRUCT
+ *tx_event_flags_group_created_next,
+ *tx_event_flags_group_created_previous;
+
+ /* Define the delayed clearing event flags. */
+ ULONG tx_event_flags_group_delayed_clear;
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of event flag sets. */
+ ULONG tx_event_flags_group_performance_set_count;
+
+ /* Define the number of event flag gets. */
+ ULONG tx_event_flags_group__performance_get_count;
+
+ /* Define the number of event flag suspensions. */
+ ULONG tx_event_flags_group___performance_suspension_count;
+
+ /* Define the number of event flag timeouts. */
+ ULONG tx_event_flags_group____performance_timeout_count;
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Define the application callback routine used to notify the application when
+ an event flag is set. */
+ VOID (*tx_event_flags_group_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
+#endif
+
+ /* Define the port extension in the event flags group control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_EVENT_FLAGS_GROUP_EXTENSION
+
+} TX_EVENT_FLAGS_GROUP;
+
+
+/* Determine if the mutex put extension 1 is defined. If not, define the
+ extension to whitespace. */
+
+#ifndef TX_MUTEX_PUT_EXTENSION_1
+#define TX_MUTEX_PUT_EXTENSION_1
+#endif
+
+
+/* Determine if the mutex put extension 2 is defined. If not, define the
+ extension to whitespace. */
+
+#ifndef TX_MUTEX_PUT_EXTENSION_2
+#define TX_MUTEX_PUT_EXTENSION_2
+#endif
+
+
+/* Determine if the mutex priority change extension is defined. If not, define the
+ extension to whitespace. */
+
+#ifndef TX_MUTEX_PRIORITY_CHANGE_EXTENSION
+#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION
+#endif
+
+
+/* Define the mutex structure utilized by the application. */
+
+typedef struct TX_MUTEX_STRUCT
+{
+
+ /* Define the mutex ID used for error checking. */
+ ULONG tx_mutex_id;
+
+ /* Define the mutex's name. */
+ CHAR *tx_mutex_name;
+
+ /* Define the mutex ownership count. */
+ UINT tx_mutex_ownership_count;
+
+ /* Define the mutex ownership pointer. This pointer points to the
+ the thread that owns the mutex. */
+ TX_THREAD *tx_mutex_owner;
+
+ /* Define the priority inheritance flag. If this flag is set, priority
+ inheritance will be in effect. */
+ UINT tx_mutex_inherit;
+
+ /* Define the save area for the owning thread's original priority. */
+ UINT tx_mutex_original_priority;
+
+ /* Define the mutex suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_mutex_suspension_list;
+ UINT tx_mutex_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_MUTEX_STRUCT
+ *tx_mutex_created_next,
+ *tx_mutex_created_previous;
+
+ /* Define the priority of the highest priority thread waiting for
+ this mutex. */
+ UINT tx_mutex_highest_priority_waiting;
+
+ /* Define the owned list next and previous pointers. */
+ struct TX_MUTEX_STRUCT
+ *tx_mutex_owned_next,
+ *tx_mutex_owned_previous;
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of mutex puts. */
+ ULONG tx_mutex_performance_put_count;
+
+ /* Define the total number of mutex gets. */
+ ULONG tx_mutex_performance_get_count;
+
+ /* Define the total number of mutex suspensions. */
+ ULONG tx_mutex_performance_suspension_count;
+
+ /* Define the total number of mutex timeouts. */
+ ULONG tx_mutex_performance_timeout_count;
+
+ /* Define the total number of priority inversions. */
+ ULONG tx_mutex_performance_priority_inversion_count;
+
+ /* Define the total number of priority inheritance conditions. */
+ ULONG tx_mutex_performance__priority_inheritance_count;
+#endif
+
+ /* Define the port extension in the mutex control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_MUTEX_EXTENSION
+
+} TX_MUTEX;
+
+
+/* Define the queue structure utilized by the application. */
+
+typedef struct TX_QUEUE_STRUCT
+{
+
+ /* Define the queue ID used for error checking. */
+ ULONG tx_queue_id;
+
+ /* Define the queue's name. */
+ CHAR *tx_queue_name;
+
+ /* Define the message size that was specified in queue creation. */
+ UINT tx_queue_message_size;
+
+ /* Define the total number of messages in the queue. */
+ UINT tx_queue_capacity;
+
+ /* Define the current number of messages enqueued and the available
+ queue storage space. */
+ UINT tx_queue_enqueued;
+ UINT tx_queue_available_storage;
+
+ /* Define pointers that represent the start and end for the queue's
+ message area. */
+ ULONG *tx_queue_start;
+ ULONG *tx_queue_end;
+
+ /* Define the queue read and write pointers. Send requests use the write
+ pointer while receive requests use the read pointer. */
+ ULONG *tx_queue_read;
+ ULONG *tx_queue_write;
+
+ /* Define the queue suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_queue_suspension_list;
+ UINT tx_queue_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_QUEUE_STRUCT
+ *tx_queue_created_next,
+ *tx_queue_created_previous;
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of messages sent to this queue. */
+ ULONG tx_queue_performance_messages_sent_count;
+
+ /* Define the number of messages received from this queue. */
+ ULONG tx_queue_performance_messages_received_count;
+
+ /* Define the number of empty suspensions on this queue. */
+ ULONG tx_queue_performance_empty_suspension_count;
+
+ /* Define the number of full suspensions on this queue. */
+ ULONG tx_queue_performance_full_suspension_count;
+
+ /* Define the number of full non-suspensions on this queue. These
+ messages are rejected with an appropriate error code. */
+ ULONG tx_queue_performance_full_error_count;
+
+ /* Define the number of queue timeouts. */
+ ULONG tx_queue_performance_timeout_count;
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Define the application callback routine used to notify the application when
+ the a message is sent to the queue. */
+ VOID (*tx_queue_send_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
+#endif
+
+ /* Define the port extension in the queue control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_QUEUE_EXTENSION
+
+} TX_QUEUE;
+
+
+/* Define the semaphore structure utilized by the application. */
+
+typedef struct TX_SEMAPHORE_STRUCT
+{
+
+ /* Define the semaphore ID used for error checking. */
+ ULONG tx_semaphore_id;
+
+ /* Define the semaphore's name. */
+ CHAR *tx_semaphore_name;
+
+ /* Define the actual semaphore count. A zero means that no semaphore
+ instance is available. */
+ ULONG tx_semaphore_count;
+
+ /* Define the semaphore suspension list head along with a count of
+ how many threads are suspended. */
+ struct TX_THREAD_STRUCT
+ *tx_semaphore_suspension_list;
+ UINT tx_semaphore_suspended_count;
+
+ /* Define the created list next and previous pointers. */
+ struct TX_SEMAPHORE_STRUCT
+ *tx_semaphore_created_next,
+ *tx_semaphore_created_previous;
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Define the number of semaphore puts. */
+ ULONG tx_semaphore_performance_put_count;
+
+ /* Define the number of semaphore gets. */
+ ULONG tx_semaphore_performance_get_count;
+
+ /* Define the number of semaphore suspensions. */
+ ULONG tx_semaphore_performance_suspension_count;
+
+ /* Define the number of semaphore timeouts. */
+ ULONG tx_semaphore_performance_timeout_count;
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Define the application callback routine used to notify the application when
+ the a semaphore is put. */
+ VOID (*tx_semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
+#endif
+
+ /* Define the port extension in the semaphore control block. This
+ is typically defined to whitespace in tx_port.h. */
+ TX_SEMAPHORE_EXTENSION
+
+} TX_SEMAPHORE;
+
+
+/* Define the system API mappings based on the error checking
+ selected by the user. Note: this section is only applicable to
+ application source code, hence the conditional that turns off this
+ stuff when the include file is processed by the ThreadX source. */
+
+#ifndef TX_SOURCE_CODE
+
+
+/* Determine if error checking is desired. If so, map API functions
+ to the appropriate error checking front-ends. Otherwise, map API
+ functions to the core functions that actually perform the work.
+ Note: error checking is enabled by default. */
+
+#ifdef TX_DISABLE_ERROR_CHECKING
+
+
+/* Services without error checking. */
+
+#define tx_kernel_enter _tx_initialize_kernel_enter
+
+#define tx_block_allocate _tx_block_allocate
+#define tx_block_pool_create _tx_block_pool_create
+#define tx_block_pool_delete _tx_block_pool_delete
+#define tx_block_pool_info_get _tx_block_pool_info_get
+#define tx_block_pool_performance_info_get _tx_block_pool_performance_info_get
+#define tx_block_pool_performance_system_info_get _tx_block_pool_performance_system_info_get
+#define tx_block_pool_prioritize _tx_block_pool_prioritize
+#define tx_block_release _tx_block_release
+
+#define tx_byte_allocate _tx_byte_allocate
+#define tx_byte_pool_create _tx_byte_pool_create
+#define tx_byte_pool_delete _tx_byte_pool_delete
+#define tx_byte_pool_info_get _tx_byte_pool_info_get
+#define tx_byte_pool_performance_info_get _tx_byte_pool_performance_info_get
+#define tx_byte_pool_performance_system_info_get _tx_byte_pool_performance_system_info_get
+#define tx_byte_pool_prioritize _tx_byte_pool_prioritize
+#define tx_byte_release _tx_byte_release
+
+#define tx_event_flags_create _tx_event_flags_create
+#define tx_event_flags_delete _tx_event_flags_delete
+#define tx_event_flags_get _tx_event_flags_get
+#define tx_event_flags_info_get _tx_event_flags_info_get
+#define tx_event_flags_performance_info_get _tx_event_flags_performance_info_get
+#define tx_event_flags_performance_system_info_get _tx_event_flags_performance_system_info_get
+#define tx_event_flags_set _tx_event_flags_set
+#define tx_event_flags_set_notify _tx_event_flags_set_notify
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+UINT _tx_el_interrupt_control(UINT new_posture);
+#define tx_interrupt_control _tx_el_interrupt_control
+#else
+#ifdef TX_ENABLE_EVENT_TRACE
+UINT _tx_trace_interrupt_control(UINT new_posture);
+#define tx_interrupt_control _tx_trace_interrupt_control
+#else
+#define tx_interrupt_control _tx_thread_interrupt_control
+#endif
+#endif
+
+#define tx_mutex_create _tx_mutex_create
+#define tx_mutex_delete _tx_mutex_delete
+#define tx_mutex_get _tx_mutex_get
+#define tx_mutex_info_get _tx_mutex_info_get
+#define tx_mutex_performance_info_get _tx_mutex_performance_info_get
+#define tx_mutex_performance_system_info_get _tx_mutex_performance_system_info_get
+#define tx_mutex_prioritize _tx_mutex_prioritize
+#define tx_mutex_put _tx_mutex_put
+
+#define tx_queue_create _tx_queue_create
+#define tx_queue_delete _tx_queue_delete
+#define tx_queue_flush _tx_queue_flush
+#define tx_queue_info_get _tx_queue_info_get
+#define tx_queue_performance_info_get _tx_queue_performance_info_get
+#define tx_queue_performance_system_info_get _tx_queue_performance_system_info_get
+#define tx_queue_receive _tx_queue_receive
+#define tx_queue_send _tx_queue_send
+#define tx_queue_send_notify _tx_queue_send_notify
+#define tx_queue_front_send _tx_queue_front_send
+#define tx_queue_prioritize _tx_queue_prioritize
+
+#define tx_semaphore_ceiling_put _tx_semaphore_ceiling_put
+#define tx_semaphore_create _tx_semaphore_create
+#define tx_semaphore_delete _tx_semaphore_delete
+#define tx_semaphore_get _tx_semaphore_get
+#define tx_semaphore_info_get _tx_semaphore_info_get
+#define tx_semaphore_performance_info_get _tx_semaphore_performance_info_get
+#define tx_semaphore_performance_system_info_get _tx_semaphore_performance_system_info_get
+#define tx_semaphore_prioritize _tx_semaphore_prioritize
+#define tx_semaphore_put _tx_semaphore_put
+#define tx_semaphore_put_notify _tx_semaphore_put_notify
+
+#define tx_thread_create _tx_thread_create
+#define tx_thread_delete _tx_thread_delete
+#define tx_thread_entry_exit_notify _tx_thread_entry_exit_notify
+#define tx_thread_identify _tx_thread_identify
+#define tx_thread_info_get _tx_thread_info_get
+#define tx_thread_performance_info_get _tx_thread_performance_info_get
+#define tx_thread_performance_system_info_get _tx_thread_performance_system_info_get
+#define tx_thread_preemption_change _tx_thread_preemption_change
+#define tx_thread_priority_change _tx_thread_priority_change
+#define tx_thread_relinquish _tx_thread_relinquish
+#define tx_thread_reset _tx_thread_reset
+#define tx_thread_resume _tx_thread_resume
+#define tx_thread_sleep _tx_thread_sleep
+#define tx_thread_stack_error_notify _tx_thread_stack_error_notify
+#define tx_thread_suspend _tx_thread_suspend
+#define tx_thread_terminate _tx_thread_terminate
+#define tx_thread_time_slice_change _tx_thread_time_slice_change
+#define tx_thread_wait_abort _tx_thread_wait_abort
+
+#define tx_time_get _tx_time_get
+#define tx_time_set _tx_time_set
+#define tx_timer_activate _tx_timer_activate
+#define tx_timer_change _tx_timer_change
+#define tx_timer_create _tx_timer_create
+#define tx_timer_deactivate _tx_timer_deactivate
+#define tx_timer_delete _tx_timer_delete
+#define tx_timer_info_get _tx_timer_info_get
+#define tx_timer_performance_info_get _tx_timer_performance_info_get
+#define tx_timer_performance_system_info_get _tx_timer_performance_system_info_get
+
+#define tx_trace_enable _tx_trace_enable
+#define tx_trace_event_filter _tx_trace_event_filter
+#define tx_trace_event_unfilter _tx_trace_event_unfilter
+#define tx_trace_disable _tx_trace_disable
+#define tx_trace_isr_enter_insert _tx_trace_isr_enter_insert
+#define tx_trace_isr_exit_insert _tx_trace_isr_exit_insert
+#define tx_trace_buffer_full_notify _tx_trace_buffer_full_notify
+#define tx_trace_user_event_insert _tx_trace_user_event_insert
+
+#else
+
+/* Services with error checking. */
+
+#define tx_kernel_enter _tx_initialize_kernel_enter
+
+/* Define the system API mappings depending on the runtime error
+ checking behavior selected by the user. */
+
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+
+
+/* Services with MULTI runtime error checking ThreadX. */
+
+#define tx_block_allocate _txr_block_allocate
+#define tx_block_pool_create(p,n,b,s,l) _txr_block_pool_create((p),(n),(b),(s),(l),(sizeof(TX_BLOCK_POOL)))
+#define tx_block_pool_delete _txr_block_pool_delete
+#define tx_block_pool_info_get _txr_block_pool_info_get
+#define tx_block_pool_performance_info_get _tx_block_pool_performance_info_get
+#define tx_block_pool_performance_system_info_get _tx_block_pool_performance_system_info_get
+#define tx_block_pool_prioritize _txr_block_pool_prioritize
+#define tx_block_release _txr_block_release
+
+#define tx_byte_allocate _txr_byte_allocate
+#define tx_byte_pool_create(p,n,s,l) _txr_byte_pool_create((p),(n),(s),(l),(sizeof(TX_BYTE_POOL)))
+#define tx_byte_pool_delete _txr_byte_pool_delete
+#define tx_byte_pool_info_get _txr_byte_pool_info_get
+#define tx_byte_pool_performance_info_get _tx_byte_pool_performance_info_get
+#define tx_byte_pool_performance_system_info_get _tx_byte_pool_performance_system_info_get
+#define tx_byte_pool_prioritize _txr_byte_pool_prioritize
+#define tx_byte_release _txr_byte_release
+
+#define tx_event_flags_create(g,n) _txr_event_flags_create((g),(n),(sizeof(TX_EVENT_FLAGS_GROUP)))
+#define tx_event_flags_delete _txr_event_flags_delete
+#define tx_event_flags_get _txr_event_flags_get
+#define tx_event_flags_info_get _txr_event_flags_info_get
+#define tx_event_flags_performance_info_get _tx_event_flags_performance_info_get
+#define tx_event_flags_performance_system_info_get _tx_event_flags_performance_system_info_get
+#define tx_event_flags_set _txr_event_flags_set
+#define tx_event_flags_set_notify _txr_event_flags_set_notify
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+UINT _tx_el_interrupt_control(UINT new_posture);
+#define tx_interrupt_control _tx_el_interrupt_control
+#else
+#ifdef TX_ENABLE_EVENT_TRACE
+UINT _tx_trace_interrupt_control(UINT new_posture);
+#define tx_interrupt_control _tx_trace_interrupt_control
+#else
+#define tx_interrupt_control _tx_thread_interrupt_control
+#endif
+#endif
+
+#define tx_mutex_create(m,n,i) _txr_mutex_create((m),(n),(i),(sizeof(TX_MUTEX)))
+#define tx_mutex_delete _txr_mutex_delete
+#define tx_mutex_get _txr_mutex_get
+#define tx_mutex_info_get _txr_mutex_info_get
+#define tx_mutex_performance_info_get _tx_mutex_performance_info_get
+#define tx_mutex_performance_system_info_get _tx_mutex_performance_system_info_get
+#define tx_mutex_prioritize _txr_mutex_prioritize
+#define tx_mutex_put _txr_mutex_put
+
+#define tx_queue_create(q,n,m,s,l) _txr_queue_create((q),(n),(m),(s),(l),(sizeof(TX_QUEUE)))
+#define tx_queue_delete _txr_queue_delete
+#define tx_queue_flush _txr_queue_flush
+#define tx_queue_info_get _txr_queue_info_get
+#define tx_queue_performance_info_get _tx_queue_performance_info_get
+#define tx_queue_performance_system_info_get _tx_queue_performance_system_info_get
+#define tx_queue_receive _txr_queue_receive
+#define tx_queue_send _txr_queue_send
+#define tx_queue_send_notify _txr_queue_send_notify
+#define tx_queue_front_send _txr_queue_front_send
+#define tx_queue_prioritize _txr_queue_prioritize
+
+#define tx_semaphore_ceiling_put _txr_semaphore_ceiling_put
+#define tx_semaphore_create(s,n,i) _txr_semaphore_create((s),(n),(i),(sizeof(TX_SEMAPHORE)))
+#define tx_semaphore_delete _txr_semaphore_delete
+#define tx_semaphore_get _txr_semaphore_get
+#define tx_semaphore_info_get _txr_semaphore_info_get
+#define tx_semaphore_performance_info_get _tx_semaphore_performance_info_get
+#define tx_semaphore_performance_system_info_get _tx_semaphore_performance_system_info_get
+#define tx_semaphore_prioritize _txr_semaphore_prioritize
+#define tx_semaphore_put _txr_semaphore_put
+#define tx_semaphore_put_notify _txr_semaphore_put_notify
+
+#define tx_thread_create(t,n,e,i,s,l,p,r,c,a) _txr_thread_create((t),(n),(e),(i),(s),(l),(p),(r),(c),(a),(sizeof(TX_THREAD)))
+#define tx_thread_delete _txr_thread_delete
+#define tx_thread_entry_exit_notify _txr_thread_entry_exit_notify
+#define tx_thread_identify _tx_thread_identify
+#define tx_thread_info_get _txr_thread_info_get
+#define tx_thread_performance_info_get _tx_thread_performance_info_get
+#define tx_thread_performance_system_info_get _tx_thread_performance_system_info_get
+#define tx_thread_preemption_change _txr_thread_preemption_change
+#define tx_thread_priority_change _txr_thread_priority_change
+#define tx_thread_relinquish _txe_thread_relinquish
+#define tx_thread_reset _txr_thread_reset
+#define tx_thread_resume _txr_thread_resume
+#define tx_thread_sleep _tx_thread_sleep
+#define tx_thread_stack_error_notify _tx_thread_stack_error_notify
+#define tx_thread_suspend _txr_thread_suspend
+#define tx_thread_terminate _txr_thread_terminate
+#define tx_thread_time_slice_change _txr_thread_time_slice_change
+#define tx_thread_wait_abort _txr_thread_wait_abort
+
+#define tx_time_get _tx_time_get
+#define tx_time_set _tx_time_set
+#define tx_timer_activate _txr_timer_activate
+#define tx_timer_change _txr_timer_change
+#define tx_timer_create(t,n,e,i,c,r,a) _txr_timer_create((t),(n),(e),(i),(c),(r),(a),(sizeof(TX_TIMER)))
+#define tx_timer_deactivate _txr_timer_deactivate
+#define tx_timer_delete _txr_timer_delete
+#define tx_timer_info_get _txr_timer_info_get
+#define tx_timer_performance_info_get _tx_timer_performance_info_get
+#define tx_timer_performance_system_info_get _tx_timer_performance_system_info_get
+
+#define tx_trace_enable _tx_trace_enable
+#define tx_trace_event_filter _tx_trace_event_filter
+#define tx_trace_event_unfilter _tx_trace_event_unfilter
+#define tx_trace_disable _tx_trace_disable
+#define tx_trace_isr_enter_insert _tx_trace_isr_enter_insert
+#define tx_trace_isr_exit_insert _tx_trace_isr_exit_insert
+#define tx_trace_buffer_full_notify _tx_trace_buffer_full_notify
+#define tx_trace_user_event_insert _tx_trace_user_event_insert
+
+#else
+
+#define tx_block_allocate _txe_block_allocate
+#define tx_block_pool_create(p,n,b,s,l) _txe_block_pool_create((p),(n),(b),(s),(l),(sizeof(TX_BLOCK_POOL)))
+#define tx_block_pool_delete _txe_block_pool_delete
+#define tx_block_pool_info_get _txe_block_pool_info_get
+#define tx_block_pool_performance_info_get _tx_block_pool_performance_info_get
+#define tx_block_pool_performance_system_info_get _tx_block_pool_performance_system_info_get
+#define tx_block_pool_prioritize _txe_block_pool_prioritize
+#define tx_block_release _txe_block_release
+
+#define tx_byte_allocate _txe_byte_allocate
+#define tx_byte_pool_create(p,n,s,l) _txe_byte_pool_create((p),(n),(s),(l),(sizeof(TX_BYTE_POOL)))
+#define tx_byte_pool_delete _txe_byte_pool_delete
+#define tx_byte_pool_info_get _txe_byte_pool_info_get
+#define tx_byte_pool_performance_info_get _tx_byte_pool_performance_info_get
+#define tx_byte_pool_performance_system_info_get _tx_byte_pool_performance_system_info_get
+#define tx_byte_pool_prioritize _txe_byte_pool_prioritize
+#define tx_byte_release _txe_byte_release
+
+#define tx_event_flags_create(g,n) _txe_event_flags_create((g),(n),(sizeof(TX_EVENT_FLAGS_GROUP)))
+#define tx_event_flags_delete _txe_event_flags_delete
+#define tx_event_flags_get _txe_event_flags_get
+#define tx_event_flags_info_get _txe_event_flags_info_get
+#define tx_event_flags_performance_info_get _tx_event_flags_performance_info_get
+#define tx_event_flags_performance_system_info_get _tx_event_flags_performance_system_info_get
+#define tx_event_flags_set _txe_event_flags_set
+#define tx_event_flags_set_notify _txe_event_flags_set_notify
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+UINT _tx_el_interrupt_control(UINT new_posture);
+#define tx_interrupt_control _tx_el_interrupt_control
+#else
+#ifdef TX_ENABLE_EVENT_TRACE
+#define tx_interrupt_control _tx_trace_interrupt_control
+#else
+#define tx_interrupt_control _tx_thread_interrupt_control
+#endif
+#endif
+
+#define tx_mutex_create(m,n,i) _txe_mutex_create((m),(n),(i),(sizeof(TX_MUTEX)))
+#define tx_mutex_delete _txe_mutex_delete
+#define tx_mutex_get _txe_mutex_get
+#define tx_mutex_info_get _txe_mutex_info_get
+#define tx_mutex_performance_info_get _tx_mutex_performance_info_get
+#define tx_mutex_performance_system_info_get _tx_mutex_performance_system_info_get
+#define tx_mutex_prioritize _txe_mutex_prioritize
+#define tx_mutex_put _txe_mutex_put
+
+#define tx_queue_create(q,n,m,s,l) _txe_queue_create((q),(n),(m),(s),(l),(sizeof(TX_QUEUE)))
+#define tx_queue_delete _txe_queue_delete
+#define tx_queue_flush _txe_queue_flush
+#define tx_queue_info_get _txe_queue_info_get
+#define tx_queue_performance_info_get _tx_queue_performance_info_get
+#define tx_queue_performance_system_info_get _tx_queue_performance_system_info_get
+#define tx_queue_receive _txe_queue_receive
+#define tx_queue_send _txe_queue_send
+#define tx_queue_send_notify _txe_queue_send_notify
+#define tx_queue_front_send _txe_queue_front_send
+#define tx_queue_prioritize _txe_queue_prioritize
+
+#define tx_semaphore_ceiling_put _txe_semaphore_ceiling_put
+#define tx_semaphore_create(s,n,i) _txe_semaphore_create((s),(n),(i),(sizeof(TX_SEMAPHORE)))
+#define tx_semaphore_delete _txe_semaphore_delete
+#define tx_semaphore_get _txe_semaphore_get
+#define tx_semaphore_info_get _txe_semaphore_info_get
+#define tx_semaphore_performance_info_get _tx_semaphore_performance_info_get
+#define tx_semaphore_performance_system_info_get _tx_semaphore_performance_system_info_get
+#define tx_semaphore_prioritize _txe_semaphore_prioritize
+#define tx_semaphore_put _txe_semaphore_put
+#define tx_semaphore_put_notify _txe_semaphore_put_notify
+
+#define tx_thread_create(t,n,e,i,s,l,p,r,c,a) _txe_thread_create((t),(n),(e),(i),(s),(l),(p),(r),(c),(a),(sizeof(TX_THREAD)))
+#define tx_thread_delete _txe_thread_delete
+#define tx_thread_entry_exit_notify _txe_thread_entry_exit_notify
+#define tx_thread_identify _tx_thread_identify
+#define tx_thread_info_get _txe_thread_info_get
+#define tx_thread_performance_info_get _tx_thread_performance_info_get
+#define tx_thread_performance_system_info_get _tx_thread_performance_system_info_get
+#define tx_thread_preemption_change _txe_thread_preemption_change
+#define tx_thread_priority_change _txe_thread_priority_change
+#define tx_thread_relinquish _txe_thread_relinquish
+#define tx_thread_reset _txe_thread_reset
+#define tx_thread_resume _txe_thread_resume
+#define tx_thread_sleep _tx_thread_sleep
+#define tx_thread_stack_error_notify _tx_thread_stack_error_notify
+#define tx_thread_suspend _txe_thread_suspend
+#define tx_thread_terminate _txe_thread_terminate
+#define tx_thread_time_slice_change _txe_thread_time_slice_change
+#define tx_thread_wait_abort _txe_thread_wait_abort
+
+#define tx_time_get _tx_time_get
+#define tx_time_set _tx_time_set
+#define tx_timer_activate _txe_timer_activate
+#define tx_timer_change _txe_timer_change
+#define tx_timer_create(t,n,e,i,c,r,a) _txe_timer_create((t),(n),(e),(i),(c),(r),(a),(sizeof(TX_TIMER)))
+#define tx_timer_deactivate _txe_timer_deactivate
+#define tx_timer_delete _txe_timer_delete
+#define tx_timer_info_get _txe_timer_info_get
+#define tx_timer_performance_info_get _tx_timer_performance_info_get
+#define tx_timer_performance_system_info_get _tx_timer_performance_system_info_get
+
+#define tx_trace_enable _tx_trace_enable
+#define tx_trace_event_filter _tx_trace_event_filter
+#define tx_trace_event_unfilter _tx_trace_event_unfilter
+#define tx_trace_disable _tx_trace_disable
+#define tx_trace_isr_enter_insert _tx_trace_isr_enter_insert
+#define tx_trace_isr_exit_insert _tx_trace_isr_exit_insert
+#define tx_trace_buffer_full_notify _tx_trace_buffer_full_notify
+#define tx_trace_user_event_insert _tx_trace_user_event_insert
+
+#endif
+#endif
+
+#endif
+
+
+/* Declare the tx_application_define function as having C linkage. */
+
+VOID tx_application_define(VOID *first_unused_memory);
+
+
+/* Define the function prototypes of the ThreadX API. */
+
+
+/* Define block memory pool management function prototypes. */
+
+UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option);
+UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
+ VOID *pool_start, ULONG pool_size);
+UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr);
+UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
+ ULONG *total_blocks, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BLOCK_POOL **next_pool);
+UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
+ ULONG *suspensions, ULONG *timeouts);
+UINT _tx_block_pool_performance_system_info_get(ULONG *allocates, ULONG *releases,
+ ULONG *suspensions, ULONG *timeouts);
+UINT _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr);
+UINT _tx_block_release(VOID *block_ptr);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option);
+UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
+ VOID *pool_start, ULONG pool_size, UINT pool_control_block_size);
+UINT _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr);
+UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
+ ULONG *total_blocks, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BLOCK_POOL **next_pool);
+UINT _txe_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr);
+UINT _txe_block_release(VOID *block_ptr);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option);
+UINT _txr_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
+ VOID *pool_start, ULONG pool_size, UINT pool_control_block_size);
+UINT _txr_block_pool_delete(TX_BLOCK_POOL *pool_ptr);
+UINT _txr_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
+ ULONG *total_blocks, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BLOCK_POOL **next_pool);
+UINT _txr_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr);
+UINT _txr_block_release(VOID *block_ptr);
+#endif
+
+
+/* Define byte memory pool management function prototypes. */
+
+UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size,
+ ULONG wait_option);
+UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start,
+ ULONG pool_size);
+UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr);
+UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
+ ULONG *fragments, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BYTE_POOL **next_pool);
+UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
+ ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts);
+UINT _tx_byte_pool_performance_system_info_get(ULONG *allocates, ULONG *releases,
+ ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts);
+UINT _tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr);
+UINT _tx_byte_release(VOID *memory_ptr);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size,
+ ULONG wait_option);
+UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start,
+ ULONG pool_size, UINT pool_control_block_size);
+UINT _txe_byte_pool_delete(TX_BYTE_POOL *pool_ptr);
+UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
+ ULONG *fragments, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BYTE_POOL **next_pool);
+UINT _txe_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr);
+UINT _txe_byte_release(VOID *memory_ptr);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size,
+ ULONG wait_option);
+UINT _txr_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start,
+ ULONG pool_size, UINT pool_control_block_size);
+UINT _txr_byte_pool_delete(TX_BYTE_POOL *pool_ptr);
+UINT _txr_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
+ ULONG *fragments, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BYTE_POOL **next_pool);
+UINT _txr_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr);
+UINT _txr_byte_release(VOID *memory_ptr);
+#endif
+
+
+/* Define event flags management function prototypes. */
+
+UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr);
+UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr);
+UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
+ UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option);
+UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_EVENT_FLAGS_GROUP **next_group);
+UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts);
+UINT _tx_event_flags_performance_system_info_get(ULONG *sets, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts);
+UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set,
+ UINT set_option);
+UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr));
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size);
+UINT _txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr);
+UINT _txe_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
+ UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option);
+UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_EVENT_FLAGS_GROUP **next_group);
+UINT _txe_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set,
+ UINT set_option);
+UINT _txe_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr));
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size);
+UINT _txr_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr);
+UINT _txr_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
+ UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option);
+UINT _txr_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_EVENT_FLAGS_GROUP **next_group);
+UINT _txr_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set,
+ UINT set_option);
+UINT _txr_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr));
+#endif
+
+
+/* Define initialization function prototypes. */
+
+VOID _tx_initialize_kernel_enter(VOID);
+
+
+/* Define mutex management function prototypes. */
+
+UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit);
+UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr);
+UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option);
+UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_MUTEX **next_mutex);
+UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts, ULONG *inversions, ULONG *inheritances);
+UINT _tx_mutex_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, ULONG *timeouts,
+ ULONG *inversions, ULONG *inheritances);
+UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr);
+UINT _tx_mutex_put(TX_MUTEX *mutex_ptr);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size);
+UINT _txe_mutex_delete(TX_MUTEX *mutex_ptr);
+UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option);
+UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_MUTEX **next_mutex);
+UINT _txe_mutex_prioritize(TX_MUTEX *mutex_ptr);
+UINT _txe_mutex_put(TX_MUTEX *mutex_ptr);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size);
+UINT _txr_mutex_delete(TX_MUTEX *mutex_ptr);
+UINT _txr_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option);
+UINT _txr_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_MUTEX **next_mutex);
+UINT _txr_mutex_prioritize(TX_MUTEX *mutex_ptr);
+UINT _txr_mutex_put(TX_MUTEX *mutex_ptr);
+#endif
+
+
+/* Define queue management function prototypes. */
+
+UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+ VOID *queue_start, ULONG queue_size);
+UINT _tx_queue_delete(TX_QUEUE *queue_ptr);
+UINT _tx_queue_flush(TX_QUEUE *queue_ptr);
+UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
+ TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue);
+UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received,
+ ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts);
+UINT _tx_queue_performance_system_info_get(ULONG *messages_sent, ULONG *messages_received,
+ ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts);
+UINT _tx_queue_prioritize(TX_QUEUE *queue_ptr);
+UINT _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option);
+UINT _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+UINT _tx_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr));
+UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+ VOID *queue_start, ULONG queue_size, UINT queue_control_block_size);
+UINT _txe_queue_delete(TX_QUEUE *queue_ptr);
+UINT _txe_queue_flush(TX_QUEUE *queue_ptr);
+UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
+ TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue);
+UINT _txe_queue_prioritize(TX_QUEUE *queue_ptr);
+UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option);
+UINT _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+UINT _txe_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr));
+UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+ VOID *queue_start, ULONG queue_size, UINT queue_control_block_size);
+UINT _txr_queue_delete(TX_QUEUE *queue_ptr);
+UINT _txr_queue_flush(TX_QUEUE *queue_ptr);
+UINT _txr_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
+ TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue);
+UINT _txr_queue_prioritize(TX_QUEUE *queue_ptr);
+UINT _txr_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option);
+UINT _txr_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+UINT _txr_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr));
+UINT _txr_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option);
+#endif
+
+
+/* Define semaphore management function prototypes. */
+
+UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling);
+UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count);
+UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr);
+UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option);
+UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_SEMAPHORE **next_semaphore);
+UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts);
+UINT _tx_semaphore_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, ULONG *timeouts);
+UINT _tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr);
+UINT _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr);
+UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr));
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling);
+UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size);
+UINT _txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr);
+UINT _txe_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option);
+UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_SEMAPHORE **next_semaphore);
+UINT _txe_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr);
+UINT _txe_semaphore_put(TX_SEMAPHORE *semaphore_ptr);
+UINT _txe_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr));
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling);
+UINT _txr_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size);
+UINT _txr_semaphore_delete(TX_SEMAPHORE *semaphore_ptr);
+UINT _txr_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option);
+UINT _txr_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_SEMAPHORE **next_semaphore);
+UINT _txr_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr);
+UINT _txr_semaphore_put(TX_SEMAPHORE *semaphore_ptr);
+UINT _txr_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr));
+#endif
+
+
+/* Define thread control function prototypes. */
+
+VOID _tx_thread_context_save(VOID);
+VOID _tx_thread_context_restore(VOID);
+UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
+ VOID (*entry_function)(ULONG entry_input), ULONG entry_input,
+ VOID *stack_start, ULONG stack_size,
+ UINT priority, UINT preempt_threshold,
+ ULONG time_slice, UINT auto_start);
+UINT _tx_thread_delete(TX_THREAD *thread_ptr);
+UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type));
+TX_THREAD *_tx_thread_identify(VOID);
+UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
+ UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
+ TX_THREAD **next_thread, TX_THREAD **next_suspended_thread);
+UINT _tx_thread_interrupt_control(UINT new_posture);
+UINT _tx_thread_performance_info_get(TX_THREAD *thread_ptr, ULONG *resumptions, ULONG *suspensions,
+ ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
+ ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts, TX_THREAD **last_preempted_by);
+UINT _tx_thread_performance_system_info_get(ULONG *resumptions, ULONG *suspensions,
+ ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
+ ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts,
+ ULONG *non_idle_returns, ULONG *idle_returns);
+UINT _tx_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold,
+ UINT *old_threshold);
+UINT _tx_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority,
+ UINT *old_priority);
+VOID _tx_thread_relinquish(VOID);
+UINT _tx_thread_reset(TX_THREAD *thread_ptr);
+UINT _tx_thread_resume(TX_THREAD *thread_ptr);
+UINT _tx_thread_sleep(ULONG timer_ticks);
+UINT _tx_thread_stack_error_notify(VOID (*stack_error_handler)(TX_THREAD *thread_ptr));
+UINT _tx_thread_suspend(TX_THREAD *thread_ptr);
+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);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
+ VOID (*entry_function)(ULONG entry_input), ULONG entry_input,
+ VOID *stack_start, ULONG stack_size,
+ UINT priority, UINT preempt_threshold,
+ ULONG time_slice, UINT auto_start, UINT thread_control_block_size);
+UINT _txe_thread_delete(TX_THREAD *thread_ptr);
+UINT _txe_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type));
+UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
+ UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
+ TX_THREAD **next_thread, TX_THREAD **next_suspended_thread);
+UINT _txe_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold,
+ UINT *old_threshold);
+UINT _txe_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority,
+ UINT *old_priority);
+VOID _txe_thread_relinquish(VOID);
+UINT _txe_thread_reset(TX_THREAD *thread_ptr);
+UINT _txe_thread_resume(TX_THREAD *thread_ptr);
+UINT _txe_thread_suspend(TX_THREAD *thread_ptr);
+UINT _txe_thread_terminate(TX_THREAD *thread_ptr);
+UINT _txe_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice);
+UINT _txe_thread_wait_abort(TX_THREAD *thread_ptr);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
+ VOID (*entry_function)(ULONG entry_input), ULONG entry_input,
+ VOID *stack_start, ULONG stack_size,
+ UINT priority, UINT preempt_threshold,
+ ULONG time_slice, UINT auto_start, UINT thread_control_block_size);
+UINT _txr_thread_delete(TX_THREAD *thread_ptr);
+UINT _txr_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type));
+UINT _txr_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
+ UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
+ TX_THREAD **next_thread, TX_THREAD **next_suspended_thread);
+UINT _txr_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold,
+ UINT *old_threshold);
+UINT _txr_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority,
+ UINT *old_priority);
+UINT _txr_thread_reset(TX_THREAD *thread_ptr);
+UINT _txr_thread_resume(TX_THREAD *thread_ptr);
+UINT _txr_thread_suspend(TX_THREAD *thread_ptr);
+UINT _txr_thread_terminate(TX_THREAD *thread_ptr);
+UINT _txr_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice);
+UINT _txr_thread_wait_abort(TX_THREAD *thread_ptr);
+#endif
+
+
+/* Define timer management function prototypes. */
+
+UINT _tx_timer_activate(TX_TIMER *timer_ptr);
+UINT _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks);
+UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
+ VOID (*expiration_function)(ULONG input), ULONG expiration_input,
+ ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate);
+UINT _tx_timer_deactivate(TX_TIMER *timer_ptr);
+UINT _tx_timer_delete(TX_TIMER *timer_ptr);
+UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
+ ULONG *reschedule_ticks, TX_TIMER **next_timer);
+UINT _tx_timer_performance_info_get(TX_TIMER *timer_ptr, ULONG *activates, ULONG *reactivates,
+ ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts);
+UINT _tx_timer_performance_system_info_get(ULONG *activates, ULONG *reactivates,
+ ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts);
+
+ULONG _tx_time_get(VOID);
+VOID _tx_time_set(ULONG new_time);
+
+
+/* Define error checking shells for API services. These are only referenced by the
+ application. */
+
+UINT _txe_timer_activate(TX_TIMER *timer_ptr);
+UINT _txe_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks);
+UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
+ VOID (*expiration_function)(ULONG input), ULONG expiration_input,
+ ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size);
+UINT _txe_timer_deactivate(TX_TIMER *timer_ptr);
+UINT _txe_timer_delete(TX_TIMER *timer_ptr);
+UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
+ ULONG *reschedule_ticks, TX_TIMER **next_timer);
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+UINT _txr_timer_activate(TX_TIMER *timer_ptr);
+UINT _txr_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks);
+UINT _txr_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
+ VOID (*expiration_function)(ULONG input), ULONG expiration_input,
+ ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size);
+UINT _txr_timer_deactivate(TX_TIMER *timer_ptr);
+UINT _txr_timer_delete(TX_TIMER *timer_ptr);
+UINT _txr_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
+ ULONG *reschedule_ticks, TX_TIMER **next_timer);
+#endif
+
+
+/* Define trace API function prototypes. */
+
+UINT _tx_trace_enable(VOID *trace_buffer_start, ULONG trace_buffer_size, ULONG registry_entries);
+UINT _tx_trace_event_filter(ULONG event_filter_bits);
+UINT _tx_trace_event_unfilter(ULONG event_unfilter_bits);
+UINT _tx_trace_disable(VOID);
+VOID _tx_trace_isr_enter_insert(ULONG isr_id);
+VOID _tx_trace_isr_exit_insert(ULONG isr_id);
+UINT _tx_trace_buffer_full_notify(VOID (*full_buffer_callback)(VOID *buffer));
+UINT _tx_trace_user_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4);
+UINT _tx_trace_interrupt_control(UINT new_posture);
+
+
+/* Add a default macro that can be re-defined in tx_port.h to add default processing when a thread starts. Common usage
+ would be for enabling floating point for a thread by default, however, the additional processing could be anything
+ defined in tx_port.h. */
+
+#ifndef TX_THREAD_STARTED_EXTENSION
+#define TX_THREAD_STARTED_EXTENSION(thread_ptr)
+#endif
+
+
+/* Add a default macro that can be re-defined in tx_port.h to add processing to the thread stack analyze function.
+ By default, this is simply defined as whitespace. */
+
+#ifndef TX_THREAD_STACK_ANALYZE_EXTENSION
+#define TX_THREAD_STACK_ANALYZE_EXTENSION
+#endif
+
+
+/* Add a default macro that can be re-defined in tx_port.h to add processing to the initialize kernel enter function.
+ By default, this is simply defined as whitespace. */
+
+#ifndef TX_INITIALIZE_KERNEL_ENTER_EXTENSION
+#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION
+#endif
+
+
+/* Check for MISRA compliance requirements. */
+
+#ifdef TX_MISRA_ENABLE
+
+
+/* Define MISRA-specific routines. */
+
+VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size);
+UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount);
+UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount);
+ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2);
+ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr);
+ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount);
+ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount);
+ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2);
+VOID *_tx_misra_ulong_to_pointer_convert(ULONG input);
+VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, UINT size);
+ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, TX_TIMER_INTERNAL **ptr2);
+TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL **ptr1, ULONG size);
+VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL *internal_timer, TX_TIMER **user_timer);
+VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, VOID **highest_stack);
+VOID _tx_misra_trace_event_insert(ULONG event_id, VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, ULONG time_stamp);
+UINT _tx_misra_always_true(void);
+
+UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **pointer);
+UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer);
+UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool);
+TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer);
+UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer);
+TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer);
+UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer);
+TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer);
+UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool);
+ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer);
+TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer);
+TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer);
+ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer);
+TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer);
+UINT _tx_misra_status_get(UINT status);
+TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer);
+TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer);
+VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer);
+TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value);
+VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer);
+CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer);
+TX_THREAD *_tx_misra_void_to_thread_pointer_convert(VOID *pointer);
+UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer);
+VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr);
+VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr));
+VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr);
+VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr));
+VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr);
+VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr));
+VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr);
+VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id));
+
+
+#define TX_MEMSET(a,b,c) _tx_misra_memset((a), (UINT) (b), (UINT) (c))
+#define TX_UCHAR_POINTER_ADD(a,b) _tx_misra_uchar_pointer_add((UCHAR *) (a), (ULONG) (b))
+#define TX_UCHAR_POINTER_SUB(a,b) _tx_misra_uchar_pointer_sub((UCHAR *) (a), (ULONG) (b))
+#define TX_UCHAR_POINTER_DIF(a,b) _tx_misra_uchar_pointer_dif((UCHAR *) (a), (UCHAR *) (b))
+#define TX_ULONG_POINTER_ADD(a,b) _tx_misra_ulong_pointer_add((ULONG *) (a), (ULONG) (b))
+#define TX_ULONG_POINTER_SUB(a,b) _tx_misra_ulong_pointer_sub((ULONG *) (a), (ULONG) (b))
+#define TX_ULONG_POINTER_DIF(a,b) _tx_misra_ulong_pointer_dif((ULONG *) (a), (ULONG *) (b))
+#define TX_POINTER_TO_ULONG_CONVERT(a) _tx_misra_pointer_to_ulong_convert((VOID *) (a))
+#define TX_ULONG_TO_POINTER_CONVERT(a) _tx_misra_ulong_to_pointer_convert((ULONG) (a))
+#define TX_QUEUE_MESSAGE_COPY(s,d,z) _tx_misra_message_copy(&(s), &(d), (z));
+#define TX_TIMER_POINTER_DIF(a,b) _tx_misra_timer_pointer_dif((TX_TIMER_INTERNAL **) (a), (TX_TIMER_INTERNAL **) (b))
+#define TX_TIMER_POINTER_ADD(a,b) _tx_misra_timer_pointer_add((TX_TIMER_INTERNAL **) (a), (ULONG) (b))
+#define TX_USER_TIMER_POINTER_GET(a,b) _tx_misra_user_timer_pointer_get((TX_TIMER_INTERNAL *) (a), (TX_TIMER **) &(b));
+#define TX_THREAD_STACK_CHECK(a) _tx_misra_thread_stack_check((a), &((a)->tx_thread_stack_highest_ptr));
+#ifdef TX_ENABLE_EVENT_TRACE
+#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) _tx_misra_trace_event_insert((ULONG) (i), (VOID *) (a), (ULONG) (b), (ULONG) (c), (ULONG) (d), (ULONG) (e), ((ULONG) TX_TRACE_TIME_SOURCE));
+#endif
+#define TX_LOOP_FOREVER (_tx_misra_always_true() == TX_TRUE)
+
+
+#define TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_indirect_void_to_uchar_pointer_convert((a))
+#define TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) _tx_misra_uchar_to_indirect_uchar_pointer_convert((a))
+#define TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_block_pool_to_uchar_pointer_convert((a))
+#define TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(a) _tx_misra_void_to_block_pool_pointer_convert((a))
+#define TX_VOID_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_void_to_uchar_pointer_convert((a))
+#define TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT(a) _tx_misra_uchar_to_block_pool_pointer_convert((a))
+#define TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) _tx_misra_void_to_indirect_uchar_pointer_convert((a))
+#define TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(a) _tx_misra_void_to_byte_pool_pointer_convert((a))
+#define TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_byte_pool_to_uchar_pointer_convert((a))
+#define TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(a) _tx_misra_uchar_to_align_type_pointer_convert((a))
+#define TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(a) _tx_misra_uchar_to_indirect_byte_pool_pointer_convert((a))
+#define TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(a) _tx_misra_void_to_event_flags_pointer_convert((a))
+#define TX_VOID_TO_ULONG_POINTER_CONVERT(a) _tx_misra_void_to_ulong_pointer_convert((a))
+#define TX_VOID_TO_MUTEX_POINTER_CONVERT(a) _tx_misra_void_to_mutex_pointer_convert((a))
+#define TX_MUTEX_PRIORITIZE_MISRA_EXTENSION(a) _tx_misra_status_get((a))
+#define TX_VOID_TO_QUEUE_POINTER_CONVERT(a) _tx_misra_void_to_queue_pointer_convert((a))
+#define TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(a) _tx_misra_void_to_semaphore_pointer_convert((a))
+#define TX_UCHAR_TO_VOID_POINTER_CONVERT(a) _tx_misra_uchar_to_void_pointer_convert((a))
+#define TX_ULONG_TO_THREAD_POINTER_CONVERT(a) _tx_misra_ulong_to_thread_pointer_convert((a))
+#define TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(a) _tx_misra_timer_indirect_to_void_pointer_convert((a))
+#ifndef TX_TIMER_INITIALIZE_EXTENSION
+#define TX_TIMER_INITIALIZE_EXTENSION(a) status = _tx_misra_status_get((a));
+#endif
+#define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) _tx_misra_const_char_to_char_pointer_convert((a))
+#define TX_VOID_TO_THREAD_POINTER_CONVERT(a) _tx_misra_void_to_thread_pointer_convert((a))
+#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_char_to_uchar_pointer_convert((a))
+#define TX_EVENT_FLAGS_GROUP_NOT_USED(a) _tx_misra_event_flags_group_not_used((a))
+#define TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(a) _tx_misra_event_flags_set_notify_not_used((a))
+#define TX_QUEUE_NOT_USED(a) _tx_misra_queue_not_used((a))
+#define TX_QUEUE_SEND_NOTIFY_NOT_USED(a) _tx_misra_queue_send_notify_not_used((a))
+#define TX_SEMAPHORE_NOT_USED(a) _tx_misra_semaphore_not_used((a))
+#define TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(a) _tx_misra_semaphore_put_notify_not_used((a))
+#define TX_THREAD_NOT_USED(a) _tx_misra_thread_not_used((a))
+#define TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(a) _tx_misra_thread_entry_exit_notify_not_used((a))
+
+
+#else
+
+/* Define the TX_MEMSET macro to the standard library function, if not already defined. */
+
+#ifndef TX_MEMSET
+#define TX_MEMSET(a,b,c) memset((a),(b),(c))
+#endif
+
+#define TX_UCHAR_POINTER_ADD(a,b) (((UCHAR *) (a)) + ((UINT) (b)))
+#define TX_UCHAR_POINTER_SUB(a,b) (((UCHAR *) (a)) - ((UINT) (b)))
+#define TX_UCHAR_POINTER_DIF(a,b) ((ULONG)(((UCHAR *) (a)) - ((UCHAR *) (b))))
+#define TX_ULONG_POINTER_ADD(a,b) (((ULONG *) (a)) + ((UINT) (b)))
+#define TX_ULONG_POINTER_SUB(a,b) (((ULONG *) (a)) - ((UINT) (b)))
+#define TX_ULONG_POINTER_DIF(a,b) ((ULONG)(((ULONG *) (a)) - ((ULONG *) (b))))
+#define TX_POINTER_TO_ULONG_CONVERT(a) ((ULONG) ((VOID *) (a)))
+#define TX_ULONG_TO_POINTER_CONVERT(a) ((VOID *) ((ULONG) (a)))
+#define TX_TIMER_POINTER_DIF(a,b) ((ULONG)(((TX_TIMER_INTERNAL **) (a)) - ((TX_TIMER_INTERNAL **) (b))))
+#define TX_TIMER_POINTER_ADD(a,b) (((TX_TIMER_INTERNAL **) (a)) + ((ULONG) (b)))
+#define TX_USER_TIMER_POINTER_GET(a,b) { \
+ UCHAR *working_ptr; \
+ working_ptr = (UCHAR *) (a); \
+ (b) = (TX_TIMER *) working_ptr; \
+ working_ptr = working_ptr - (((UCHAR *) &(b) -> tx_timer_internal) - ((UCHAR *) &(b) -> tx_timer_id)); \
+ (b) = (TX_TIMER *) working_ptr; \
+ }
+#define TX_LOOP_FOREVER ((UINT) 1)
+
+
+#define TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR **) ((VOID *) (a)))
+#define TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) ((UCHAR **) ((VOID *) (a)))
+#define TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+#define TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(a) ((TX_BLOCK_POOL *) ((VOID *) (a)))
+#define TX_VOID_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+#define TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT(a) ((TX_BLOCK_POOL *) ((VOID *) (a)))
+#define TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) ((UCHAR **) ((VOID *) (a)))
+#define TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(a) ((TX_BYTE_POOL *) ((VOID *) (a)))
+#define TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+#ifndef TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT
+#define TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(a) ((ALIGN_TYPE *) ((VOID *) (a)))
+#endif
+#define TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(a) ((TX_BYTE_POOL **) ((VOID *) (a)))
+#define TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(a) ((TX_EVENT_FLAGS_GROUP *) ((VOID *) (a)))
+#define TX_VOID_TO_ULONG_POINTER_CONVERT(a) ((ULONG *) ((VOID *) (a)))
+#define TX_VOID_TO_MUTEX_POINTER_CONVERT(a) ((TX_MUTEX *) ((VOID *) (a)))
+#define TX_VOID_TO_QUEUE_POINTER_CONVERT(a) ((TX_QUEUE *) ((VOID *) (a)))
+#define TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(a) ((TX_SEMAPHORE *) ((VOID *) (a)))
+#define TX_UCHAR_TO_VOID_POINTER_CONVERT(a) ((VOID *) (a))
+#define TX_ULONG_TO_THREAD_POINTER_CONVERT(a) ((TX_THREAD *) ((VOID *) (a)))
+#ifndef TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT
+#define TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(a) ((VOID *) (a))
+#endif
+#ifndef TX_TIMER_INITIALIZE_EXTENSION
+#define TX_TIMER_INITIALIZE_EXTENSION(a)
+#endif
+#define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) ((CHAR *) ((VOID *) (a)))
+#define TX_VOID_TO_THREAD_POINTER_CONVERT(a) ((TX_THREAD *) ((VOID *) (a)))
+#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+#ifndef TX_EVENT_FLAGS_GROUP_NOT_USED
+#define TX_EVENT_FLAGS_GROUP_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED
+#define TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_QUEUE_NOT_USED
+#define TX_QUEUE_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_QUEUE_SEND_NOTIFY_NOT_USED
+#define TX_QUEUE_SEND_NOTIFY_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_SEMAPHORE_NOT_USED
+#define TX_SEMAPHORE_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_SEMAPHORE_PUT_NOTIFY_NOT_USED
+#define TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_THREAD_NOT_USED
+#define TX_THREAD_NOT_USED(a) ((void)(a))
+#endif
+#ifndef TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED
+#define TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(a) ((void)(a))
+#endif
+
+#endif
+
+
+/* Determine if there is an tx_api.h extension file to include. */
+
+#ifdef TX_THREAD_API_EXTENSION
+
+/* Yes, bring in the tx_api.h extension file. */
+#include "tx_api_extension.h"
+
+#endif
+
+
+/* Define safety critical configuration and exception handling. */
+
+#ifdef TX_SAFETY_CRITICAL
+
+/* Ensure the maximum number of priorities is defined in safety critical mode. */
+#ifndef TX_MAX_PRIORITIES
+#error "tx_port.h: TX_MAX_PRIORITIES not defined."
+#endif
+
+/* Ensure the maximum number of priorities is a multiple of 32. */
+#if (TX_MAX_PRIORITIES %32) != 0
+#error "tx_port.h: TX_MAX_PRIORITIES must be a multiple of 32."
+#endif
+
+/* Ensure error checking is enabled. */
+#ifdef TX_DISABLE_ERROR_CHECKING
+#error "TX_DISABLE_ERROR_CHECKING must not be defined."
+#endif
+
+/* Ensure timer ISR processing is not defined. */
+#ifdef TX_TIMER_PROCESS_IN_ISR
+#error "TX_TIMER_PROCESS_IN_ISR must not be defined."
+#endif
+
+/* Ensure timer reactivation in-line is not defined. */
+#ifdef TX_REACTIVATE_INLINE
+#error "TX_REACTIVATE_INLINE must not be defined."
+#endif
+
+/* Ensure disable stack filling is not defined. */
+#ifdef TX_DISABLE_STACK_FILLING
+#error "TX_DISABLE_STACK_FILLING must not be defined."
+#endif
+
+/* Ensure enable stack checking is not defined. */
+#ifdef TX_ENABLE_STACK_CHECKING
+#error "TX_ENABLE_STACK_CHECKING must not be defined."
+#endif
+
+/* Ensure disable preemption-threshold is not defined. */
+#ifdef TX_DISABLE_PREEMPTION_THRESHOLD
+#error "TX_DISABLE_PREEMPTION_THRESHOLD must not be defined."
+#endif
+
+/* Ensure disable redundant clearing is not defined. */
+#ifdef TX_DISABLE_REDUNDANT_CLEARING
+#error "TX_DISABLE_REDUNDANT_CLEARING must not be defined."
+#endif
+
+/* Ensure no timer is not defined. */
+#ifdef TX_NO_TIMER
+#error "TX_NO_TIMER must not be defined."
+#endif
+
+/* Ensure disable notify callbacks is not defined. */
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+#error "TX_DISABLE_NOTIFY_CALLBACKS must not be defined."
+#endif
+
+/* Ensure in-line thread suspend/resume is not defined. */
+#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
+#error "TX_INLINE_THREAD_RESUME_SUSPEND must not be defined."
+#endif
+
+/* Ensure not interruptable is not defined. */
+#ifdef TX_NOT_INTERRUPTABLE
+#error "TX_NOT_INTERRUPTABLE must not be defined."
+#endif
+
+/* Ensure event trace enable is not defined. */
+#ifdef TX_ENABLE_EVENT_TRACE
+#error "TX_ENABLE_EVENT_TRACE must not be defined."
+#endif
+
+/* Ensure block pool performance info enable is not defined. */
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+#error "TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure byte pool performance info enable is not defined. */
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+#error "TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure event flag performance info enable is not defined. */
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+#error "TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure mutex performance info enable is not defined. */
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+#error "TX_MUTEX_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure queue performance info enable is not defined. */
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#error "TX_QUEUE_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure semaphore performance info enable is not defined. */
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+#error "TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure thread performance info enable is not defined. */
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+#error "TX_THREAD_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+/* Ensure timer performance info enable is not defined. */
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+#error "TX_TIMER_ENABLE_PERFORMANCE_INFO must not be defined."
+#endif
+
+
+/* Now define the safety critical exception handler. */
+
+VOID _tx_safety_critical_exception_handler(CHAR *file_name, INT line_number, UINT status);
+
+
+#ifndef TX_SAFETY_CRITICAL_EXCEPTION
+#define TX_SAFETY_CRITICAL_EXCEPTION(a, b, c) _tx_safety_critical_exception_handler(a, b, c);
+#endif
+
+#ifndef TX_SAFETY_CRITICAL_EXCEPTION_HANDLER
+#define TX_SAFETY_CRITICAL_EXCEPTION_HANDLER VOID _tx_safety_critical_exception_handler(CHAR *file_name, INT line_number, UINT status) \
+ { \
+ while(1) \
+ { \
+ } \
+ }
+#endif
+#endif
+
+
+#ifdef TX_ENABLE_MULTI_ERROR_CHECKING
+
+/* Define ThreadX API MULTI run-time error checking function. */
+void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hexVal);
+
+#endif
+
+/* Bring in the event logging constants and prototypes. Note that
+ TX_ENABLE_EVENT_LOGGING must be defined when building the ThreadX
+ library components in order to enable event logging. */
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+#include "tx_el.h"
+#else
+#ifndef TX_SOURCE_CODE
+#ifndef TX_MISRA_ENABLE
+#define _tx_el_user_event_insert(a,b,c,d,e)
+#endif
+#endif
+#define TX_EL_INITIALIZE
+#define TX_EL_THREAD_REGISTER(a)
+#define TX_EL_THREAD_UNREGISTER(a)
+#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b)
+#define TX_EL_BYTE_ALLOCATE_INSERT
+#define TX_EL_BYTE_POOL_CREATE_INSERT
+#define TX_EL_BYTE_POOL_DELETE_INSERT
+#define TX_EL_BYTE_RELEASE_INSERT
+#define TX_EL_BLOCK_ALLOCATE_INSERT
+#define TX_EL_BLOCK_POOL_CREATE_INSERT
+#define TX_EL_BLOCK_POOL_DELETE_INSERT
+#define TX_EL_BLOCK_RELEASE_INSERT
+#define TX_EL_EVENT_FLAGS_CREATE_INSERT
+#define TX_EL_EVENT_FLAGS_DELETE_INSERT
+#define TX_EL_EVENT_FLAGS_GET_INSERT
+#define TX_EL_EVENT_FLAGS_SET_INSERT
+#define TX_EL_INTERRUPT_CONTROL_INSERT
+#define TX_EL_QUEUE_CREATE_INSERT
+#define TX_EL_QUEUE_DELETE_INSERT
+#define TX_EL_QUEUE_FLUSH_INSERT
+#define TX_EL_QUEUE_RECEIVE_INSERT
+#define TX_EL_QUEUE_SEND_INSERT
+#define TX_EL_SEMAPHORE_CREATE_INSERT
+#define TX_EL_SEMAPHORE_DELETE_INSERT
+#define TX_EL_SEMAPHORE_GET_INSERT
+#define TX_EL_SEMAPHORE_PUT_INSERT
+#define TX_EL_THREAD_CREATE_INSERT
+#define TX_EL_THREAD_DELETE_INSERT
+#define TX_EL_THREAD_IDENTIFY_INSERT
+#define TX_EL_THREAD_PREEMPTION_CHANGE_INSERT
+#define TX_EL_THREAD_PRIORITY_CHANGE_INSERT
+#define TX_EL_THREAD_RELINQUISH_INSERT
+#define TX_EL_THREAD_RESUME_INSERT
+#define TX_EL_THREAD_SLEEP_INSERT
+#define TX_EL_THREAD_SUSPEND_INSERT
+#define TX_EL_THREAD_TERMINATE_INSERT
+#define TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT
+#define TX_EL_TIME_GET_INSERT
+#define TX_EL_TIME_SET_INSERT
+#define TX_EL_TIMER_ACTIVATE_INSERT
+#define TX_EL_TIMER_CHANGE_INSERT
+#define TX_EL_TIMER_CREATE_INSERT
+#define TX_EL_TIMER_DEACTIVATE_INSERT
+#define TX_EL_TIMER_DELETE_INSERT
+#define TX_EL_BLOCK_POOL_INFO_GET_INSERT
+#define TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
+#define TX_EL_BYTE_POOL_INFO_GET_INSERT
+#define TX_EL_BYTE_POOL_PRIORITIZE_INSERT
+#define TX_EL_EVENT_FLAGS_INFO_GET_INSERT
+#define TX_EL_MUTEX_CREATE_INSERT
+#define TX_EL_MUTEX_DELETE_INSERT
+#define TX_EL_MUTEX_GET_INSERT
+#define TX_EL_MUTEX_INFO_GET_INSERT
+#define TX_EL_MUTEX_PRIORITIZE_INSERT
+#define TX_EL_MUTEX_PUT_INSERT
+#define TX_EL_QUEUE_INFO_GET_INSERT
+#define TX_EL_QUEUE_FRONT_SEND_INSERT
+#define TX_EL_QUEUE_PRIORITIZE_INSERT
+#define TX_EL_SEMAPHORE_INFO_GET_INSERT
+#define TX_EL_SEMAPHORE_PRIORITIZE_INSERT
+#define TX_EL_THREAD_INFO_GET_INSERT
+#define TX_EL_THREAD_WAIT_ABORT_INSERT
+#define TX_EL_TIMER_INFO_GET_INSERT
+#define TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT
+#define TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_QUEUE_SEND_NOTIFY_INSERT
+#define TX_EL_SEMAPHORE_CEILING_PUT_INSERT
+#define TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT
+#define TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT
+#define TX_EL_THREAD_RESET_INSERT
+#define TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#define TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT
+#define TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT
+#define TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+#endif
+
+
+
+/* Determine if a C++ compiler is being used. If so, complete the standard
+ C conditional started above. */
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
diff --git a/common/inc/tx_block_pool.h b/common/inc/tx_block_pool.h
new file mode 100644
index 00000000..1000c4b6
--- /dev/null
+++ b/common/inc/tx_block_pool.h
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_block_pool.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX block memory management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_BLOCK_POOL_H
+#define TX_BLOCK_POOL_H
+
+
+/* Define block memory control specific data definitions. */
+
+#define TX_BLOCK_POOL_ID ((ULONG) 0x424C4F43)
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the block memory pool
+ initialization function. */
+
+#ifndef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+#define _tx_block_pool_initialize() \
+ _tx_block_pool_created_ptr = TX_NULL; \
+ _tx_block_pool_created_count = TX_EMPTY
+#else
+#define _tx_block_pool_initialize() \
+ _tx_block_pool_created_ptr = TX_NULL; \
+ _tx_block_pool_created_count = TX_EMPTY; \
+ _tx_block_pool_performance_allocate_count = ((ULONG) 0); \
+ _tx_block_pool_performance_release_count = ((ULONG) 0); \
+ _tx_block_pool_performance_suspension_count = ((ULONG) 0); \
+ _tx_block_pool_performance_timeout_count = ((ULONG) 0)
+#endif
+#define TX_BLOCK_POOL_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call. */
+VOID _tx_block_pool_initialize(VOID);
+#endif
+
+
+/* Define internal block memory pool management function prototypes. */
+
+VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Block pool management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_BLOCK_POOL_INIT
+#define BLOCK_POOL_DECLARE
+#else
+#define BLOCK_POOL_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created block pool list. */
+
+BLOCK_POOL_DECLARE TX_BLOCK_POOL * _tx_block_pool_created_ptr;
+
+
+/* Define the variable that holds the number of created block pools. */
+
+BLOCK_POOL_DECLARE ULONG _tx_block_pool_created_count;
+
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of block allocates. */
+
+BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_allocate_count;
+
+
+/* Define the total number of block releases. */
+
+BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_release_count;
+
+
+/* Define the total number of block pool suspensions. */
+
+BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_suspension_count;
+
+
+/* Define the total number of block pool timeouts. */
+
+BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_timeout_count;
+
+
+#endif
+
+
+/* Define default post block pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_BLOCK_POOL_DELETE_PORT_COMPLETION
+#define TX_BLOCK_POOL_DELETE_PORT_COMPLETION(p)
+#endif
+
+
+#endif
diff --git a/common/inc/tx_byte_pool.h b/common/inc/tx_byte_pool.h
new file mode 100644
index 00000000..408a0924
--- /dev/null
+++ b/common/inc/tx_byte_pool.h
@@ -0,0 +1,177 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_byte_pool.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX byte memory management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_BYTE_POOL_H
+#define TX_BYTE_POOL_H
+
+
+/* Define byte memory control specific data definitions. */
+
+#define TX_BYTE_POOL_ID ((ULONG) 0x42595445)
+
+#ifndef TX_BYTE_BLOCK_FREE
+#define TX_BYTE_BLOCK_FREE ((ULONG) 0xFFFFEEEEUL)
+#endif
+
+#ifndef TX_BYTE_BLOCK_MIN
+#define TX_BYTE_BLOCK_MIN ((ULONG) 20)
+#endif
+
+#ifndef TX_BYTE_POOL_MIN
+#define TX_BYTE_POOL_MIN ((ULONG) 100)
+#endif
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the byte memory pool
+ initialization function. */
+
+#ifndef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+#define _tx_byte_pool_initialize() \
+ _tx_byte_pool_created_ptr = TX_NULL; \
+ _tx_byte_pool_created_count = TX_EMPTY
+#else
+#define _tx_byte_pool_initialize() \
+ _tx_byte_pool_created_ptr = TX_NULL; \
+ _tx_byte_pool_created_count = TX_EMPTY; \
+ _tx_byte_pool_performance_allocate_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_release_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_merge_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_split_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_search_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_suspension_count = ((ULONG) 0); \
+ _tx_byte_pool_performance_timeout_count = ((ULONG) 0)
+#endif
+#define TX_BYTE_POOL_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call. */
+VOID _tx_byte_pool_initialize(VOID);
+#endif
+
+
+/* Define internal byte memory pool management function prototypes. */
+
+UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size);
+VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Byte pool management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_BYTE_POOL_INIT
+#define BYTE_POOL_DECLARE
+#else
+#define BYTE_POOL_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created byte pool list. */
+
+BYTE_POOL_DECLARE TX_BYTE_POOL * _tx_byte_pool_created_ptr;
+
+
+/* Define the variable that holds the number of created byte pools. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_created_count;
+
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of allocates. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_allocate_count;
+
+
+/* Define the total number of releases. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_release_count;
+
+
+/* Define the total number of adjacent memory fragment merges. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_merge_count;
+
+
+/* Define the total number of memory fragment splits. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_split_count;
+
+
+/* Define the total number of memory fragments searched during allocation. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_search_count;
+
+
+/* Define the total number of byte pool suspensions. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_suspension_count;
+
+
+/* Define the total number of byte pool timeouts. */
+
+BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_timeout_count;
+
+
+#endif
+
+
+/* Define default post byte pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_BYTE_POOL_DELETE_PORT_COMPLETION
+#define TX_BYTE_POOL_DELETE_PORT_COMPLETION(p)
+#endif
+
+
+#endif
diff --git a/common/inc/tx_event_flags.h b/common/inc/tx_event_flags.h
new file mode 100644
index 00000000..c3fa8e44
--- /dev/null
+++ b/common/inc/tx_event_flags.h
@@ -0,0 +1,147 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_event_flags.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX event flags management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_EVENT_FLAGS_H
+#define TX_EVENT_FLAGS_H
+
+
+/* Define event flags control specific data definitions. */
+
+#define TX_EVENT_FLAGS_ID ((ULONG) 0x4456444E)
+#define TX_EVENT_FLAGS_AND_MASK ((UINT) 0x2)
+#define TX_EVENT_FLAGS_CLEAR_MASK ((UINT) 0x1)
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the event flag initialization
+ function. */
+
+#ifndef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+#define _tx_event_flags_initialize() \
+ _tx_event_flags_created_ptr = TX_NULL; \
+ _tx_event_flags_created_count = TX_EMPTY
+#else
+#define _tx_event_flags_initialize() \
+ _tx_event_flags_created_ptr = TX_NULL; \
+ _tx_event_flags_created_count = TX_EMPTY; \
+ _tx_event_flags_performance_set_count = ((ULONG) 0); \
+ _tx_event_flags_performance_get_count = ((ULONG) 0); \
+ _tx_event_flags_performance_suspension_count = ((ULONG) 0); \
+ _tx_event_flags_performance_timeout_count = ((ULONG) 0)
+#endif
+#define TX_EVENT_FLAGS_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call. */
+VOID _tx_event_flags_initialize(VOID);
+#endif
+
+
+/* Define internal event flags management function prototypes. */
+
+VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Event flags management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_EVENT_FLAGS_INIT
+#define EVENT_FLAGS_DECLARE
+#else
+#define EVENT_FLAGS_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created event flags list. */
+
+EVENT_FLAGS_DECLARE TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr;
+
+
+/* Define the variable that holds the number of created event flag groups. */
+
+EVENT_FLAGS_DECLARE ULONG _tx_event_flags_created_count;
+
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of event flag sets. */
+
+EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_set_count;
+
+
+/* Define the total number of event flag gets. */
+
+EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_get_count;
+
+
+/* Define the total number of event flag suspensions. */
+
+EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_suspension_count;
+
+
+/* Define the total number of event flag timeouts. */
+
+EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_timeout_count;
+
+
+#endif
+
+/* Define default post event flag group delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION
+#define TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(g)
+#endif
+
+
+#endif
+
diff --git a/common/inc/tx_initialize.h b/common/inc/tx_initialize.h
new file mode 100644
index 00000000..f41eee48
--- /dev/null
+++ b/common/inc/tx_initialize.h
@@ -0,0 +1,111 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_initialize.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX initialization component, including */
+/* data types and external references. It is assumed that tx_api.h */
+/* and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_INITIALIZE_H
+#define TX_INITIALIZE_H
+
+
+/* Define constants that indicate initialization is in progress. */
+
+#define TX_INITIALIZE_IN_PROGRESS ((ULONG) 0xF0F0F0F0UL)
+#define TX_INITIALIZE_ALMOST_DONE ((ULONG) 0xF0F0F0F1UL)
+#define TX_INITIALIZE_IS_FINISHED ((ULONG) 0x00000000UL)
+
+
+/* Define internal initialization function prototypes. */
+
+VOID _tx_initialize_high_level(VOID);
+VOID _tx_initialize_kernel_setup(VOID);
+VOID _tx_initialize_low_level(VOID);
+
+
+/* Define the macro for adding additional port-specific global data. This macro is defined
+ as white space, unless defined by tx_port.h. */
+
+#ifndef TX_PORT_SPECIFIC_DATA
+#define TX_PORT_SPECIFIC_DATA
+#endif
+
+
+/* Define the macro for adding additional port-specific pre and post initialization processing.
+ These macros is defined as white space, unless defined by tx_port.h. */
+
+#ifndef TX_PORT_SPECIFIC_PRE_INITIALIZATION
+#define TX_PORT_SPECIFIC_PRE_INITIALIZATION
+#endif
+
+#ifndef TX_PORT_SPECIFIC_POST_INITIALIZATION
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION
+#endif
+
+#ifndef TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
+#endif
+
+
+/* Initialization component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_INITIALIZE_INIT
+#define INITIALIZE_DECLARE
+#else
+#define INITIALIZE_DECLARE extern
+#endif
+
+
+/* Define the unused memory pointer. The value of the first available
+ memory address is placed in this variable in the low-level
+ initialization function. The content of this variable is passed
+ to the application's system definition function. */
+
+INITIALIZE_DECLARE VOID *_tx_initialize_unused_memory;
+
+
+#endif
diff --git a/common/inc/tx_mutex.h b/common/inc/tx_mutex.h
new file mode 100644
index 00000000..4ee63e55
--- /dev/null
+++ b/common/inc/tx_mutex.h
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_mutex.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX mutex management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_MUTEX_H
+#define TX_MUTEX_H
+
+
+/* Define mutex control specific data definitions. */
+
+#define TX_MUTEX_ID ((ULONG) 0x4D555445)
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the mutex initialization
+ function. */
+
+#ifndef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+#define _tx_mutex_initialize() \
+ _tx_mutex_created_ptr = TX_NULL; \
+ _tx_mutex_created_count = TX_EMPTY
+#else
+#define _tx_mutex_initialize() \
+ _tx_mutex_created_ptr = TX_NULL; \
+ _tx_mutex_created_count = TX_EMPTY; \
+ _tx_mutex_performance_put_count = ((ULONG) 0); \
+ _tx_mutex_performance_get_count = ((ULONG) 0); \
+ _tx_mutex_performance_suspension_count = ((ULONG) 0); \
+ _tx_mutex_performance_timeout_count = ((ULONG) 0); \
+ _tx_mutex_performance_priority_inversion_count = ((ULONG) 0); \
+ _tx_mutex_performance__priority_inheritance_count = ((ULONG) 0)
+#endif
+#define TX_MUTEX_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call. */
+VOID _tx_mutex_initialize(VOID);
+#endif
+
+
+/* Define internal mutex management function prototypes. */
+
+VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr);
+VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority);
+
+
+/* Mutex management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_MUTEX_INIT
+#define MUTEX_DECLARE
+#else
+#define MUTEX_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created mutex list. */
+
+MUTEX_DECLARE TX_MUTEX * _tx_mutex_created_ptr;
+
+
+/* Define the variable that holds the number of created mutexes. */
+
+MUTEX_DECLARE ULONG _tx_mutex_created_count;
+
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of mutex puts. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance_put_count;
+
+
+/* Define the total number of mutex gets. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance_get_count;
+
+
+/* Define the total number of mutex suspensions. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance_suspension_count;
+
+
+/* Define the total number of mutex timeouts. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance_timeout_count;
+
+
+/* Define the total number of priority inversions. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance_priority_inversion_count;
+
+
+/* Define the total number of priority inheritance conditions. */
+
+MUTEX_DECLARE ULONG _tx_mutex_performance__priority_inheritance_count;
+
+
+#endif
+
+
+/* Define default post mutex delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_MUTEX_DELETE_PORT_COMPLETION
+#define TX_MUTEX_DELETE_PORT_COMPLETION(m)
+#endif
+
+
+#endif
diff --git a/common/inc/tx_queue.h b/common/inc/tx_queue.h
new file mode 100644
index 00000000..d6997cbc
--- /dev/null
+++ b/common/inc/tx_queue.h
@@ -0,0 +1,173 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_queue.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX queue management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_QUEUE_H
+#define TX_QUEUE_H
+
+
+/* Define queue control specific data definitions. */
+
+#define TX_QUEUE_ID ((ULONG) 0x51554555)
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the queue initialization
+ function. */
+
+#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#define _tx_queue_initialize() \
+ _tx_queue_created_ptr = TX_NULL; \
+ _tx_queue_created_count = TX_EMPTY
+#else
+#define _tx_queue_initialize() \
+ _tx_queue_created_ptr = TX_NULL; \
+ _tx_queue_created_count = TX_EMPTY; \
+ _tx_queue_performance_messages_sent_count = ((ULONG) 0); \
+ _tx_queue_performance__messages_received_count = ((ULONG) 0); \
+ _tx_queue_performance_empty_suspension_count = ((ULONG) 0); \
+ _tx_queue_performance_full_suspension_count = ((ULONG) 0); \
+ _tx_queue_performance_timeout_count = ((ULONG) 0)
+#endif
+#define TX_QUEUE_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call. */
+VOID _tx_queue_initialize(VOID);
+#endif
+
+
+/* Define the message copy macro. Note that the source and destination
+ pointers must be modified since they are used subsequently. */
+
+#ifndef TX_QUEUE_MESSAGE_COPY
+#define TX_QUEUE_MESSAGE_COPY(s, d, z) \
+ *(d)++ = *(s)++; \
+ if ((z) > ((UINT) 1)) \
+ { \
+ while (--(z)) \
+ { \
+ *(d)++ = *(s)++; \
+ } \
+ }
+#endif
+
+
+/* Define internal queue management function prototypes. */
+
+VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Queue management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_QUEUE_INIT
+#define QUEUE_DECLARE
+#else
+#define QUEUE_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created queue list. */
+
+QUEUE_DECLARE TX_QUEUE * _tx_queue_created_ptr;
+
+
+/* Define the variable that holds the number of created queues. */
+
+QUEUE_DECLARE ULONG _tx_queue_created_count;
+
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of messages sent. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance_messages_sent_count;
+
+
+/* Define the total number of messages received. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance__messages_received_count;
+
+
+/* Define the total number of queue empty suspensions. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance_empty_suspension_count;
+
+
+/* Define the total number of queue full suspensions. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance_full_suspension_count;
+
+
+/* Define the total number of queue full errors. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance_full_error_count;
+
+
+/* Define the total number of queue timeouts. */
+
+QUEUE_DECLARE ULONG _tx_queue_performance_timeout_count;
+
+
+#endif
+
+
+/* Define default post queue delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_QUEUE_DELETE_PORT_COMPLETION
+#define TX_QUEUE_DELETE_PORT_COMPLETION(q)
+#endif
+
+
+#endif
+
diff --git a/common/inc/tx_semaphore.h b/common/inc/tx_semaphore.h
new file mode 100644
index 00000000..78a2f78f
--- /dev/null
+++ b/common/inc/tx_semaphore.h
@@ -0,0 +1,144 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_semaphore.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX semaphore management component, */
+/* including all data types and external references. It is assumed */
+/* that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_SEMAPHORE_H
+#define TX_SEMAPHORE_H
+
+
+/* Define semaphore control specific data definitions. */
+
+#define TX_SEMAPHORE_ID ((ULONG) 0x53454D41)
+
+
+/* Determine if in-line component initialization is supported by the
+ caller. */
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+ /* Yes, in-line initialization is supported, remap the
+ semaphore initialization function. */
+#ifndef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+#define _tx_semaphore_initialize() \
+ _tx_semaphore_created_ptr = TX_NULL; \
+ _tx_semaphore_created_count = TX_EMPTY
+#else
+#define _tx_semaphore_initialize() \
+ _tx_semaphore_created_ptr = TX_NULL; \
+ _tx_semaphore_created_count = TX_EMPTY; \
+ _tx_semaphore_performance_put_count = ((ULONG) 0); \
+ _tx_semaphore_performance_get_count = ((ULONG) 0); \
+ _tx_semaphore_performance_suspension_count = ((ULONG) 0); \
+ _tx_semaphore_performance_timeout_count = ((ULONG) 0)
+#endif
+#define TX_SEMAPHORE_INIT
+#else
+ /* No in-line initialization is supported, use standard
+ function call. */
+VOID _tx_semaphore_initialize(VOID);
+#endif
+
+
+/* Define internal semaphore management function prototypes. */
+
+VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Semaphore management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_SEMAPHORE_INIT
+#define SEMAPHORE_DECLARE
+#else
+#define SEMAPHORE_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created semaphore list. */
+
+SEMAPHORE_DECLARE TX_SEMAPHORE * _tx_semaphore_created_ptr;
+
+
+/* Define the variable that holds the number of created semaphores. */
+
+SEMAPHORE_DECLARE ULONG _tx_semaphore_created_count;
+
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of semaphore puts. */
+
+SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_put_count;
+
+
+/* Define the total number of semaphore gets. */
+
+SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_get_count;
+
+
+/* Define the total number of semaphore suspensions. */
+
+SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_suspension_count;
+
+
+/* Define the total number of semaphore timeouts. */
+
+SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_timeout_count;
+
+
+#endif
+
+
+/* Define default post semaphore delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_SEMAPHORE_DELETE_PORT_COMPLETION
+#define TX_SEMAPHORE_DELETE_PORT_COMPLETION(s)
+#endif
+
+
+#endif
+
diff --git a/common/inc/tx_thread.h b/common/inc/tx_thread.h
new file mode 100644
index 00000000..f7e462b7
--- /dev/null
+++ b/common/inc/tx_thread.h
@@ -0,0 +1,524 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_thread.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX thread control component, including */
+/* data types and external references. It is assumed that tx_api.h */
+/* and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_THREAD_H
+#define TX_THREAD_H
+
+
+/* Define thread control specific data definitions. */
+
+#define TX_THREAD_ID ((ULONG) 0x54485244)
+#define TX_THREAD_PRIORITY_GROUP_MASK ((ULONG) 0xFF)
+#define TX_THREAD_EXECUTE_LOG_SIZE ((UINT) 8)
+
+
+/* Define the MOD32 bit set macro that is used to set/clear a priority bit within a specific
+ priority group. */
+
+#if TX_MAX_PRIORITIES > 32
+#define MAP_INDEX (map_index)
+#ifndef TX_MOD32_BIT_SET
+#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)%((UINT)32)));
+#endif
+#else
+#define MAP_INDEX (0)
+#ifndef TX_MOD32_BIT_SET
+#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)));
+#endif
+#endif
+
+
+/* Define the DIV32 bit set macro that is used to set/clear a priority group bit and is
+ only necessary when using priorities greater than 32. */
+
+#if TX_MAX_PRIORITIES > 32
+#ifndef TX_DIV32_BIT_SET
+#define TX_DIV32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)/((UINT) 32)));
+#endif
+#endif
+
+
+/* Define state change macro that can be used by run-mode debug agents to keep track of thread
+ state changes. By default, it is mapped to white space. */
+
+#ifndef TX_THREAD_STATE_CHANGE
+#define TX_THREAD_STATE_CHANGE(a, b)
+#endif
+
+
+/* Define the macro to get the current thread pointer. This is particularly useful in SMP
+ versions of ThreadX to add additional processing. The default implementation is to simply
+ access the global current thread pointer directly. */
+
+#ifndef TX_THREAD_GET_CURRENT
+#define TX_THREAD_GET_CURRENT(a) (a) = _tx_thread_current_ptr;
+#endif
+
+
+/* Define the macro to set the current thread pointer. This is particularly useful in SMP
+ versions of ThreadX to add additional processing. The default implementation is to simply
+ access the global current thread pointer directly. */
+
+#ifndef TX_THREAD_SET_CURRENT
+#define TX_THREAD_SET_CURRENT(a) _tx_thread_current_ptr = (a);
+#endif
+
+
+/* Define the get system state macro. By default, it simply maps to the variable _tx_thread_system_state. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#define TX_THREAD_GET_SYSTEM_STATE() _tx_thread_system_state
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = (ULONG) _tx_thread_preempt_disable; (c) = (c) | TX_THREAD_GET_SYSTEM_STATE();
+#endif
+
+
+/* Define the timeout setup macro used in _tx_thread_create. */
+
+#ifndef TX_THREAD_CREATE_TIMEOUT_SETUP
+#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
+ (t) -> tx_thread_timer.tx_timer_internal_timeout_param = TX_POINTER_TO_ULONG_CONVERT((t));
+#endif
+
+
+/* Define the thread timeout pointer setup macro used in _tx_thread_timeout. */
+
+#ifndef TX_THREAD_TIMEOUT_POINTER_SETUP
+#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = TX_ULONG_TO_THREAD_POINTER_CONVERT(timeout_input);
+#endif
+
+
+/* Define the lowest bit set macro. Note, that this may be overridden
+ by a port specific definition if there is supporting assembly language
+ instructions in the architecture. */
+
+#ifndef TX_LOWEST_SET_BIT_CALCULATE
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) \
+ (b) = ((ULONG) 0); \
+ (m) = (m) & ((~(m)) + ((ULONG) 1)); \
+ if ((m) < ((ULONG) 0x10)) \
+ { \
+ if ((m) >= ((ULONG) 4)) \
+ { \
+ (m) = (m) >> ((ULONG) 2); \
+ (b) = (b) + ((ULONG) 2); \
+ } \
+ (b) = (b) + ((m) >> ((ULONG) 1)); \
+ } \
+ else if ((m) < ((ULONG) 0x100)) \
+ { \
+ (m) = (m) >> ((ULONG) 4); \
+ (b) = (b) + ((ULONG) 4); \
+ if ((m) >= ((ULONG) 4)) \
+ { \
+ (m) = (m) >> ((ULONG) 2); \
+ (b) = (b) + ((ULONG) 2); \
+ } \
+ (b) = (b) + ((m) >> ((ULONG) 1)); \
+ } \
+ else if ((m) < ((ULONG) 0x10000)) \
+ { \
+ (m) = (m) >> ((ULONG) 8); \
+ (b) = (b) + ((ULONG) 8); \
+ if ((m) >= ((ULONG) 0x10)) \
+ { \
+ (m) = (m) >> ((ULONG) 4); \
+ (b) = (b) + ((ULONG) 4); \
+ } \
+ if ((m) >= ((ULONG) 4)) \
+ { \
+ (m) = (m) >> ((ULONG) 2); \
+ (b) = (b) + ((ULONG) 2); \
+ } \
+ (b) = (b) + ((m) >> ((ULONG) 1)); \
+ } \
+ else \
+ { \
+ (m) = (m) >> ((ULONG) 16); \
+ (b) = (b) + ((ULONG) 16); \
+ if ((m) >= ((ULONG) 0x100)) \
+ { \
+ (m) = (m) >> ((ULONG) 8); \
+ (b) = (b) + ((ULONG) 8); \
+ } \
+ if ((m) >= ((ULONG) 16)) \
+ { \
+ (m) = (m) >> ((ULONG) 4); \
+ (b) = (b) + ((ULONG) 4); \
+ } \
+ if ((m) >= ((ULONG) 4)) \
+ { \
+ (m) = (m) >> ((ULONG) 2); \
+ (b) = (b) + ((ULONG) 2); \
+ } \
+ (b) = (b) + ((m) >> ((ULONG) 1)); \
+ }
+#endif
+
+
+/* Define the default thread stack checking. This can be overridden by
+ a particular port, which is necessary if the stack growth is from
+ low address to high address (the default logic is for stacks that
+ grow from high address to low address. */
+
+#ifndef TX_THREAD_STACK_CHECK
+#define TX_THREAD_STACK_CHECK(thread_ptr) \
+ { \
+ TX_INTERRUPT_SAVE_AREA \
+ TX_DISABLE \
+ if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID)) \
+ { \
+ if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr)) \
+ { \
+ (thread_ptr) -> tx_thread_stack_highest_ptr = (thread_ptr) -> tx_thread_stack_ptr; \
+ } \
+ if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) || \
+ (*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) || \
+ (((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start))) \
+ { \
+ TX_RESTORE \
+ _tx_thread_stack_error_handler((thread_ptr)); \
+ TX_DISABLE \
+ } \
+ if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL) \
+ { \
+ TX_RESTORE \
+ _tx_thread_stack_analyze((thread_ptr)); \
+ TX_DISABLE \
+ } \
+ } \
+ TX_RESTORE \
+ }
+#endif
+
+
+/* Define default post thread delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_THREAD_DELETE_PORT_COMPLETION
+#define TX_THREAD_DELETE_PORT_COMPLETION(t)
+#endif
+
+
+/* Define default post thread reset macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_THREAD_RESET_PORT_COMPLETION
+#define TX_THREAD_RESET_PORT_COMPLETION(t)
+#endif
+
+
+/* Define the thread create internal extension macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_THREAD_CREATE_INTERNAL_EXTENSION
+#define TX_THREAD_CREATE_INTERNAL_EXTENSION(t)
+#endif
+
+
+/* Define internal thread control function prototypes. */
+
+VOID _tx_thread_initialize(VOID);
+VOID _tx_thread_schedule(VOID);
+VOID _tx_thread_shell_entry(VOID);
+VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr);
+VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID));
+VOID _tx_thread_stack_error(TX_THREAD *thread_ptr);
+VOID _tx_thread_stack_error_handler(TX_THREAD *thread_ptr);
+VOID _tx_thread_system_preempt_check(VOID);
+VOID _tx_thread_system_resume(TX_THREAD *thread_ptr);
+VOID _tx_thread_system_ni_resume(TX_THREAD *thread_ptr);
+VOID _tx_thread_system_return(VOID);
+VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr);
+VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option);
+VOID _tx_thread_time_slice(VOID);
+VOID _tx_thread_timeout(ULONG timeout_input);
+
+
+/* Thread control component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#define THREAD_DECLARE extern
+
+
+/* Define the pointer that contains the system stack pointer. This is
+ utilized when control returns from a thread to the system to reset the
+ current stack. This is setup in the low-level initialization function. */
+
+THREAD_DECLARE VOID * _tx_thread_system_stack_ptr;
+
+
+/* Define the current thread pointer. This variable points to the currently
+ executing thread. If this variable is NULL, no thread is executing. */
+
+THREAD_DECLARE TX_THREAD * _tx_thread_current_ptr;
+
+
+/* Define the variable that holds the next thread to execute. It is important
+ to remember that this is not necessarily equal to the current thread
+ pointer. */
+
+THREAD_DECLARE TX_THREAD * _tx_thread_execute_ptr;
+
+
+/* Define the head pointer of the created thread list. */
+
+THREAD_DECLARE TX_THREAD * _tx_thread_created_ptr;
+
+
+/* Define the variable that holds the number of created threads. */
+
+THREAD_DECLARE ULONG _tx_thread_created_count;
+
+
+/* Define the current state variable. When this value is 0, a thread
+ is executing or the system is idle. Other values indicate that
+ interrupt or initialization processing is active. This variable is
+ initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
+ active. */
+
+THREAD_DECLARE volatile ULONG _tx_thread_system_state;
+
+
+/* Define the 32-bit priority bit-maps. There is one priority bit map for each
+ 32 priority levels supported. If only 32 priorities are supported there is
+ only one bit map. Each bit within a priority bit map represents that one
+ or more threads at the associated thread priority are ready. */
+
+THREAD_DECLARE ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
+
+
+/* Define the priority map active bit map that specifies which of the previously
+ defined priority maps have something set. This is only necessary if more than
+ 32 priorities are supported. */
+
+#if TX_MAX_PRIORITIES > 32
+THREAD_DECLARE ULONG _tx_thread_priority_map_active;
+#endif
+
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+/* Define the 32-bit preempt priority bit maps. There is one preempt bit map
+ for each 32 priority levels supported. If only 32 priorities are supported
+ there is only one bit map. Each set set bit corresponds to a preempted priority
+ level that had preemption-threshold active to protect against preemption of a
+ range of relatively higher priority threads. */
+
+THREAD_DECLARE ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
+
+
+/* Define the preempt map active bit map that specifies which of the previously
+ defined preempt maps have something set. This is only necessary if more than
+ 32 priorities are supported. */
+
+#if TX_MAX_PRIORITIES > 32
+THREAD_DECLARE ULONG _tx_thread_preempted_map_active;
+#endif
+#endif
+
+/* Define the variable that holds the highest priority group ready for
+ execution. It is important to note that this is not necessarily the same
+ as the priority of the thread pointed to by _tx_execute_thread. */
+
+THREAD_DECLARE UINT _tx_thread_highest_priority;
+
+
+/* Define the array of thread pointers. Each entry represents the threads that
+ are ready at that priority group. For example, index 10 in this array
+ represents the first thread ready at priority 10. If this entry is NULL,
+ no threads are ready at that priority. */
+
+THREAD_DECLARE TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES];
+
+
+/* Define the global preempt disable variable. If this is non-zero, preemption is
+ disabled. It is used internally by ThreadX to prevent preemption of a thread in
+ the middle of a service that is resuming or suspending another thread. */
+
+THREAD_DECLARE volatile UINT _tx_thread_preempt_disable;
+
+
+/* Define the global function pointer for mutex cleanup on thread completion or
+ termination. This pointer is setup during mutex initialization. */
+
+THREAD_DECLARE VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
+
+
+/* Define the global build options variable. This contains a bit map representing
+ how the ThreadX library was built. The following are the bit field definitions:
+
+ Bit(s) Meaning
+
+ 31 TX_NOT_INTERRUPTABLE defined
+ 30 TX_INLINE_THREAD_RESUME_SUSPEND define
+ 29-24 Priority groups 1 -> 32 priorities
+ 2 -> 64 priorities
+ 3 -> 96 priorities
+
+ ...
+
+ 32 -> 1024 priorities
+ 23 TX_TIMER_PROCESS_IN_ISR defined
+ 22 TX_REACTIVATE_INLINE defined
+ 21 TX_DISABLE_STACK_FILLING defined
+ 20 TX_ENABLE_STACK_CHECKING defined
+ 19 TX_DISABLE_PREEMPTION_THRESHOLD defined
+ 18 TX_DISABLE_REDUNDANT_CLEARING defined
+ 17 TX_DISABLE_NOTIFY_CALLBACKS defined
+ 16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
+ 15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
+ 14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
+ 13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
+ 12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
+ 11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
+ 10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined
+ 9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined
+ 8 TX_ENABLE_EVENT_TRACE defined
+ 7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
+ 6-0 Port Specific */
+
+THREAD_DECLARE ULONG _tx_build_options;
+
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+/* Define the global function pointer for stack error handling. If a stack error is
+ detected and the application has registered a stack error handler, it will be
+ called via this function pointer. */
+
+THREAD_DECLARE VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
+
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of thread resumptions. Each time a thread enters the
+ ready state this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_resume_count;
+
+
+/* Define the total number of thread suspensions. Each time a thread enters a
+ suspended state this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_suspend_count;
+
+
+/* Define the total number of solicited thread preemptions. Each time a thread is
+ preempted by directly calling a ThreadX service, this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_solicited_preemption_count;
+
+
+/* Define the total number of interrupt thread preemptions. Each time a thread is
+ preempted as a result of an ISR calling a ThreadX service, this variable is
+ incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_interrupt_preemption_count;
+
+
+/* Define the total number of priority inversions. Each time a thread is blocked by
+ a mutex owned by a lower-priority thread, this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_priority_inversion_count;
+
+
+/* Define the total number of time-slices. Each time a time-slice operation is
+ actually performed (another thread is setup for running) this variable is
+ incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_time_slice_count;
+
+
+/* Define the total number of thread relinquish operations. Each time a thread
+ relinquish operation is actually performed (another thread is setup for running)
+ this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_relinquish_count;
+
+
+/* Define the total number of thread timeouts. Each time a thread has a
+ timeout this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_timeout_count;
+
+
+/* Define the total number of thread wait aborts. Each time a thread's suspension
+ is lifted by the tx_thread_wait_abort call this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_wait_abort_count;
+
+
+/* Define the total number of idle system thread returns. Each time a thread returns to
+ an idle system (no other thread is ready to run) this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_idle_return_count;
+
+
+/* Define the total number of non-idle system thread returns. Each time a thread returns to
+ a non-idle system (another thread is ready to run) this variable is incremented. */
+
+THREAD_DECLARE ULONG _tx_thread_performance_non_idle_return_count;
+
+
+/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
+ is a circular list, where the index points to the oldest entry. */
+
+THREAD_DECLARE ULONG _tx_thread_performance__execute_log_index;
+THREAD_DECLARE TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
+
+#endif
+
+#endif
+
diff --git a/common/inc/tx_timer.h b/common/inc/tx_timer.h
new file mode 100644
index 00000000..9d0522c9
--- /dev/null
+++ b/common/inc/tx_timer.h
@@ -0,0 +1,213 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_timer.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX timer management component, including */
+/* data types and external references. It is assumed that tx_api.h */
+/* and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_TIMER_H
+#define TX_TIMER_H
+
+
+/* Define timer management specific data definitions. */
+
+#define TX_TIMER_ID ((ULONG) 0x4154494D)
+#define TX_TIMER_ENTRIES ((ULONG) 32)
+
+
+/* Define internal timer management function prototypes. */
+
+VOID _tx_timer_expiration_process(VOID);
+VOID _tx_timer_initialize(VOID);
+VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr);
+VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr);
+VOID _tx_timer_thread_entry(ULONG timer_thread_input);
+
+
+/* Timer management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_TIMER_INIT
+#define TIMER_DECLARE
+#else
+#define TIMER_DECLARE extern
+#endif
+
+
+/* Define the system clock value that is continually incremented by the
+ periodic timer interrupt processing. */
+
+TIMER_DECLARE volatile ULONG _tx_timer_system_clock;
+
+
+/* Define the current time slice value. If non-zero, a time-slice is active.
+ Otherwise, the time_slice is not active. */
+
+TIMER_DECLARE ULONG _tx_timer_time_slice;
+
+
+/* Define the time-slice expiration flag. This is used to indicate that a time-slice
+ has happened. */
+
+TIMER_DECLARE UINT _tx_timer_expired_time_slice;
+
+
+/* Define the thread and application timer entry list. This list provides a direct access
+ method for insertion of times less than TX_TIMER_ENTRIES. */
+
+TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES];
+
+
+/* Define the boundary pointers to the list. These are setup to easily manage
+ wrapping the list. */
+
+TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_start;
+TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_end;
+
+
+/* Define the current timer pointer in the list. This pointer is moved sequentially
+ through the timer list by the timer interrupt handler. */
+
+TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_current_ptr;
+
+
+/* Define the timer expiration flag. This is used to indicate that a timer
+ has expired. */
+
+TIMER_DECLARE UINT _tx_timer_expired;
+
+
+/* Define the created timer list head pointer. */
+
+TIMER_DECLARE TX_TIMER *_tx_timer_created_ptr;
+
+
+/* Define the created timer count. */
+
+TIMER_DECLARE ULONG _tx_timer_created_count;
+
+
+/* Define the pointer to the timer that has expired and is being processed. */
+
+TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr;
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+/* Define the timer thread's control block. */
+
+TIMER_DECLARE TX_THREAD _tx_timer_thread;
+
+
+/* Define the variable that holds the timer thread's starting stack address. */
+
+TIMER_DECLARE VOID *_tx_timer_stack_start;
+
+
+/* Define the variable that holds the timer thread's stack size. */
+
+TIMER_DECLARE ULONG _tx_timer_stack_size;
+
+
+/* Define the variable that holds the timer thread's priority. */
+
+TIMER_DECLARE UINT _tx_timer_priority;
+
+/* Define the system timer thread's stack. The default size is defined
+ in tx_port.h. */
+
+TIMER_DECLARE ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG)) - ((UINT) 1)))/sizeof(ULONG)];
+
+#else
+
+
+/* Define the busy flag that will prevent nested timer ISR processing. */
+
+TIMER_DECLARE UINT _tx_timer_processing_active;
+
+#endif
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of timer activations. */
+
+TIMER_DECLARE ULONG _tx_timer_performance_activate_count;
+
+
+/* Define the total number of timer reactivations. */
+
+TIMER_DECLARE ULONG _tx_timer_performance_reactivate_count;
+
+
+/* Define the total number of timer deactivations. */
+
+TIMER_DECLARE ULONG _tx_timer_performance_deactivate_count;
+
+
+/* Define the total number of timer expirations. */
+
+TIMER_DECLARE ULONG _tx_timer_performance_expiration_count;
+
+
+/* Define the total number of timer expiration adjustments. These are required
+ if the expiration time is greater than the size of the timer list. In such
+ cases, the timer is placed at the end of the list and then reactivated
+ as many times as necessary to finally achieve the resulting timeout. */
+
+TIMER_DECLARE ULONG _tx_timer_performance__expiration_adjust_count;
+
+
+#endif
+
+
+/* Define default post timer delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
+
+#ifndef TX_TIMER_DELETE_PORT_COMPLETION
+#define TX_TIMER_DELETE_PORT_COMPLETION(t)
+#endif
+
+
+#endif
diff --git a/common/inc/tx_trace.h b/common/inc/tx_trace.h
new file mode 100644
index 00000000..f8e98cf7
--- /dev/null
+++ b/common/inc/tx_trace.h
@@ -0,0 +1,559 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_trace.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX trace component, including constants */
+/* and structure definitions as well as external references. It is */
+/* assumed that tx_api.h and tx_port.h have already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+
+/* Include necessary system files. */
+
+#ifndef TX_TRACE_H
+#define TX_TRACE_H
+
+
+/* Determine if tracing is enabled. If not, simply define the in-line trace
+ macros to whitespace. */
+
+#ifndef TX_ENABLE_EVENT_TRACE
+#define TX_TRACE_INITIALIZE
+#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b)
+#define TX_TRACE_OBJECT_UNREGISTER(o)
+#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,f)
+#else
+
+/* Event tracing is enabled. */
+
+/* Ensure that the thread component information is included. */
+
+#include "tx_thread.h"
+
+
+/* Define trace port-specfic extension to white space if it isn't defined
+ already. */
+
+#ifndef TX_TRACE_PORT_EXTENSION
+#define TX_TRACE_PORT_EXTENSION
+#endif
+
+
+/* Define the default clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the ID showing the event trace buffer is valid. */
+
+#define TX_TRACE_VALID 0x54585442UL
+
+
+/* ThreadX Trace Description. The ThreadX Trace feature is designed to capture
+ events in real-time in a circular event buffer. This buffer may be analyzed by other
+ tools. The high-level format of the Trace structure is:
+
+ [Trace Control Header ]
+ [Trace Object Registry - Entry 0 ]
+ ...
+ [Trace Object Registry - Entry "n" ]
+ [Trace Buffer - Entry 0 ]
+ ...
+ [Trace Buffer - Entry "n" ]
+
+*/
+
+
+/* Trace Control Header. The Trace Control Header contains information that
+ defines the format of the Trace Object Registry as well as the location and
+ current entry of the Trace Buffer itself. The high-level format of the
+ Trace Control Header is:
+
+ Entry Size Description
+
+ [Trace ID] 4 This 4-byte field contains the ThreadX Trace
+ Identification. If the trace buffer is valid, the
+ contents are 0x54585442 (TXTB). Since it is written as
+ a 32-bit unsigned word, this value is also used to
+ determine if the event trace information is in
+ little or big endian format.
+ [Timer Valid Mask] 4 Mask of valid bits in the 32-bit time stamp. This
+ enables use of 32, 24, 16, or event 8-bit timers.
+ If the time source is 32-bits, the mask is
+ 0xFFFFFFFF. If the time source is 16-bits, the
+ mask is 0x0000FFFF.
+ [Trace Base Address] 4 The base address for all trace pointer. Subtracting
+ the pointer and this address will yield the proper
+ offset into the trace buffer.
+ [Trace Object Registry Start Pointer] 4 Pointer to the start of Trace Object Registry
+ [Reserved] 2 Reserved two bytes - should be 0x0000
+ [Trace Object Object Name Size] 2 Number of bytes in object name
+ [Trace Object Registry End Pointer] 4 Pointer to the end of Trace Object Registry
+ [Trace Buffer Start Pointer] 4 Pointer to the start of the Trace Buffer Area
+ [Trace Buffer End Pointer] 4 Pointer to the end of the Trace Buffer Area
+ [Trace Buffer Current Pointer] 4 Pointer to the oldest entry in the Trace Buffer.
+ This entry will be overwritten on the next event and
+ incremented to the next event (wrapping to the top
+ if the buffer end pointer is exceeded).
+ [Reserved] 4 Reserved 4 bytes, should be 0xAAAAAAAA
+ [Reserved] 4 Reserved 4 bytes, should be 0xBBBBBBBB
+ [Reserved] 4 Reserved 4 bytes, should be 0xCCCCCCCC
+*/
+
+
+/* Define the Trace Control Header. */
+
+typedef struct TX_TRACE_HEADER_STRUCT
+{
+
+ ULONG tx_trace_header_id;
+ ULONG tx_trace_header_timer_valid_mask;
+ ULONG tx_trace_header_trace_base_address;
+ ULONG tx_trace_header_registry_start_pointer;
+ USHORT tx_trace_header_reserved1;
+ USHORT tx_trace_header_object_name_size;
+ ULONG tx_trace_header_registry_end_pointer;
+ ULONG tx_trace_header_buffer_start_pointer;
+ ULONG tx_trace_header_buffer_end_pointer;
+ ULONG tx_trace_header_buffer_current_pointer;
+ ULONG tx_trace_header_reserved2;
+ ULONG tx_trace_header_reserved3;
+ ULONG tx_trace_header_reserved4;
+} TX_TRACE_HEADER;
+
+
+/* Trace Object Registry. The Trace Object Registry is used to map the object pointer in the trace buffer to
+ the application's name for the object (defined during object creation in ThreadX). */
+
+#ifndef TX_TRACE_OBJECT_REGISTRY_NAME
+#define TX_TRACE_OBJECT_REGISTRY_NAME 32
+#endif
+
+
+/* Define the object name types as well as the contents of any additional parameters that might be useful in
+ trace analysis. */
+
+#define TX_TRACE_OBJECT_TYPE_NOT_VALID ((UCHAR) 0) /* Object is not valid */
+#define TX_TRACE_OBJECT_TYPE_THREAD ((UCHAR) 1) /* P1 = stack start address, P2 = stack size */
+#define TX_TRACE_OBJECT_TYPE_TIMER ((UCHAR) 2) /* P1 = initial ticks, P2 = reschedule ticks */
+#define TX_TRACE_OBJECT_TYPE_QUEUE ((UCHAR) 3) /* P1 = queue size, P2 = message size */
+#define TX_TRACE_OBJECT_TYPE_SEMAPHORE ((UCHAR) 4) /* P1 = initial instances */
+#define TX_TRACE_OBJECT_TYPE_MUTEX ((UCHAR) 5) /* P1 = priority inheritance flag */
+#define TX_TRACE_OBJECT_TYPE_EVENT_FLAGS ((UCHAR) 6) /* none */
+#define TX_TRACE_OBJECT_TYPE_BLOCK_POOL ((UCHAR) 7) /* P1 = total blocks, P2 = block size */
+#define TX_TRACE_OBJECT_TYPE_BYTE_POOL ((UCHAR) 8) /* P1 = total bytes */
+
+
+typedef struct TX_TRACE_OBJECT_ENTRY_STRUCT
+{
+
+ UCHAR tx_trace_object_entry_available; /* TX_TRUE -> available */
+ UCHAR tx_trace_object_entry_type; /* Types defined above */
+ UCHAR tx_trace_object_entry_reserved1; /* Should be zero - except for thread */
+ UCHAR tx_trace_object_entry_reserved2; /* Should be zero - except for thread */
+ ULONG tx_trace_object_entry_thread_pointer; /* ThreadX object pointer */
+ ULONG tx_trace_object_entry_param_1; /* Parameter value defined */
+ ULONG tx_trace_object_entry_param_2; /* according to type above */
+ UCHAR tx_trace_object_entry_name[TX_TRACE_OBJECT_REGISTRY_NAME]; /* Object name */
+} TX_TRACE_OBJECT_ENTRY;
+
+
+/* Trace Buffer Entry. The Trace Buffer Entry contains information about a particular
+ event in the system. The high-level format of the Trace Buffer Entry is:
+
+ Entry Size Description
+
+ [Thread Pointer] 4 This 4-byte field contains the pointer to the
+ ThreadX thread running that caused the event.
+ If this field is NULL, the entry hasn't been used
+ yet. If this field is 0xFFFFFFFF, the event occurred
+ from within an ISR. If this entry is 0xF0F0F0F0, the
+ event occurred during initialization.
+ [Thread Priority or 4 This 4-byte field contains the current thread pointer for interrupt
+ Current Thread events or the thread preemption-threshold/priority for thread events.
+ Preemption-Threshold/
+ Priority]
+ [Event ID] 4 This 4-byte field contains the Event ID of the event. A value of
+ 0xFFFFFFFF indicates the event is invalid. All events are marked
+ as invalid during initialization.
+ [Time Stamp] 4 This 4-byte field contains the time stamp of the event.
+ [Information Field 1] 4 This 4-byte field contains the first 4-bytes of information
+ specific to the event.
+ [Information Field 2] 4 This 4-byte field contains the second 4-bytes of information
+ specific to the event.
+ [Information Field 3] 4 This 4-byte field contains the third 4-bytes of information
+ specific to the event.
+ [Information Field 4] 4 This 4-byte field contains the fourth 4-bytes of information
+ specific to the event.
+*/
+
+#define TX_TRACE_INVALID_EVENT 0xFFFFFFFFUL
+
+
+/* Define ThreadX Trace Events, along with a brief description of the additional information fields,
+ where I1 -> Information Field 1, I2 -> Information Field 2, etc. */
+
+/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are:
+
+ ThreadX events: 1-199
+ FileX events: 200-299
+ NetX events: 300-599
+ USBX events: 600-999
+
+ User-defined event numbers start at 4096 and continue through 65535, as defined by the constants
+ TX_TRACE_USER_EVENT_START and TX_TRACE_USER_EVENT_END, respectively. User events should be based
+ on these constants in case the user event number assignment is changed in future releases. */
+
+/* Define the basic ThreadX thread scheduling events first. */
+
+#define TX_TRACE_THREAD_RESUME 1 /* I1 = thread ptr, I2 = previous_state, I3 = stack ptr, I4 = next thread */
+#define TX_TRACE_THREAD_SUSPEND 2 /* I1 = thread ptr, I2 = new_state, I3 = stack ptr I4 = next thread */
+#define TX_TRACE_ISR_ENTER 3 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
+#define TX_TRACE_ISR_EXIT 4 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
+#define TX_TRACE_TIME_SLICE 5 /* I1 = next thread ptr, I2 = system state, I3 = preempt disable, I4 = stack*/
+#define TX_TRACE_RUNNING 6 /* None */
+
+
+/* Define the rest of the ThreadX system events. */
+
+#define TX_TRACE_BLOCK_ALLOCATE 10 /* I1 = pool ptr, I2 = memory ptr, I3 = wait option, I4 = remaining blocks */
+#define TX_TRACE_BLOCK_POOL_CREATE 11 /* I1 = pool ptr, I2 = pool_start, I3 = total blocks, I4 = block size */
+#define TX_TRACE_BLOCK_POOL_DELETE 12 /* I1 = pool ptr, I2 = stack ptr */
+#define TX_TRACE_BLOCK_POOL_INFO_GET 13 /* I1 = pool ptr */
+#define TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET 14 /* I1 = pool ptr */
+#define TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET 15 /* None */
+#define TX_TRACE_BLOCK_POOL_PRIORITIZE 16 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
+#define TX_TRACE_BLOCK_RELEASE 17 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = stack ptr */
+#define TX_TRACE_BYTE_ALLOCATE 20 /* I1 = pool ptr, I2 = memory ptr, I3 = size requested, I4 = wait option */
+#define TX_TRACE_BYTE_POOL_CREATE 21 /* I1 = pool ptr, I2 = start ptr, I3 = pool size, I4 = stack ptr */
+#define TX_TRACE_BYTE_POOL_DELETE 22 /* I1 = pool ptr, I2 = stack ptr */
+#define TX_TRACE_BYTE_POOL_INFO_GET 23 /* I1 = pool ptr */
+#define TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET 24 /* I1 = pool ptr */
+#define TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET 25 /* None */
+#define TX_TRACE_BYTE_POOL_PRIORITIZE 26 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
+#define TX_TRACE_BYTE_RELEASE 27 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = available bytes */
+#define TX_TRACE_EVENT_FLAGS_CREATE 30 /* I1 = group ptr, I2 = stack ptr */
+#define TX_TRACE_EVENT_FLAGS_DELETE 31 /* I1 = group ptr, I2 = stack ptr */
+#define TX_TRACE_EVENT_FLAGS_GET 32 /* I1 = group ptr, I2 = requested flags, I3 = current flags, I4 = get option*/
+#define TX_TRACE_EVENT_FLAGS_INFO_GET 33 /* I1 = group ptr */
+#define TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET 34 /* I1 = group ptr */
+#define TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET 35 /* None */
+#define TX_TRACE_EVENT_FLAGS_SET 36 /* I1 = group ptr, I2 = flags to set, I3 = set option, I4= suspended count */
+#define TX_TRACE_EVENT_FLAGS_SET_NOTIFY 37 /* I1 = group ptr */
+#define TX_TRACE_INTERRUPT_CONTROL 40 /* I1 = new interrupt posture, I2 = stack ptr */
+#define TX_TRACE_MUTEX_CREATE 50 /* I1 = mutex ptr, I2 = inheritance, I3 = stack ptr */
+#define TX_TRACE_MUTEX_DELETE 51 /* I1 = mutex ptr, I2 = stack ptr */
+#define TX_TRACE_MUTEX_GET 52 /* I1 = mutex ptr, I2 = wait option, I3 = owning thread, I4 = own count */
+#define TX_TRACE_MUTEX_INFO_GET 53 /* I1 = mutex ptr */
+#define TX_TRACE_MUTEX_PERFORMANCE_INFO_GET 54 /* I1 = mutex ptr */
+#define TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET 55 /* None */
+#define TX_TRACE_MUTEX_PRIORITIZE 56 /* I1 = mutex ptr, I2 = suspended count, I3 = stack ptr */
+#define TX_TRACE_MUTEX_PUT 57 /* I1 = mutex ptr, I2 = owning thread, I3 = own count, I4 = stack ptr */
+#define TX_TRACE_QUEUE_CREATE 60 /* I1 = queue ptr, I2 = message size, I3 = queue start, I4 = queue size */
+#define TX_TRACE_QUEUE_DELETE 61 /* I1 = queue ptr, I2 = stack ptr */
+#define TX_TRACE_QUEUE_FLUSH 62 /* I1 = queue ptr, I2 = stack ptr */
+#define TX_TRACE_QUEUE_FRONT_SEND 63 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
+#define TX_TRACE_QUEUE_INFO_GET 64 /* I1 = queue ptr */
+#define TX_TRACE_QUEUE_PERFORMANCE_INFO_GET 65 /* I1 = queue ptr */
+#define TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET 66 /* None */
+#define TX_TRACE_QUEUE_PRIORITIZE 67 /* I1 = queue ptr, I2 = suspended count, I3 = stack ptr */
+#define TX_TRACE_QUEUE_RECEIVE 68 /* I1 = queue ptr, I2 = destination ptr, I3 = wait option, I4 = enqueued */
+#define TX_TRACE_QUEUE_SEND 69 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
+#define TX_TRACE_QUEUE_SEND_NOTIFY 70 /* I1 = queue ptr */
+#define TX_TRACE_SEMAPHORE_CEILING_PUT 80 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4 =ceiling */
+#define TX_TRACE_SEMAPHORE_CREATE 81 /* I1 = semaphore ptr, I2 = initial count, I3 = stack ptr */
+#define TX_TRACE_SEMAPHORE_DELETE 82 /* I1 = semaphore ptr, I2 = stack ptr */
+#define TX_TRACE_SEMAPHORE_GET 83 /* I1 = semaphore ptr, I2 = wait option, I3 = current count, I4 = stack ptr */
+#define TX_TRACE_SEMAPHORE_INFO_GET 84 /* I1 = semaphore ptr */
+#define TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET 85 /* I1 = semaphore ptr */
+#define TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET 86 /* None */
+#define TX_TRACE_SEMAPHORE_PRIORITIZE 87 /* I1 = semaphore ptr, I2 = suspended count, I2 = stack ptr */
+#define TX_TRACE_SEMAPHORE_PUT 88 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4=stack ptr*/
+#define TX_TRACE_SEMAPHORE_PUT_NOTIFY 89 /* I1 = semaphore ptr */
+#define TX_TRACE_THREAD_CREATE 100 /* I1 = thread ptr, I2 = priority, I3 = stack ptr, I4 = stack_size */
+#define TX_TRACE_THREAD_DELETE 101 /* I1 = thread ptr, I2 = stack ptr */
+#define TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY 102 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_THREAD_IDENTIFY 103 /* None */
+#define TX_TRACE_THREAD_INFO_GET 104 /* I1 = thread ptr, I2 = thread state */
+#define TX_TRACE_THREAD_PERFORMANCE_INFO_GET 105 /* I1 = thread ptr, I2 = thread state */
+#define TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET 106 /* None */
+#define TX_TRACE_THREAD_PREEMPTION_CHANGE 107 /* I1 = thread ptr, I2 = new threshold, I3 = old threshold, I4 =thread state*/
+#define TX_TRACE_THREAD_PRIORITY_CHANGE 108 /* I1 = thread ptr, I2 = new priority, I3 = old priority, I4 = thread state */
+#define TX_TRACE_THREAD_RELINQUISH 109 /* I1 = stack ptr, I2 = next thread ptr */
+#define TX_TRACE_THREAD_RESET 110 /* I1 = thread ptr, I2 = thread state */
+#define TX_TRACE_THREAD_RESUME_API 111 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_THREAD_SLEEP 112 /* I1 = sleep value, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_THREAD_STACK_ERROR_NOTIFY 113 /* None */
+#define TX_TRACE_THREAD_SUSPEND_API 114 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_THREAD_TERMINATE 115 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_THREAD_TIME_SLICE_CHANGE 116 /* I1 = thread ptr, I2 = new timeslice, I3 = old timeslice */
+#define TX_TRACE_THREAD_WAIT_ABORT 117 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
+#define TX_TRACE_TIME_GET 120 /* I1 = current time, I2 = stack ptr */
+#define TX_TRACE_TIME_SET 121 /* I1 = new time */
+#define TX_TRACE_TIMER_ACTIVATE 122 /* I1 = timer ptr */
+#define TX_TRACE_TIMER_CHANGE 123 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks */
+#define TX_TRACE_TIMER_CREATE 124 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks, I4 = enable */
+#define TX_TRACE_TIMER_DEACTIVATE 125 /* I1 = timer ptr, I2 = stack ptr */
+#define TX_TRACE_TIMER_DELETE 126 /* I1 = timer ptr */
+#define TX_TRACE_TIMER_INFO_GET 127 /* I1 = timer ptr, I2 = stack ptr */
+#define TX_TRACE_TIMER_PERFORMANCE_INFO_GET 128 /* I1 = timer ptr */
+#define TX_TRACE_TIMER_PERFORMANCE_SYSTEM_INFO_GET 129 /* None */
+
+
+/* Define the an Trace Buffer Entry. */
+
+typedef struct TX_TRACE_BUFFER_ENTRY_STRUCT
+{
+
+ ULONG tx_trace_buffer_entry_thread_pointer;
+ ULONG tx_trace_buffer_entry_thread_priority;
+ ULONG tx_trace_buffer_entry_event_id;
+ ULONG tx_trace_buffer_entry_time_stamp;
+#ifdef TX_MISRA_ENABLE
+ ULONG tx_trace_buffer_entry_info_1;
+ ULONG tx_trace_buffer_entry_info_2;
+ ULONG tx_trace_buffer_entry_info_3;
+ ULONG tx_trace_buffer_entry_info_4;
+#else
+ ULONG tx_trace_buffer_entry_information_field_1;
+ ULONG tx_trace_buffer_entry_information_field_2;
+ ULONG tx_trace_buffer_entry_information_field_3;
+ ULONG tx_trace_buffer_entry_information_field_4;
+#endif
+} TX_TRACE_BUFFER_ENTRY;
+
+
+/* Trace management component data declarations follow. */
+
+/* Determine if the initialization function of this component is including
+ this file. If so, make the data definitions really happen. Otherwise,
+ make them extern so other functions in the component can access them. */
+
+#ifdef TX_TRACE_INIT
+#define TRACE_DECLARE
+#else
+#define TRACE_DECLARE extern
+#endif
+
+
+/* Define the pointer to the start of the trace buffer control structure. */
+
+TRACE_DECLARE TX_TRACE_HEADER *_tx_trace_header_ptr;
+
+
+/* Define the pointer to the start of the trace object registry area in the trace buffer. */
+
+TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_start_ptr;
+
+
+/* Define the pointer to the end of the trace object registry area in the trace buffer. */
+
+TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_end_ptr;
+
+
+/* Define the pointer to the starting entry of the actual trace event area of the trace buffer. */
+
+TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr;
+
+
+/* Define the pointer to the ending entry of the actual trace event area of the trace buffer. */
+
+TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr;
+
+
+/* Define the pointer to the current entry of the actual trace event area of the trace buffer. */
+
+TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr;
+
+
+/* Define the trace event enable bits, where each bit represents a type of event that can be enabled
+ or disabled dynamically by the application. */
+
+TRACE_DECLARE ULONG _tx_trace_event_enable_bits;
+
+
+/* Define a counter that is used in environments that don't have a timer source. This counter
+ is incremented on each use giving each event a unique timestamp. */
+
+TRACE_DECLARE ULONG _tx_trace_simulated_time;
+
+
+/* Define the function pointer used to call the application when the trace buffer wraps. If NULL,
+ the application has not registered a callback function. */
+
+TRACE_DECLARE VOID (*_tx_trace_full_notify_function)(VOID *buffer);
+
+
+/* Define the total number of registry entries. */
+
+TRACE_DECLARE ULONG _tx_trace_total_registry_entries;
+
+
+/* Define a counter that is used to track the number of available registry entries. */
+
+TRACE_DECLARE ULONG _tx_trace_available_registry_entries;
+
+
+/* Define an index that represents the start of the registry search. */
+
+TRACE_DECLARE ULONG _tx_trace_registry_search_start;
+
+
+/* Define the event trace macros that are expanded in-line when event tracing is enabled. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (d);
+#else
+#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (d);
+#endif
+
+
+#define TX_TRACE_INITIALIZE _tx_trace_initialize();
+#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (CHAR *) (n), (ULONG) (a), (ULONG) (b));
+#define TX_TRACE_OBJECT_UNREGISTER(o) _tx_trace_object_unregister((VOID *) (o));
+#ifndef TX_TRACE_IN_LINE_INSERT
+#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) \
+ { \
+ TX_TRACE_BUFFER_ENTRY *trace_event_ptr; \
+ ULONG trace_system_state; \
+ ULONG trace_priority; \
+ TX_THREAD *trace_thread_ptr; \
+ trace_event_ptr = _tx_trace_buffer_current_ptr; \
+ if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (e)))) \
+ { \
+ TX_TRACE_PORT_EXTENSION \
+ trace_system_state = (ULONG) TX_THREAD_GET_SYSTEM_STATE(); \
+ TX_THREAD_GET_CURRENT(trace_thread_ptr) \
+ \
+ if (trace_system_state == 0) \
+ { \
+ trace_priority = trace_thread_ptr -> tx_thread_priority; \
+ trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16); \
+ } \
+ else if (trace_system_state < 0xF0F0F0F0UL) \
+ { \
+ trace_priority = (ULONG) trace_thread_ptr; \
+ trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL; \
+ } \
+ else \
+ { \
+ trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL; \
+ trace_priority = 0; \
+ } \
+ trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr; \
+ trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority; \
+ trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (i); \
+ trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) TX_TRACE_TIME_SOURCE; \
+ TX_TRACE_INFO_FIELD_ASSIGNMENT((a),(b),(c),(d)) \
+ trace_event_ptr++; \
+ if (trace_event_ptr >= _tx_trace_buffer_end_ptr) \
+ { \
+ trace_event_ptr = _tx_trace_buffer_start_ptr; \
+ _tx_trace_buffer_current_ptr = trace_event_ptr; \
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
+ if (_tx_trace_full_notify_function) \
+ (_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr); \
+ } \
+ else \
+ { \
+ _tx_trace_buffer_current_ptr = trace_event_ptr; \
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
+ } \
+ } \
+ }
+#endif
+#endif
+
+
+#ifdef TX_SOURCE_CODE
+
+/* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */
+
+VOID _tx_trace_initialize(VOID);
+VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2);
+VOID _tx_trace_object_unregister(VOID *object_ptr);
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/* Check for MISRA compliance requirements. */
+
+#ifdef TX_MISRA_ENABLE
+
+/* Define MISRA-specific routines. */
+
+UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer);
+TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer);
+TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer);
+TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer);
+UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer);
+
+
+#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_object_to_uchar_pointer_convert((a))
+#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) _tx_misra_uchar_to_object_pointer_convert((a))
+#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) _tx_misra_uchar_to_header_pointer_convert((a))
+#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) _tx_misra_uchar_to_entry_pointer_convert((a))
+#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_entry_to_uchar_pointer_convert((a))
+
+#else
+
+#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) ((TX_TRACE_OBJECT_ENTRY *) ((VOID *) (a)))
+#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) ((TX_TRACE_HEADER *) ((VOID *) (a)))
+#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) ((TX_TRACE_BUFFER_ENTRY *) ((VOID *) (a)))
+#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
+
+#endif
+#endif
+#endif
+#endif
+
diff --git a/common/inc/tx_user_sample.h b/common/inc/tx_user_sample.h
new file mode 100644
index 00000000..8a2e5166
--- /dev/null
+++ b/common/inc/tx_user_sample.h
@@ -0,0 +1,257 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** User Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_user.h PORTABLE C */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains user defines for configuring ThreadX in specific */
+/* ways. This file will have an effect only if the application and */
+/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */
+/* Note that all the defines in this file may also be made on the */
+/* command line when building ThreadX library and application objects. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_USER_H
+#define TX_USER_H
+
+
+/* Define various build options for the ThreadX port. The application should either make changes
+ here by commenting or un-commenting the conditional compilation defined OR supply the defines
+ though the compiler's equivalent of the -D option.
+
+ For maximum speed, the following should be defined:
+
+ TX_MAX_PRIORITIES 32
+ TX_DISABLE_PREEMPTION_THRESHOLD
+ TX_DISABLE_REDUNDANT_CLEARING
+ TX_DISABLE_NOTIFY_CALLBACKS
+ TX_NOT_INTERRUPTABLE
+ TX_TIMER_PROCESS_IN_ISR
+ TX_REACTIVATE_INLINE
+ TX_DISABLE_STACK_FILLING
+ TX_INLINE_THREAD_RESUME_SUSPEND
+
+ For minimum size, the following should be defined:
+
+ TX_MAX_PRIORITIES 32
+ TX_DISABLE_PREEMPTION_THRESHOLD
+ TX_DISABLE_REDUNDANT_CLEARING
+ TX_DISABLE_NOTIFY_CALLBACKS
+ TX_NOT_INTERRUPTABLE
+ TX_TIMER_PROCESS_IN_ISR
+
+ Of course, many of these defines reduce functionality and/or change the behavior of the
+ system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR
+ results in faster and smaller code, however, it increases the amount of processing in the ISR.
+ In addition, some services that are available in timers are not available from ISRs and will
+ therefore return an error if this option is used. This may or may not be desirable for a
+ given application. */
+
+
+/* Override various options with default values already assigned in tx_port.h. Please also refer
+ to tx_port.h for descriptions on each of these options. */
+
+/*
+#define TX_MAX_PRIORITIES 32
+#define TX_MINIMUM_STACK ????
+#define TX_THREAD_USER_EXTENSION ????
+#define TX_TIMER_THREAD_STACK_SIZE ????
+#define TX_TIMER_THREAD_PRIORITY ????
+*/
+
+/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls
+ should be processed within the a system timer thread or directly in the timer ISR.
+ By default, the timer thread is used. When the following is defined, the timer expiration
+ processing is done directly from the timer ISR, thereby eliminating the timer thread control
+ block, stack, and context switching to activate it. */
+
+/*
+#define TX_TIMER_PROCESS_IN_ISR
+*/
+
+/* Determine if in-line timer reactivation should be used within the timer expiration processing.
+ By default, this is disabled and a function call is used. When the following is defined,
+ reactivating is performed in-line resulting in faster timer processing but slightly larger
+ code size. */
+
+/*
+#define TX_REACTIVATE_INLINE
+*/
+
+/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled,
+ which places an 0xEF pattern in each byte of each thread's stack. This is used by
+ debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */
+
+/*
+#define TX_DISABLE_STACK_FILLING
+*/
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+/*
+#define TX_ENABLE_STACK_CHECKING
+*/
+
+/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is
+ enabled. If the application does not use preemption-threshold, it may be disabled to reduce
+ code size and improve performance. */
+
+/*
+#define TX_DISABLE_PREEMPTION_THRESHOLD
+*/
+
+/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears
+ the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary
+ clearing of ThreadX global variables. */
+
+/*
+#define TX_DISABLE_REDUNDANT_CLEARING
+*/
+
+/* Determine if no timer processing is required. This option will help eliminate the timer
+ processing when not needed. The user will also have to comment out the call to
+ tx_timer_interrupt, which is typically made from assembly language in
+ tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR
+ must also be used. */
+
+/*
+#define TX_NO_TIMER
+#ifndef TX_TIMER_PROCESS_IN_ISR
+#define TX_TIMER_PROCESS_IN_ISR
+#endif
+*/
+
+/* Determine if the notify callback option should be disabled. By default, notify callbacks are
+ enabled. If the application does not use notify callbacks, they may be disabled to reduce
+ code size and improve performance. */
+
+/*
+#define TX_DISABLE_NOTIFY_CALLBACKS
+*/
+
+
+/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal
+ code in-line. This results in a larger image, but improves the performance of the thread
+ resume and suspend services. */
+
+/*
+#define TX_INLINE_THREAD_RESUME_SUSPEND
+*/
+
+
+/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code
+ size and less processing overhead, but increases the interrupt lockout time. */
+
+/*
+#define TX_NOT_INTERRUPTABLE
+*/
+
+
+/* Determine if the trace event logging code should be enabled. This causes slight increases in
+ code size and overhead, but provides the ability to generate system trace information which
+ is available for viewing in TraceX. */
+
+/*
+#define TX_ENABLE_EVENT_TRACE
+*/
+
+
+/* Determine if block pool performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various block pool performance information. */
+
+/*
+#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if byte pool performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various byte pool performance information. */
+
+/*
+#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if event flags performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various event flags performance information. */
+
+/*
+#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if mutex performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various mutex performance information. */
+
+/*
+#define TX_MUTEX_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if queue performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various queue performance information. */
+
+/*
+#define TX_QUEUE_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if semaphore performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various semaphore performance information. */
+
+/*
+#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if thread performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various thread performance information. */
+
+/*
+#define TX_THREAD_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if timer performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various timer performance information. */
+
+/*
+#define TX_TIMER_ENABLE_PERFORMANCE_INFO
+*/
+
+#endif
+
diff --git a/common/src/tx_block_allocate.c b/common/src/tx_block_allocate.c
new file mode 100644
index 00000000..1035e681
--- /dev/null
+++ b/common/src/tx_block_allocate.c
@@ -0,0 +1,372 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_trace.h"
+#endif
+#include "tx_thread.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_allocate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocates a block from the specified memory block */
+/* pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* block_ptr Pointer to place allocated block */
+/* pointer */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Suspend thread */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+TX_THREAD *thread_ptr;
+UCHAR *work_ptr;
+UCHAR *temp_ptr;
+UCHAR **next_block_ptr;
+UCHAR **return_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *entry_ptr;
+ULONG time_stamp = ((ULONG) 0);
+#endif
+#ifdef TX_ENABLE_EVENT_LOGGING
+UCHAR *log_entry_ptr;
+ULONG upper_tbu;
+ULONG lower_tbu;
+#endif
+
+
+ /* Disable interrupts to get a block from the pool. */
+ TX_DISABLE
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total allocations counter. */
+ _tx_block_pool_performance_allocate_count++;
+
+ /* Increment the number of allocations on this pool. */
+ pool_ptr -> tx_block_pool_performance_allocate_count++;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_ALLOCATE, pool_ptr, 0, wait_option, pool_ptr -> tx_block_pool_available, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time the allocate
+ call succeeds. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ log_entry_ptr = *(UCHAR **) _tx_el_current_event;
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_ALLOCATE_INSERT
+
+ /* Store -1 in the third event slot. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) -1;
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time the allocate
+ call succeeds. */
+ lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET));
+ upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET));
+#endif
+
+ /* Determine if there is an available block. */
+ if (pool_ptr -> tx_block_pool_available != ((UINT) 0))
+ {
+
+ /* Yes, a block is available. Decrement the available count. */
+ pool_ptr -> tx_block_pool_available--;
+
+ /* Pickup the current block pointer. */
+ work_ptr = pool_ptr -> tx_block_pool_available_list;
+
+ /* Return the first available block to the caller. */
+ temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
+ return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
+ *return_ptr = temp_ptr;
+
+ /* Modify the available list to point at the next block in the pool. */
+ next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ pool_ptr -> tx_block_pool_available_list = *next_block_ptr;
+
+ /* Save the pool's address in the block for when it is released! */
+ temp_ptr = TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
+ *next_block_ptr = temp_ptr;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the time stamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, update the entry with the address. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
+#endif
+ }
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ /* Store the address of the allocated block. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr;
+#endif
+
+ /* Set status to success. */
+ status = TX_SUCCESS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Default the return pointer to NULL. */
+ return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
+ *return_ptr = TX_NULL;
+
+ /* Determine if the request specifies suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */
+ status = TX_NO_MEMORY;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total suspensions counter. */
+ _tx_block_pool_performance_suspension_count++;
+
+ /* Increment the number of suspensions on this pool. */
+ pool_ptr -> tx_block_pool_performance_suspension_count++;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
+
+ /* Setup cleanup information, i.e. this pool control
+ block. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr;
+
+ /* Save the return block pointer address as well. */
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) block_ptr;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Pickup the number of suspended threads. */
+ suspended_count = (pool_ptr -> tx_block_pool_suspended_count);
+
+ /* Increment the number of suspended threads. */
+ (pool_ptr -> tx_block_pool_suspended_count)++;
+
+ /* Setup suspension list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ pool_ptr -> tx_block_pool_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = pool_ptr -> tx_block_pool_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_BLOCK_MEMORY;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the time-stamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, update the entry with the address. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
+#endif
+ }
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ /* Check that the event time stamp is unchanged and the call is about
+ to return success. A different timestamp means that a later event
+ wrote over the block allocate event. A return value other than
+ TX_SUCCESS indicates that no block was available. In those cases,
+ do nothing here. */
+ if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
+ upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) &&
+ ((thread_ptr -> tx_thread_suspend_status) == TX_SUCCESS))
+ {
+
+ /* Store the address of the allocated block. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr;
+ }
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Immediate return, return error completion. */
+ status = TX_NO_MEMORY;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_block_pool_cleanup.c b/common/src/tx_block_pool_cleanup.c
new file mode 100644
index 00000000..6578e5c5
--- /dev/null
+++ b/common/src/tx_block_pool_cleanup.c
@@ -0,0 +1,213 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes block allocate timeout and thread terminate */
+/* actions that require the block pool data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_BLOCK_POOL *pool_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the block pool. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_block_pool_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to block pool control block. */
+ pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for a NULL byte pool pointer. */
+ if (pool_ptr != TX_NULL)
+ {
+
+ /* Check for valid pool ID. */
+ if (pool_ptr -> tx_block_pool_id == TX_BLOCK_POOL_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (pool_ptr -> tx_block_pool_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to block pool control block. */
+ pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Yes, we still have thread suspension! */
+
+ /* Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Decrement the suspended count. */
+ pool_ptr -> tx_block_pool_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = pool_ptr -> tx_block_pool_suspended_count;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (pool_ptr -> tx_block_pool_suspension_list == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ pool_ptr -> tx_block_pool_suspension_list = next_thread;
+ }
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_BLOCK_MEMORY)
+ {
+
+ /* Timeout condition and the thread still suspended on the block pool.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_block_pool_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this block pool. */
+ pool_ptr -> tx_block_pool_performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_block_pool_create.c b/common/src/tx_block_pool_create.c
new file mode 100644
index 00000000..4d74cc03
--- /dev/null
+++ b/common/src/tx_block_pool_create.c
@@ -0,0 +1,213 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a pool of fixed-size memory blocks in the */
+/* specified memory area. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* name_ptr Pointer to block pool name */
+/* block_size Number of bytes in each block */
+/* pool_start Address of beginning of pool area */
+/* pool_size Number of bytes in the block pool */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
+ VOID *pool_start, ULONG pool_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT blocks;
+UINT status;
+ULONG total_blocks;
+UCHAR *block_ptr;
+UCHAR **block_link_ptr;
+UCHAR *next_block_ptr;
+TX_BLOCK_POOL *next_pool;
+TX_BLOCK_POOL *previous_pool;
+
+
+ /* Initialize block pool control block to all zeros. */
+ TX_MEMSET(pool_ptr, 0, (sizeof(TX_BLOCK_POOL)));
+
+ /* Round the block size up to something that is evenly divisible by
+ an ALIGN_TYPE (typically this is a 32-bit ULONG). This helps guarantee proper alignment. */
+ block_size = (((block_size + (sizeof(ALIGN_TYPE))) - ((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
+
+ /* Round the pool size down to something that is evenly divisible by
+ an ALIGN_TYPE (typically this is a 32-bit ULONG). */
+ pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
+
+ /* Setup the basic block pool fields. */
+ pool_ptr -> tx_block_pool_name = name_ptr;
+ pool_ptr -> tx_block_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ pool_ptr -> tx_block_pool_size = pool_size;
+ pool_ptr -> tx_block_pool_block_size = (UINT) block_size;
+
+ /* Calculate the total number of blocks. */
+ total_blocks = pool_size/(block_size + (sizeof(UCHAR *)));
+
+ /* Walk through the pool area, setting up the available block list. */
+ blocks = ((UINT) 0);
+ block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
+ while(blocks < (UINT) total_blocks)
+ {
+
+ /* Yes, we have another block. Increment the block count. */
+ blocks++;
+
+ /* Setup the link to the next block. */
+ block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
+ *block_link_ptr = next_block_ptr;
+
+ /* Advance to the next block. */
+ block_ptr = next_block_ptr;
+
+ /* Update the next block pointer. */
+ next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
+ }
+
+ /* Save the remaining information in the pool control block. */
+ pool_ptr -> tx_block_pool_available = blocks;
+ pool_ptr -> tx_block_pool_total = blocks;
+
+ /* Quickly check to make sure at least one block is in the pool. */
+ if (blocks != ((UINT) 0))
+ {
+
+ /* Backup to the last block in the pool. */
+ block_ptr = TX_UCHAR_POINTER_SUB(block_ptr,(block_size + (sizeof(UCHAR *))));
+
+ /* Set the last block's forward pointer to NULL. */
+ block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
+ *block_link_ptr = TX_NULL;
+
+ /* Setup the starting pool address. */
+ pool_ptr -> tx_block_pool_available_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+
+ /* Disable interrupts to place the block pool on the created list. */
+ TX_DISABLE
+
+ /* Setup the block pool ID to make it valid. */
+ pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID;
+
+ /* Place the block pool on the list of created block pools. First,
+ check for an empty list. */
+ if (_tx_block_pool_created_count == TX_EMPTY)
+ {
+
+ /* The created block pool list is empty. Add block pool to empty list. */
+ _tx_block_pool_created_ptr = pool_ptr;
+ pool_ptr -> tx_block_pool_created_next = pool_ptr;
+ pool_ptr -> tx_block_pool_created_previous = pool_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_pool = _tx_block_pool_created_ptr;
+ previous_pool = next_pool -> tx_block_pool_created_previous;
+
+ /* Place the new block pool in the list. */
+ next_pool -> tx_block_pool_created_previous = pool_ptr;
+ previous_pool -> tx_block_pool_created_next = pool_ptr;
+
+ /* Setup this block pool's created links. */
+ pool_ptr -> tx_block_pool_created_previous = previous_pool;
+ pool_ptr -> tx_block_pool_created_next = next_pool;
+ }
+
+ /* Increment the created count. */
+ _tx_block_pool_created_count++;
+
+ /* Optional block pool create extended processing. */
+ TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, pool_ptr, name_ptr, pool_size, block_size)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), blocks, block_size, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return successful status. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Not enough memory for one block, return appropriate error. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_block_pool_delete.c b/common/src/tx_block_pool_delete.c
new file mode 100644
index 00000000..8e52e444
--- /dev/null
+++ b/common/src/tx_block_pool_delete.c
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified block pool. All threads */
+/* suspended on the block pool are resumed with the TX_DELETED status */
+/* code. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+UINT suspended_count;
+TX_BLOCK_POOL *next_pool;
+TX_BLOCK_POOL *previous_pool;
+
+
+ /* Disable interrupts to remove the block pool from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_DELETE_INSERT
+
+ /* Optional block pool delete extended processing. */
+ TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(pool_ptr)
+
+ /* Clear the block pool ID to make it invalid. */
+ pool_ptr -> tx_block_pool_id = TX_CLEAR_ID;
+
+ /* Decrement the number of block pools. */
+ _tx_block_pool_created_count--;
+
+ /* See if the block pool is the only one on the list. */
+ if (_tx_block_pool_created_count == TX_EMPTY)
+ {
+
+ /* Only created block pool, just set the created list to NULL. */
+ _tx_block_pool_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_pool = pool_ptr -> tx_block_pool_created_next;
+ previous_pool = pool_ptr -> tx_block_pool_created_previous;
+ next_pool -> tx_block_pool_created_previous = previous_pool;
+ previous_pool -> tx_block_pool_created_next = next_pool;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_block_pool_created_ptr == pool_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_block_pool_created_ptr = next_pool;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = pool_ptr -> tx_block_pool_suspension_list;
+ pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
+ suspended_count = pool_ptr -> tx_block_pool_suspended_count;
+ pool_ptr -> tx_block_pool_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the block pool suspension list to resume any and all threads suspended
+ on this block pool. */
+ while (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_BLOCK_POOL_DELETE_PORT_COMPLETION(pool_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_block_pool_info_get.c b/common/src/tx_block_pool_info_get.c
new file mode 100644
index 00000000..20b2d130
--- /dev/null
+++ b/common/src/tx_block_pool_info_get.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified block pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to block pool control blk */
+/* name Destination for the pool name */
+/* available_blocks Number of free blocks in pool */
+/* total_blocks Total number of blocks in pool */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on block pool */
+/* suspended_count Destination for suspended count */
+/* next_pool Destination for pointer to next */
+/* block pool on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
+ ULONG *total_blocks, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BLOCK_POOL **next_pool)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the block pool. */
+ if (name != TX_NULL)
+ {
+
+ *name = pool_ptr -> tx_block_pool_name;
+ }
+
+ /* Retrieve the number of available blocks in the block pool. */
+ if (available_blocks != TX_NULL)
+ {
+
+ *available_blocks = (ULONG) pool_ptr -> tx_block_pool_available;
+ }
+
+ /* Retrieve the total number of blocks in the block pool. */
+ if (total_blocks != TX_NULL)
+ {
+
+ *total_blocks = (ULONG) pool_ptr -> tx_block_pool_total;
+ }
+
+ /* Retrieve the first thread suspended on this block pool. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = pool_ptr -> tx_block_pool_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this block pool. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) pool_ptr -> tx_block_pool_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next block pool created. */
+ if (next_pool != TX_NULL)
+ {
+
+ *next_pool = pool_ptr -> tx_block_pool_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_block_pool_initialize.c b/common/src/tx_block_pool_initialize.c
new file mode 100644
index 00000000..26c6a561
--- /dev/null
+++ b/common/src/tx_block_pool_initialize.c
@@ -0,0 +1,129 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Locate block pool component data in this file. */
+
+/* Define the head pointer of the created block pool list. */
+
+TX_BLOCK_POOL * _tx_block_pool_created_ptr;
+
+
+/* Define the variable that holds the number of created block pools. */
+
+ULONG _tx_block_pool_created_count;
+
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of block allocates. */
+
+ULONG _tx_block_pool_performance_allocate_count;
+
+
+/* Define the total number of block releases. */
+
+ULONG _tx_block_pool_performance_release_count;
+
+
+/* Define the total number of block pool suspensions. */
+
+ULONG _tx_block_pool_performance_suspension_count;
+
+
+/* Define the total number of block pool timeouts. */
+
+ULONG _tx_block_pool_performance_timeout_count;
+
+#endif
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block pool_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the block pool component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_block_pool_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created block pools list and the
+ number of block pools created. */
+ _tx_block_pool_created_ptr = TX_NULL;
+ _tx_block_pool_created_count = TX_EMPTY;
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize block pool performance counters. */
+ _tx_block_pool_performance_allocate_count = ((ULONG) 0);
+ _tx_block_pool_performance_release_count = ((ULONG) 0);
+ _tx_block_pool_performance_suspension_count = ((ULONG) 0);
+ _tx_block_pool_performance_timeout_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_block_pool_performance_info_get.c b/common/src/tx_block_pool_performance_info_get.c
new file mode 100644
index 00000000..9c0cf098
--- /dev/null
+++ b/common/src/tx_block_pool_performance_info_get.c
@@ -0,0 +1,201 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* block pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to block pool control blk */
+/* allocates Destination for the number of */
+/* allocations from this pool */
+/* releases Destination for the number of */
+/* blocks released back to pool */
+/* suspensions Destination for number of */
+/* suspensions on this pool */
+/* timeouts Destination for number of timeouts*/
+/* on this pool */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
+ ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Block pool pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the pool ID is invalid. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Block pool pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of allocations from this block pool. */
+ if (allocates != TX_NULL)
+ {
+
+ *allocates = pool_ptr -> tx_block_pool_performance_allocate_count;
+ }
+
+ /* Retrieve the number of blocks released to this block pool. */
+ if (releases != TX_NULL)
+ {
+
+ *releases = pool_ptr -> tx_block_pool_performance_release_count;
+ }
+
+ /* Retrieve the number of thread suspensions on this block pool. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = pool_ptr -> tx_block_pool_performance_suspension_count;
+ }
+
+ /* Retrieve the number of thread timeouts on this block pool. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = pool_ptr -> tx_block_pool_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (pool_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (allocates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (releases != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_block_pool_performance_system_info_get.c b/common/src/tx_block_pool_performance_system_info_get.c
new file mode 100644
index 00000000..317003b9
--- /dev/null
+++ b/common/src/tx_block_pool_performance_system_info_get.c
@@ -0,0 +1,173 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves block pool performance information. */
+/* */
+/* INPUT */
+/* */
+/* allocates Destination for the total number */
+/* of block allocations */
+/* releases Destination for the total number */
+/* of blocks released */
+/* suspensions Destination for the total number */
+/* of suspensions */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_performance_system_info_get(ULONG *allocates, ULONG *releases, ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of block allocations. */
+ if (allocates != TX_NULL)
+ {
+
+ *allocates = _tx_block_pool_performance_allocate_count;
+ }
+
+ /* Retrieve the total number of blocks released. */
+ if (releases != TX_NULL)
+ {
+
+ *releases = _tx_block_pool_performance_release_count;
+ }
+
+ /* Retrieve the total number of block pool thread suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_block_pool_performance_suspension_count;
+ }
+
+ /* Retrieve the total number of block pool thread timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_block_pool_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (allocates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (releases != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_block_pool_prioritize.c b/common/src/tx_block_pool_prioritize.c
new file mode 100644
index 00000000..d78f53e5
--- /dev/null
+++ b/common/src/tx_block_pool_prioritize.c
@@ -0,0 +1,249 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the highest priority suspended thread at the */
+/* front of the suspension list. All other threads remain in the same */
+/* FIFO suspension order. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *priority_thread_ptr;
+TX_THREAD *head_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT list_changed;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = pool_ptr -> tx_block_pool_suspended_count;
+
+ /* Determine if there are fewer than 2 suspended threads. */
+ if (suspended_count < ((UINT) 2))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if there how many threads are suspended on this block memory pool. */
+ else if (suspended_count == ((UINT) 2))
+ {
+
+ /* Pickup the head pointer and the next pointer. */
+ head_ptr = pool_ptr -> tx_block_pool_suspension_list;
+ next_thread = head_ptr -> tx_thread_suspended_next;
+
+ /* Determine if the next suspended thread has a higher priority. */
+ if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
+ {
+
+ /* Yes, move the list head to the next thread. */
+ pool_ptr -> tx_block_pool_suspension_list = next_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = pool_ptr -> tx_block_pool_suspension_list;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the list changed flag to false. */
+ list_changed = TX_FALSE;
+
+ /* Search through the list to find the highest priority thread. */
+ do
+ {
+
+ /* Is the current thread higher priority? */
+ if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, remember that this thread is the highest priority. */
+ priority_thread_ptr = thread_ptr;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Determine if any changes to the list have occurred while
+ interrupts were enabled. */
+
+ /* Is the list head the same? */
+ if (head_ptr != pool_ptr -> tx_block_pool_suspension_list)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ else
+ {
+
+ /* Is the suspended count the same? */
+ if (suspended_count != pool_ptr -> tx_block_pool_suspended_count)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ }
+
+ /* Determine if the list has changed. */
+ if (list_changed == TX_FALSE)
+ {
+
+ /* Move the thread pointer to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = pool_ptr -> tx_block_pool_suspension_list;
+ suspended_count = pool_ptr -> tx_block_pool_suspended_count;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Reset the list changed flag. */
+ list_changed = TX_FALSE;
+ }
+
+ } while (thread_ptr != head_ptr);
+
+ /* Release preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Now determine if the highest priority thread is at the front
+ of the list. */
+ if (priority_thread_ptr != head_ptr)
+ {
+
+ /* No, we need to move the highest priority suspended thread to the
+ front of the list. */
+
+ /* First, remove the highest priority thread by updating the
+ adjacent suspended threads. */
+ next_thread = priority_thread_ptr -> tx_thread_suspended_next;
+ previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Now, link the highest priority thread at the front of the list. */
+ previous_thread = head_ptr -> tx_thread_suspended_previous;
+ priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
+ priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
+ head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
+
+ /* Move the list head pointer to the highest priority suspended thread. */
+ pool_ptr -> tx_block_pool_suspension_list = priority_thread_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return successful status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_block_release.c b/common/src/tx_block_release.c
new file mode 100644
index 00000000..ce69a53f
--- /dev/null
+++ b/common/src/tx_block_release.c
@@ -0,0 +1,204 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_release PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns a previously allocated block to its */
+/* associated memory block pool. */
+/* */
+/* INPUT */
+/* */
+/* block_ptr Pointer to memory block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_block_release(VOID *block_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_BLOCK_POOL *pool_ptr;
+TX_THREAD *thread_ptr;
+UCHAR *work_ptr;
+UCHAR **return_block_ptr;
+UCHAR **next_block_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+ /* Disable interrupts to put this block back in the pool. */
+ TX_DISABLE
+
+ /* Pickup the pool pointer which is just previous to the starting
+ address of the block that the caller sees. */
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
+ work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *)));
+ next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT((*next_block_ptr));
+
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total releases counter. */
+ _tx_block_pool_performance_release_count++;
+
+ /* Increment the number of releases on this pool. */
+ pool_ptr -> tx_block_pool_performance_release_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(block_ptr), pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&work_ptr), TX_TRACE_BLOCK_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BLOCK_RELEASE_INSERT
+
+ /* Determine if there are any threads suspended on the block pool. */
+ thread_ptr = pool_ptr -> tx_block_pool_suspension_list;
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Remove the suspended thread from the list. */
+
+ /* Decrement the number of threads suspended. */
+ (pool_ptr -> tx_block_pool_suspended_count)--;
+
+ /* Pickup the suspended count. */
+ suspended_count = (pool_ptr -> tx_block_pool_suspended_count);
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ pool_ptr -> tx_block_pool_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Return this block pointer to the suspended thread waiting for
+ a block. */
+ return_block_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
+ *return_block_ptr = work_ptr;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+ }
+ else
+ {
+
+ /* No thread is suspended for a memory block. */
+
+ /* Put the block back in the available list. */
+ *next_block_ptr = pool_ptr -> tx_block_pool_available_list;
+
+ /* Adjust the head pointer. */
+ pool_ptr -> tx_block_pool_available_list = work_ptr;
+
+ /* Increment the count of available blocks. */
+ pool_ptr -> tx_block_pool_available++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Return successful completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_byte_allocate.c b/common/src/tx_byte_allocate.c
new file mode 100644
index 00000000..caa15f4c
--- /dev/null
+++ b/common/src/tx_byte_allocate.c
@@ -0,0 +1,409 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_trace.h"
+#endif
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_allocate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocates bytes from the specified memory byte */
+/* pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* memory_ptr Pointer to place allocated bytes */
+/* pointer */
+/* memory_size Number of bytes to allocate */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Suspend thread service */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* _tx_byte_pool_search Search byte pool for memory */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+TX_THREAD *thread_ptr;
+UCHAR *work_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT finished;
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *entry_ptr;
+ULONG time_stamp = ((ULONG) 0);
+#endif
+#ifdef TX_ENABLE_EVENT_LOGGING
+UCHAR *log_entry_ptr;
+ULONG upper_tbu;
+ULONG lower_tbu;
+#endif
+
+
+ /* Round the memory size up to the next size that is evenly divisible by
+ an ALIGN_TYPE (this is typically a 32-bit ULONG). This guarantees proper alignment. */
+ memory_size = (((memory_size + (sizeof(ALIGN_TYPE)))-((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total allocations counter. */
+ _tx_byte_pool_performance_allocate_count++;
+
+ /* Increment the number of allocations on this pool. */
+ pool_ptr -> tx_byte_pool_performance_allocate_count++;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_ALLOCATE, pool_ptr, 0, memory_size, wait_option, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time the allocate
+ call succeeds. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ log_entry_ptr = *(UCHAR **) _tx_el_current_event;
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_ALLOCATE_INSERT
+
+ /* Store -1 in the fourth event slot. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) -1;
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time the allocate
+ call succeeds. */
+ lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET));
+ upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET));
+#endif
+
+ /* Set the search finished flag to false. */
+ finished = TX_FALSE;
+
+ /* Loop to handle cases where the owner of the pool changed. */
+ do
+ {
+
+ /* Indicate that this thread is the current owner. */
+ pool_ptr -> tx_byte_pool_owner = thread_ptr;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* At this point, the executing thread owns the pool and can perform a search
+ for free memory. */
+ work_ptr = _tx_byte_pool_search(pool_ptr, memory_size);
+
+ /* Optional processing extension. */
+ TX_BYTE_ALLOCATE_EXTENSION
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Determine if we are finished. */
+ if (work_ptr != TX_NULL)
+ {
+
+ /* Yes, we have found a block the search is finished. */
+ finished = TX_TRUE;
+ }
+ else
+ {
+
+ /* No block was found, does this thread still own the pool? */
+ if (pool_ptr -> tx_byte_pool_owner == thread_ptr)
+ {
+
+ /* Yes, then we have looked through the entire pool and haven't found the memory. */
+ finished = TX_TRUE;
+ }
+ }
+
+ } while (finished == TX_FALSE);
+
+ /* Copy the pointer into the return destination. */
+ *memory_ptr = (VOID *) work_ptr;
+
+ /* Determine if memory was found. */
+ if (work_ptr != TX_NULL)
+ {
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, update the entry with the address. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
+#endif
+ }
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
+ upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)))
+ {
+ /* Store the address of the allocated fragment. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr;
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Set the status to success. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* No memory of sufficient size was found... */
+
+ /* Determine if the request specifies suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_NO_MEMORY;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total suspensions counter. */
+ _tx_byte_pool_performance_suspension_count++;
+
+ /* Increment the number of suspensions on this pool. */
+ pool_ptr -> tx_byte_pool_performance_suspension_count++;
+#endif
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
+
+ /* Setup cleanup information, i.e. this pool control
+ block. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr;
+
+ /* Save the return memory pointer address as well. */
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) memory_ptr;
+
+ /* Save the byte size requested. */
+ thread_ptr -> tx_thread_suspend_info = memory_size;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Pickup the number of suspended threads. */
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+
+ /* Increment the suspension count. */
+ (pool_ptr -> tx_byte_pool_suspended_count)++;
+
+ /* Setup suspension list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ pool_ptr -> tx_byte_pool_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = pool_ptr -> tx_byte_pool_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_BYTE_MEMORY;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, update the entry with the address. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
+#endif
+ }
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ /* Check that the event time stamp is unchanged. A different
+ timestamp means that a later event wrote over the byte
+ allocate event. In that case, do nothing here. */
+ if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
+ upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)))
+ {
+
+ /* Store the address of the allocated fragment. */
+ *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr;
+ }
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Immediate return, return error completion. */
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_byte_pool_cleanup.c b/common/src/tx_byte_pool_cleanup.c
new file mode 100644
index 00000000..c013c2ae
--- /dev/null
+++ b/common/src/tx_byte_pool_cleanup.c
@@ -0,0 +1,212 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes byte allocate timeout and thread terminate */
+/* actions that require the byte pool data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_BYTE_POOL *pool_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the byte pool. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_byte_pool_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to byte pool control block. */
+ pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for a NULL byte pool pointer. */
+ if (pool_ptr != TX_NULL)
+ {
+
+ /* Check for valid pool ID. */
+ if (pool_ptr -> tx_byte_pool_id == TX_BYTE_POOL_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to byte pool control block. */
+ pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Thread suspended for memory... Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Decrement the suspension count. */
+ pool_ptr -> tx_byte_pool_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (pool_ptr -> tx_byte_pool_suspension_list == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ pool_ptr -> tx_byte_pool_suspension_list = next_thread;
+ }
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_BYTE_MEMORY)
+ {
+
+ /* Timeout condition and the thread still suspended on the byte pool.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_byte_pool_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this byte pool. */
+ pool_ptr -> tx_byte_pool_performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_byte_pool_create.c b/common/src/tx_byte_pool_create.c
new file mode 100644
index 00000000..7c19823c
--- /dev/null
+++ b/common/src/tx_byte_pool_create.c
@@ -0,0 +1,197 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a pool of memory bytes in the specified */
+/* memory area. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* name_ptr Pointer to byte pool name */
+/* pool_start Address of beginning of pool area */
+/* pool_size Number of bytes in the byte pool */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UCHAR *block_ptr;
+UCHAR **block_indirect_ptr;
+UCHAR *temp_ptr;
+TX_BYTE_POOL *next_pool;
+TX_BYTE_POOL *previous_pool;
+ALIGN_TYPE *free_ptr;
+
+
+ /* Initialize the byte pool control block to all zeros. */
+ TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL)));
+
+ /* Round the pool size down to something that is evenly divisible by
+ an ULONG. */
+ pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
+
+ /* Setup the basic byte pool fields. */
+ pool_ptr -> tx_byte_pool_name = name_ptr;
+
+ /* Save the start and size of the pool. */
+ pool_ptr -> tx_byte_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ pool_ptr -> tx_byte_pool_size = pool_size;
+
+ /* Setup memory list to the beginning as well as the search pointer. */
+ pool_ptr -> tx_byte_pool_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ pool_ptr -> tx_byte_pool_search = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+
+ /* Initially, the pool will have two blocks. One large block at the
+ beginning that is available and a small allocated block at the end
+ of the pool that is there just for the algorithm. Be sure to count
+ the available block's header in the available bytes count. */
+ pool_ptr -> tx_byte_pool_available = pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
+ pool_ptr -> tx_byte_pool_fragments = ((UINT) 2);
+
+ /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE
+ field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the
+ owning pool (if the block is allocated). */
+
+ /* Calculate the end of the pool's memory area. */
+ block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, pool_size);
+
+ /* Backup the end of the pool pointer and build the pre-allocated block. */
+ block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
+
+ /* Cast the pool pointer into a ULONG. */
+ temp_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
+ block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
+ *block_indirect_ptr = temp_ptr;
+
+ block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
+ block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
+ *block_indirect_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+
+ /* Now setup the large available block in the pool. */
+ temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
+ *block_indirect_ptr = block_ptr;
+ block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
+ block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
+ *free_ptr = TX_BYTE_BLOCK_FREE;
+
+ /* Clear the owner id. */
+ pool_ptr -> tx_byte_pool_owner = TX_NULL;
+
+ /* Disable interrupts to place the byte pool on the created list. */
+ TX_DISABLE
+
+ /* Setup the byte pool ID to make it valid. */
+ pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID;
+
+ /* Place the byte pool on the list of created byte pools. First,
+ check for an empty list. */
+ if (_tx_byte_pool_created_count == TX_EMPTY)
+ {
+
+ /* The created byte pool list is empty. Add byte pool to empty list. */
+ _tx_byte_pool_created_ptr = pool_ptr;
+ pool_ptr -> tx_byte_pool_created_next = pool_ptr;
+ pool_ptr -> tx_byte_pool_created_previous = pool_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_pool = _tx_byte_pool_created_ptr;
+ previous_pool = next_pool -> tx_byte_pool_created_previous;
+
+ /* Place the new byte pool in the list. */
+ next_pool -> tx_byte_pool_created_previous = pool_ptr;
+ previous_pool -> tx_byte_pool_created_next = pool_ptr;
+
+ /* Setup this byte pool's created links. */
+ pool_ptr -> tx_byte_pool_created_previous = previous_pool;
+ pool_ptr -> tx_byte_pool_created_next = next_pool;
+ }
+
+ /* Increment the number of created byte pools. */
+ _tx_byte_pool_created_count++;
+
+ /* Optional byte pool create extended processing. */
+ TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_byte_pool_delete.c b/common/src/tx_byte_pool_delete.c
new file mode 100644
index 00000000..5e63ad45
--- /dev/null
+++ b/common/src/tx_byte_pool_delete.c
@@ -0,0 +1,211 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified byte pool. All threads */
+/* suspended on the byte pool are resumed with the TX_DELETED status */
+/* code. */
+/* */
+/* It is important to note that the byte pool being deleted, or the */
+/* memory associated with it should not be in use when this function */
+/* is called. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+UINT suspended_count;
+TX_BYTE_POOL *next_pool;
+TX_BYTE_POOL *previous_pool;
+
+
+ /* Disable interrupts to remove the byte pool from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Optional byte pool delete extended processing. */
+ TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(pool_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_DELETE_INSERT
+
+ /* Clear the byte pool ID to make it invalid. */
+ pool_ptr -> tx_byte_pool_id = TX_CLEAR_ID;
+
+ /* Decrement the number of byte pools created. */
+ _tx_byte_pool_created_count--;
+
+ /* See if the byte pool is the only one on the list. */
+ if (_tx_byte_pool_created_count == TX_EMPTY)
+ {
+
+ /* Only created byte pool, just set the created list to NULL. */
+ _tx_byte_pool_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_pool = pool_ptr -> tx_byte_pool_created_next;
+ previous_pool = pool_ptr -> tx_byte_pool_created_previous;
+ next_pool -> tx_byte_pool_created_previous = previous_pool;
+ previous_pool -> tx_byte_pool_created_next = next_pool;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_byte_pool_created_ptr == pool_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_byte_pool_created_ptr = next_pool;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = pool_ptr -> tx_byte_pool_suspension_list;
+ pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+ pool_ptr -> tx_byte_pool_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the byte pool list to resume any and all threads suspended
+ on this byte pool. */
+ while (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_BYTE_POOL_DELETE_PORT_COMPLETION(pool_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_byte_pool_info_get.c b/common/src/tx_byte_pool_info_get.c
new file mode 100644
index 00000000..6797263c
--- /dev/null
+++ b/common/src/tx_byte_pool_info_get.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified byte pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to byte pool control block*/
+/* name Destination for the pool name */
+/* available_bytes Number of free bytes in byte pool */
+/* fragments Number of fragments in byte pool */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on byte pool */
+/* suspended_count Destination for suspended count */
+/* next_pool Destination for pointer to next */
+/* byte pool on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
+ ULONG *fragments, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BYTE_POOL **next_pool)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the byte pool. */
+ if (name != TX_NULL)
+ {
+
+ *name = pool_ptr -> tx_byte_pool_name;
+ }
+
+ /* Retrieve the number of available bytes in the byte pool. */
+ if (available_bytes != TX_NULL)
+ {
+
+ *available_bytes = pool_ptr -> tx_byte_pool_available;
+ }
+
+ /* Retrieve the total number of bytes in the byte pool. */
+ if (fragments != TX_NULL)
+ {
+
+ *fragments = (ULONG) pool_ptr -> tx_byte_pool_fragments;
+ }
+
+ /* Retrieve the first thread suspended on this byte pool. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = pool_ptr -> tx_byte_pool_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this byte pool. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) pool_ptr -> tx_byte_pool_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next byte pool created. */
+ if (next_pool != TX_NULL)
+ {
+
+ *next_pool = pool_ptr -> tx_byte_pool_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_byte_pool_initialize.c b/common/src/tx_byte_pool_initialize.c
new file mode 100644
index 00000000..7b1ce011
--- /dev/null
+++ b/common/src/tx_byte_pool_initialize.c
@@ -0,0 +1,147 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_byte_pool.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Locate byte pool component data in this file. */
+
+/* Define the head pointer of the created byte pool list. */
+
+TX_BYTE_POOL * _tx_byte_pool_created_ptr;
+
+
+/* Define the variable that holds the number of created byte pools. */
+
+ULONG _tx_byte_pool_created_count;
+
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of allocates. */
+
+ULONG _tx_byte_pool_performance_allocate_count;
+
+
+/* Define the total number of releases. */
+
+ULONG _tx_byte_pool_performance_release_count;
+
+
+/* Define the total number of adjacent memory fragment merges. */
+
+ULONG _tx_byte_pool_performance_merge_count;
+
+
+/* Define the total number of memory fragment splits. */
+
+ULONG _tx_byte_pool_performance_split_count;
+
+
+/* Define the total number of memory fragments searched during allocation. */
+
+ULONG _tx_byte_pool_performance_search_count;
+
+
+/* Define the total number of byte pool suspensions. */
+
+ULONG _tx_byte_pool_performance_suspension_count;
+
+
+/* Define the total number of byte pool timeouts. */
+
+ULONG _tx_byte_pool_performance_timeout_count;
+
+#endif
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the byte pool component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_byte_pool_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created byte pools list and the
+ number of byte pools created. */
+ _tx_byte_pool_created_ptr = TX_NULL;
+ _tx_byte_pool_created_count = TX_EMPTY;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize byte pool performance counters. */
+ _tx_byte_pool_performance_allocate_count = ((ULONG) 0);
+ _tx_byte_pool_performance_release_count = ((ULONG) 0);
+ _tx_byte_pool_performance_merge_count = ((ULONG) 0);
+ _tx_byte_pool_performance_split_count = ((ULONG) 0);
+ _tx_byte_pool_performance_search_count = ((ULONG) 0);
+ _tx_byte_pool_performance_suspension_count = ((ULONG) 0);
+ _tx_byte_pool_performance_timeout_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_byte_pool_performance_info_get.c b/common/src/tx_byte_pool_performance_info_get.c
new file mode 100644
index 00000000..53af8211
--- /dev/null
+++ b/common/src/tx_byte_pool_performance_info_get.c
@@ -0,0 +1,253 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_byte_pool.h"
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* byte pool. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to byte pool control block*/
+/* allocates Destination for number of */
+/* allocates on this pool */
+/* releases Destination for number of */
+/* releases on this pool */
+/* fragments_searched Destination for number of */
+/* fragments searched during */
+/* allocation */
+/* merges Destination for number of adjacent*/
+/* free fragments merged */
+/* splits Destination for number of */
+/* fragments split during */
+/* allocation */
+/* suspensions Destination for number of */
+/* suspensions on this pool */
+/* timeouts Destination for number of timeouts*/
+/* on this byte pool */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
+ ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Byte pool pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the pool ID is invalid. */
+ else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Byte pool pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of allocates on this byte pool. */
+ if (allocates != TX_NULL)
+ {
+
+ *allocates = pool_ptr -> tx_byte_pool_performance_allocate_count;
+ }
+
+ /* Retrieve the number of releases on this byte pool. */
+ if (releases != TX_NULL)
+ {
+
+ *releases = pool_ptr -> tx_byte_pool_performance_release_count;
+ }
+
+ /* Retrieve the number of fragments searched in this byte pool. */
+ if (fragments_searched != TX_NULL)
+ {
+
+ *fragments_searched = pool_ptr -> tx_byte_pool_performance_search_count;
+ }
+
+ /* Retrieve the number of fragments merged on this byte pool. */
+ if (merges != TX_NULL)
+ {
+
+ *merges = pool_ptr -> tx_byte_pool_performance_merge_count;
+ }
+
+ /* Retrieve the number of fragment splits on this byte pool. */
+ if (splits != TX_NULL)
+ {
+
+ *splits = pool_ptr -> tx_byte_pool_performance_split_count;
+ }
+
+ /* Retrieve the number of suspensions on this byte pool. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = pool_ptr -> tx_byte_pool_performance_suspension_count;
+ }
+
+ /* Retrieve the number of timeouts on this byte pool. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = pool_ptr -> tx_byte_pool_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ status = TX_SUCCESS;
+ }
+
+ /* Return completion status. */
+ return(status);
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (pool_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (allocates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (releases != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (fragments_searched != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (merges != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (splits != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_byte_pool_performance_system_info_get.c b/common/src/tx_byte_pool_performance_system_info_get.c
new file mode 100644
index 00000000..02d0cc5b
--- /dev/null
+++ b/common/src/tx_byte_pool_performance_system_info_get.c
@@ -0,0 +1,221 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_byte_pool.h"
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves byte pool performance information. */
+/* */
+/* INPUT */
+/* */
+/* allocates Destination for total number of */
+/* allocates */
+/* releases Destination for total number of */
+/* releases */
+/* fragments_searched Destination for total number of */
+/* fragments searched during */
+/* allocation */
+/* merges Destination for total number of */
+/* adjacent free fragments merged */
+/* splits Destination for total number of */
+/* fragments split during */
+/* allocation */
+/* suspensions Destination for total number of */
+/* suspensions */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_performance_system_info_get(ULONG *allocates, ULONG *releases,
+ ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of byte pool allocates. */
+ if (allocates != TX_NULL)
+ {
+
+ *allocates = _tx_byte_pool_performance_allocate_count;
+ }
+
+ /* Retrieve the total number of byte pool releases. */
+ if (releases != TX_NULL)
+ {
+
+ *releases = _tx_byte_pool_performance_release_count;
+ }
+
+ /* Retrieve the total number of byte pool fragments searched. */
+ if (fragments_searched != TX_NULL)
+ {
+
+ *fragments_searched = _tx_byte_pool_performance_search_count;
+ }
+
+ /* Retrieve the total number of byte pool fragments merged. */
+ if (merges != TX_NULL)
+ {
+
+ *merges = _tx_byte_pool_performance_merge_count;
+ }
+
+ /* Retrieve the total number of byte pool fragment splits. */
+ if (splits != TX_NULL)
+ {
+
+ *splits = _tx_byte_pool_performance_split_count;
+ }
+
+ /* Retrieve the total number of byte pool suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_byte_pool_performance_suspension_count;
+ }
+
+ /* Retrieve the total number of byte pool timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_byte_pool_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (allocates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (releases != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (fragments_searched != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (merges != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (splits != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_byte_pool_prioritize.c b/common/src/tx_byte_pool_prioritize.c
new file mode 100644
index 00000000..b39d6214
--- /dev/null
+++ b/common/src/tx_byte_pool_prioritize.c
@@ -0,0 +1,249 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the highest priority suspended thread at the */
+/* front of the suspension list. All other threads remain in the same */
+/* FIFO suspension order. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *priority_thread_ptr;
+TX_THREAD *head_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT list_changed;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_byte_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_POOL_PRIORITIZE_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+
+ /* Determine if there are fewer than 2 suspended threads. */
+ if (suspended_count < ((UINT) 2))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if there how many threads are suspended on this byte memory pool. */
+ else if (suspended_count == ((UINT) 2))
+ {
+
+ /* Pickup the head pointer and the next pointer. */
+ head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
+ next_thread = head_ptr -> tx_thread_suspended_next;
+
+ /* Determine if the next suspended thread has a higher priority. */
+ if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
+ {
+
+ /* Yes, move the list head to the next thread. */
+ pool_ptr -> tx_byte_pool_suspension_list = next_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the list changed flag to false. */
+ list_changed = TX_FALSE;
+
+ /* Search through the list to find the highest priority thread. */
+ do
+ {
+
+ /* Is the current thread higher priority? */
+ if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, remember that this thread is the highest priority. */
+ priority_thread_ptr = thread_ptr;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Determine if any changes to the list have occurred while
+ interrupts were enabled. */
+
+ /* Is the list head the same? */
+ if (head_ptr != pool_ptr -> tx_byte_pool_suspension_list)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ else
+ {
+
+ /* Is the suspended count the same? */
+ if (suspended_count != pool_ptr -> tx_byte_pool_suspended_count)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ }
+
+ /* Determine if the list has changed. */
+ if (list_changed == TX_FALSE)
+ {
+
+ /* Move the thread pointer to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Reset the list changed flag. */
+ list_changed = TX_FALSE;
+ }
+
+ } while (thread_ptr != head_ptr);
+
+ /* Release preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Now determine if the highest priority thread is at the front
+ of the list. */
+ if (priority_thread_ptr != head_ptr)
+ {
+
+ /* No, we need to move the highest priority suspended thread to the
+ front of the list. */
+
+ /* First, remove the highest priority thread by updating the
+ adjacent suspended threads. */
+ next_thread = priority_thread_ptr -> tx_thread_suspended_next;
+ previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Now, link the highest priority thread at the front of the list. */
+ previous_thread = head_ptr -> tx_thread_suspended_previous;
+ priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
+ priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
+ head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
+
+ /* Move the list head pointer to the highest priority suspended thread. */
+ pool_ptr -> tx_byte_pool_suspension_list = priority_thread_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_byte_pool_search.c b/common/src/tx_byte_pool_search.c
new file mode 100644
index 00000000..3455d5f1
--- /dev/null
+++ b/common/src/tx_byte_pool_search.c
@@ -0,0 +1,350 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_search PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function searches a byte pool for a memory block to satisfy */
+/* the requested number of bytes. Merging of adjacent free blocks */
+/* takes place during the search and a split of the block that */
+/* satisfies the request may occur before this function returns. */
+/* */
+/* It is assumed that this function is called with interrupts enabled */
+/* and with the tx_pool_owner field set to the thread performing the */
+/* search. Also note that the search can occur during allocation and */
+/* release of a memory block. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* memory_size Number of bytes required */
+/* */
+/* OUTPUT */
+/* */
+/* UCHAR * Pointer to the allocated memory, */
+/* if successful. Otherwise, a */
+/* NULL is returned */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_byte_allocate Allocate bytes of memory */
+/* _tx_byte_release Release bytes of memory */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UCHAR *current_ptr;
+UCHAR *next_ptr;
+UCHAR **this_block_link_ptr;
+UCHAR **next_block_link_ptr;
+ULONG available_bytes;
+UINT examine_blocks;
+UINT first_free_block_found = TX_FALSE;
+TX_THREAD *thread_ptr;
+ALIGN_TYPE *free_ptr;
+UCHAR *work_ptr;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* First, determine if there are enough bytes in the pool. */
+ if (memory_size >= pool_ptr -> tx_byte_pool_available)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Not enough memory, return a NULL pointer. */
+ current_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup ownership of the byte pool. */
+ pool_ptr -> tx_byte_pool_owner = thread_ptr;
+
+ /* Walk through the memory pool in search for a large enough block. */
+ current_ptr = pool_ptr -> tx_byte_pool_search;
+ examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1);
+ available_bytes = ((ULONG) 0);
+ do
+ {
+
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total fragment search counter. */
+ _tx_byte_pool_performance_search_count++;
+
+ /* Increment the number of fragments searched on this pool. */
+ pool_ptr -> tx_byte_pool_performance_search_count++;
+#endif
+
+ /* Check to see if this block is free. */
+ work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
+ if ((*free_ptr) == TX_BYTE_BLOCK_FREE)
+ {
+
+ /* Determine if this is the first free block. */
+ if (first_free_block_found == TX_FALSE)
+ {
+
+ /* This is the first free block. */
+ pool_ptr->tx_byte_pool_search = current_ptr;
+
+ /* Set the flag to indicate we have found the first free
+ block. */
+ first_free_block_found = TX_TRUE;
+ }
+
+ /* Block is free, see if it is large enough. */
+
+ /* Pickup the next block's pointer. */
+ this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
+ next_ptr = *this_block_link_ptr;
+
+ /* Calculate the number of bytes available in this block. */
+ available_bytes = TX_UCHAR_POINTER_DIF(next_ptr, current_ptr);
+ available_bytes = available_bytes - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)));
+
+ /* If this is large enough, we are done because our first-fit algorithm
+ has been satisfied! */
+ if (available_bytes >= memory_size)
+ {
+ /* Get out of the search loop! */
+ break;
+ }
+ else
+ {
+
+ /* Clear the available bytes variable. */
+ available_bytes = ((ULONG) 0);
+
+ /* Not enough memory, check to see if the neighbor is
+ free and can be merged. */
+ work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
+ if ((*free_ptr) == TX_BYTE_BLOCK_FREE)
+ {
+
+ /* Yes, neighbor block can be merged! This is quickly accomplished
+ by updating the current block with the next blocks pointer. */
+ next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
+ *this_block_link_ptr = *next_block_link_ptr;
+
+ /* Reduce the fragment total. We don't need to increase the bytes
+ available because all free headers are also included in the available
+ count. */
+ pool_ptr -> tx_byte_pool_fragments--;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total merge counter. */
+ _tx_byte_pool_performance_merge_count++;
+
+ /* Increment the number of blocks merged on this pool. */
+ pool_ptr -> tx_byte_pool_performance_merge_count++;
+#endif
+
+ /* See if the search pointer is affected. */
+ if (pool_ptr -> tx_byte_pool_search == next_ptr)
+ {
+
+ /* Yes, update the search pointer. */
+ pool_ptr -> tx_byte_pool_search = current_ptr;
+ }
+ }
+ else
+ {
+
+ /* Neighbor is not free so we can skip over it! */
+ next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
+ current_ptr = *next_block_link_ptr;
+
+ /* Decrement the examined block count to account for this one. */
+ if (examine_blocks != ((UINT) 0))
+ {
+
+ examine_blocks--;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total fragment search counter. */
+ _tx_byte_pool_performance_search_count++;
+
+ /* Increment the number of fragments searched on this pool. */
+ pool_ptr -> tx_byte_pool_performance_search_count++;
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* Block is not free, move to next block. */
+ this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
+ current_ptr = *this_block_link_ptr;
+ }
+
+ /* Another block has been searched... decrement counter. */
+ if (examine_blocks != ((UINT) 0))
+ {
+
+ examine_blocks--;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if anything has changed in terms of pool ownership. */
+ if (pool_ptr -> tx_byte_pool_owner != thread_ptr)
+ {
+
+ /* Pool changed ownership in the brief period interrupts were
+ enabled. Reset the search. */
+ current_ptr = pool_ptr -> tx_byte_pool_search;
+ examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1);
+
+ /* Setup our ownership again. */
+ pool_ptr -> tx_byte_pool_owner = thread_ptr;
+ }
+ } while(examine_blocks != ((UINT) 0));
+
+ /* Determine if a block was found. If so, determine if it needs to be
+ split. */
+ if (available_bytes != ((ULONG) 0))
+ {
+
+ /* Determine if we need to split this block. */
+ if ((available_bytes - memory_size) >= ((ULONG) TX_BYTE_BLOCK_MIN))
+ {
+
+ /* Split the block. */
+ next_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (memory_size + ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
+
+ /* Setup the new free block. */
+ next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
+ this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
+ *next_block_link_ptr = *this_block_link_ptr;
+ work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
+ *free_ptr = TX_BYTE_BLOCK_FREE;
+
+ /* Increase the total fragment counter. */
+ pool_ptr -> tx_byte_pool_fragments++;
+
+ /* Update the current pointer to point at the newly created block. */
+ *this_block_link_ptr = next_ptr;
+
+ /* Set available equal to memory size for subsequent calculation. */
+ available_bytes = memory_size;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total split counter. */
+ _tx_byte_pool_performance_split_count++;
+
+ /* Increment the number of blocks split on this pool. */
+ pool_ptr -> tx_byte_pool_performance_split_count++;
+#endif
+ }
+
+ /* In any case, mark the current block as allocated. */
+ work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *)));
+ this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ *this_block_link_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
+
+ /* Reduce the number of available bytes in the pool. */
+ pool_ptr -> tx_byte_pool_available = (pool_ptr -> tx_byte_pool_available - available_bytes) - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)));
+
+ /* Determine if the search pointer needs to be updated. This is only done
+ if the search pointer matches the block to be returned. */
+ if (current_ptr == pool_ptr -> tx_byte_pool_search)
+ {
+
+ /* Yes, update the search pointer to the next block. */
+ this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
+ pool_ptr -> tx_byte_pool_search = *this_block_link_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Adjust the pointer for the application. */
+ current_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Set current pointer to NULL to indicate nothing was found. */
+ current_ptr = TX_NULL;
+ }
+ }
+
+ /* Return the search pointer. */
+ return(current_ptr);
+}
+
diff --git a/common/src/tx_byte_release.c b/common/src/tx_byte_release.c
new file mode 100644
index 00000000..404f1eb0
--- /dev/null
+++ b/common/src/tx_byte_release.c
@@ -0,0 +1,376 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_release PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns previously allocated memory to its */
+/* associated memory byte pool. */
+/* */
+/* INPUT */
+/* */
+/* memory_ptr Pointer to allocated memory */
+/* */
+/* OUTPUT */
+/* */
+/* [TX_PTR_ERROR | TX_SUCCESS] Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_byte_pool_search Search the byte pool for memory */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_byte_release(VOID *memory_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+TX_BYTE_POOL *pool_ptr;
+TX_THREAD *thread_ptr;
+UCHAR *work_ptr;
+UCHAR *temp_ptr;
+UCHAR *next_block_ptr;
+TX_THREAD *susp_thread_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+ULONG memory_size;
+ALIGN_TYPE *free_ptr;
+TX_BYTE_POOL **byte_pool_ptr;
+UCHAR **block_link_ptr;
+UCHAR **suspend_info_ptr;
+
+
+ /* Default to successful status. */
+ status = TX_SUCCESS;
+
+ /* Set the pool pointer to NULL. */
+ pool_ptr = TX_NULL;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Determine if the memory pointer is valid. */
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(memory_ptr);
+ if (work_ptr != TX_NULL)
+ {
+
+ /* Back off the memory pointer to pickup its header. */
+ work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))));
+
+ /* There is a pointer, pickup the pool pointer address. */
+ temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
+ if ((*free_ptr) != TX_BYTE_BLOCK_FREE)
+ {
+
+ /* Pickup the pool pointer. */
+ temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
+ byte_pool_ptr = TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(temp_ptr);
+ pool_ptr = *byte_pool_ptr;
+
+ /* See if we have a valid pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Return pointer error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* See if we have a valid pool. */
+ if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Return pointer error. */
+ status = TX_PTR_ERROR;
+
+ /* Reset the pool pointer is NULL. */
+ pool_ptr = TX_NULL;
+ }
+ }
+ }
+ else
+ {
+
+ /* Return pointer error. */
+ status = TX_PTR_ERROR;
+ }
+ }
+ else
+ {
+
+ /* Return pointer error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the pointer is valid. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* At this point, we know that the pointer is valid. */
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Indicate that this thread is the current owner. */
+ pool_ptr -> tx_byte_pool_owner = thread_ptr;
+
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total release counter. */
+ _tx_byte_pool_performance_release_count++;
+
+ /* Increment the number of releases on this pool. */
+ pool_ptr -> tx_byte_pool_performance_release_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(memory_ptr), pool_ptr -> tx_byte_pool_suspended_count, pool_ptr -> tx_byte_pool_available, TX_TRACE_BYTE_POOL_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_BYTE_RELEASE_INSERT
+
+ /* Release the memory. */
+ temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
+ *free_ptr = TX_BYTE_BLOCK_FREE;
+
+ /* Update the number of available bytes in the pool. */
+ block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ next_block_ptr = *block_link_ptr;
+ pool_ptr -> tx_byte_pool_available =
+ pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr);
+
+ /* Determine if the free block is prior to current search pointer. */
+ if (work_ptr < (pool_ptr -> tx_byte_pool_search))
+ {
+
+ /* Yes, update the search pointer to the released block. */
+ pool_ptr -> tx_byte_pool_search = work_ptr;
+ }
+
+ /* Determine if there are threads suspended on this byte pool. */
+ if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Now examine the suspension list to find threads waiting for
+ memory. Maybe it is now available! */
+ while (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Pickup the first suspended thread pointer. */
+ susp_thread_ptr = pool_ptr -> tx_byte_pool_suspension_list;
+
+ /* Pickup the size of the memory the thread is requesting. */
+ memory_size = susp_thread_ptr -> tx_thread_suspend_info;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* See if the request can be satisfied. */
+ work_ptr = _tx_byte_pool_search(pool_ptr, memory_size);
+
+ /* Optional processing extension. */
+ TX_BYTE_RELEASE_EXTENSION
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Indicate that this thread is the current owner. */
+ pool_ptr -> tx_byte_pool_owner = thread_ptr;
+
+ /* If there is not enough memory, break this loop! */
+ if (work_ptr == TX_NULL)
+ {
+
+ /* Break out of the loop. */
+ break;
+ }
+
+ /* Check to make sure the thread is still suspended. */
+ if (susp_thread_ptr == pool_ptr -> tx_byte_pool_suspension_list)
+ {
+
+ /* Also, makes sure the memory size is the same. */
+ if (susp_thread_ptr -> tx_thread_suspend_info == memory_size)
+ {
+
+ /* Remove the suspended thread from the list. */
+
+ /* Decrement the number of threads suspended. */
+ pool_ptr -> tx_byte_pool_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = susp_thread_ptr -> tx_thread_suspended_next;
+ pool_ptr -> tx_byte_pool_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = susp_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Prepare for resumption of the thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ susp_thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Return this block pointer to the suspended thread waiting for
+ a block. */
+ suspend_info_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(susp_thread_ptr -> tx_thread_additional_suspend_info);
+ *suspend_info_ptr = work_ptr;
+
+ /* Clear the memory pointer to indicate that it was given to the suspended thread. */
+ work_ptr = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ susp_thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(susp_thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(susp_thread_ptr);
+#endif
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+ }
+ }
+
+ /* Determine if the memory was given to the suspended thread. */
+ if (work_ptr != TX_NULL)
+ {
+
+ /* No, it wasn't given to the suspended thread. */
+
+ /* Put the memory back on the available list since this thread is no longer
+ suspended. */
+ work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
+ temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
+ free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
+ *free_ptr = TX_BYTE_BLOCK_FREE;
+
+ /* Update the number of available bytes in the pool. */
+ block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ next_block_ptr = *block_link_ptr;
+ pool_ptr -> tx_byte_pool_available =
+ pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr);
+
+ /* Determine if the current pointer is before the search pointer. */
+ if (work_ptr < (pool_ptr -> tx_byte_pool_search))
+ {
+
+ /* Yes, update the search pointer. */
+ pool_ptr -> tx_byte_pool_search = work_ptr;
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+ else
+ {
+
+ /* No, threads suspended, restore interrupts. */
+ TX_RESTORE
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_event_flags_cleanup.c b/common/src/tx_event_flags_cleanup.c
new file mode 100644
index 00000000..1b58df24
--- /dev/null
+++ b/common/src/tx_event_flags_cleanup.c
@@ -0,0 +1,237 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes event flags timeout and thread terminate */
+/* actions that require the event flags data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_EVENT_FLAGS_GROUP *group_ptr;
+UINT suspended_count;
+TX_THREAD *suspension_head;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the event flags group. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_event_flags_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to event flags control block. */
+ group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for a NULL event flags control block pointer. */
+ if (group_ptr != TX_NULL)
+ {
+
+ /* Is the group pointer ID valid? */
+ if (group_ptr -> tx_event_flags_group_id == TX_EVENT_FLAGS_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to event flags control block. */
+ group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Yes, we still have thread suspension! */
+
+ /* Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Pickup the suspended count. */
+ suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
+
+ /* Pickup the suspension head. */
+ suspension_head = group_ptr -> tx_event_flags_group_suspension_list;
+
+ /* Determine if the cleanup is being done while a set operation was interrupted. If the
+ suspended count is non-zero and the suspension head is NULL, the list is being processed
+ and cannot be touched from here. The suspension list removal will instead take place
+ inside the event flag set code. */
+ if (suspension_head != TX_NULL)
+ {
+
+ /* Remove the suspended thread from the list. */
+
+ /* Decrement the local suspension count. */
+ suspended_count--;
+
+ /* Store the updated suspended count. */
+ group_ptr -> tx_event_flags_group_suspended_count = suspended_count;
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (suspension_head == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ group_ptr -> tx_event_flags_group_suspension_list = next_thread;
+ }
+ }
+ }
+ else
+ {
+
+ /* In this case, the search pointer in an interrupted event flag set must be reset. */
+ group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
+ {
+
+ /* Timeout condition and the thread still suspended on the event flags group.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_event_flags_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this event flags group. */
+ group_ptr -> tx_event_flags_group____performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ thread_ptr -> tx_thread_suspend_status = TX_NO_EVENTS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! Check for preemption even though we are executing
+ from the system timer thread right now which normally executes at the
+ highest priority. */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_event_flags_create.c b/common/src/tx_event_flags_create.c
new file mode 100644
index 00000000..aa0e7269
--- /dev/null
+++ b/common/src/tx_event_flags_create.c
@@ -0,0 +1,141 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a group of 32 event flags. All the flags are */
+/* initially in a cleared state. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to event flags group */
+/* control block */
+/* name_ptr Pointer to event flags name */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_EVENT_FLAGS_GROUP *next_group;
+TX_EVENT_FLAGS_GROUP *previous_group;
+
+
+ /* Initialize event flags control block to all zeros. */
+ TX_MEMSET(group_ptr, 0, (sizeof(TX_EVENT_FLAGS_GROUP)));
+
+ /* Setup the basic event flags group fields. */
+ group_ptr -> tx_event_flags_group_name = name_ptr;
+
+ /* Disable interrupts to put the event flags group on the created list. */
+ TX_DISABLE
+
+ /* Setup the event flags ID to make it valid. */
+ group_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID;
+
+ /* Place the group on the list of created event flag groups. First,
+ check for an empty list. */
+ if (_tx_event_flags_created_count == TX_EMPTY)
+ {
+
+ /* The created event flags list is empty. Add event flag group to empty list. */
+ _tx_event_flags_created_ptr = group_ptr;
+ group_ptr -> tx_event_flags_group_created_next = group_ptr;
+ group_ptr -> tx_event_flags_group_created_previous = group_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_group = _tx_event_flags_created_ptr;
+ previous_group = next_group -> tx_event_flags_group_created_previous;
+
+ /* Place the new event flag group in the list. */
+ next_group -> tx_event_flags_group_created_previous = group_ptr;
+ previous_group -> tx_event_flags_group_created_next = group_ptr;
+
+ /* Setup this group's created links. */
+ group_ptr -> tx_event_flags_group_created_previous = previous_group;
+ group_ptr -> tx_event_flags_group_created_next = next_group;
+ }
+
+ /* Increment the number of created event flag groups. */
+ _tx_event_flags_created_count++;
+
+ /* Optional event flag group create extended processing. */
+ TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, group_ptr, name_ptr, 0, 0)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_CREATE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_group), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_event_flags_delete.c b/common/src/tx_event_flags_delete.c
new file mode 100644
index 00000000..d495c938
--- /dev/null
+++ b/common/src/tx_event_flags_delete.c
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified event flag group. All threads */
+/* suspended on the group are resumed with the TX_DELETED status */
+/* code. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+UINT suspended_count;
+TX_EVENT_FLAGS_GROUP *next_group;
+TX_EVENT_FLAGS_GROUP *previous_group;
+
+
+ /* Disable interrupts to remove the group from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_DELETE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Optional event flags group delete extended processing. */
+ TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(group_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_DELETE_INSERT
+
+ /* Clear the event flag group ID to make it invalid. */
+ group_ptr -> tx_event_flags_group_id = TX_CLEAR_ID;
+
+ /* Decrement the number of created event flag groups. */
+ _tx_event_flags_created_count--;
+
+ /* See if this group is the only one on the list. */
+ if (_tx_event_flags_created_count == TX_EMPTY)
+ {
+
+ /* Only created event flag group, just set the created list to NULL. */
+ _tx_event_flags_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_group = group_ptr -> tx_event_flags_group_created_next;
+ previous_group = group_ptr -> tx_event_flags_group_created_previous;
+ next_group -> tx_event_flags_group_created_previous = previous_group;
+ previous_group -> tx_event_flags_group_created_next = next_group;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_event_flags_created_ptr == group_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_event_flags_created_ptr = next_group;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = group_ptr -> tx_event_flags_group_suspension_list;
+ group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
+ suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
+ group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the event flag suspension list to resume any and all threads
+ suspended on this group. */
+ while (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Decrement the number of suspended threads. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(group_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_event_flags_get.c b/common/src/tx_event_flags_get.c
new file mode 100644
index 00000000..ed3bba20
--- /dev/null
+++ b/common/src/tx_event_flags_get.c
@@ -0,0 +1,401 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets the specified event flags from the group, */
+/* according to the get option. The get option also specifies whether */
+/* or not the retrieved flags are cleared. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* requested_event_flags Event flags requested */
+/* get_option Specifies and/or and clear options*/
+/* actual_flags_ptr Pointer to place the actual flags */
+/* the service retrieved */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Suspend thread service */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
+ UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+UINT and_request;
+UINT clear_request;
+ULONG current_flags;
+ULONG flags_satisfied;
+#ifndef TX_NOT_INTERRUPTABLE
+ULONG delayed_clear_flags;
+#endif
+UINT suspended_count;
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+#ifndef TX_NOT_INTERRUPTABLE
+UINT interrupted_set_request;
+#endif
+
+
+ /* Disable interrupts to examine the event flags group. */
+ TX_DISABLE
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total event flags get counter. */
+ _tx_event_flags_performance_get_count++;
+
+ /* Increment the number of event flags gets on this semaphore. */
+ group_ptr -> tx_event_flags_group__performance_get_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_GET, group_ptr, requested_flags, group_ptr -> tx_event_flags_group_current, get_option, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_GET_INSERT
+
+ /* Pickup current flags. */
+ current_flags = group_ptr -> tx_event_flags_group_current;
+
+ /* Apply the event flag option mask. */
+ and_request = (get_option & TX_AND);
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Check for AND condition. All flags must be present to satisfy request. */
+ if (and_request == TX_AND)
+ {
+
+ /* AND request is present. */
+
+ /* Calculate the flags present. */
+ flags_satisfied = (current_flags & requested_flags);
+
+ /* Determine if they satisfy the AND request. */
+ if (flags_satisfied != requested_flags)
+ {
+
+ /* No, not all the requested flags are present. Clear the flags present variable. */
+ flags_satisfied = ((ULONG) 0);
+ }
+ }
+ else
+ {
+
+ /* OR request is present. Simply or the requested flags and the current flags. */
+ flags_satisfied = (current_flags & requested_flags);
+ }
+
+ /* Determine if the request is satisfied. */
+ if (flags_satisfied != ((ULONG) 0))
+ {
+
+ /* Return the actual event flags that satisfied the request. */
+ *actual_flags_ptr = current_flags;
+
+ /* Pickup the clear bit. */
+ clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
+
+ /* Determine whether or not clearing needs to take place. */
+ if (clear_request == TX_TRUE)
+ {
+
+ /* Yes, clear the flags that satisfied this request. */
+ group_ptr -> tx_event_flags_group_current =
+ group_ptr -> tx_event_flags_group_current & (~requested_flags);
+ }
+
+ /* Return success. */
+ status = TX_SUCCESS;
+ }
+
+#else
+
+ /* Pickup delayed clear flags. */
+ delayed_clear_flags = group_ptr -> tx_event_flags_group_delayed_clear;
+
+ /* Determine if there are any delayed clear operations pending. */
+ if (delayed_clear_flags != ((ULONG) 0))
+ {
+
+ /* Yes, apply them to the current flags. */
+ current_flags = current_flags & (~delayed_clear_flags);
+ }
+
+ /* Check for AND condition. All flags must be present to satisfy request. */
+ if (and_request == TX_AND)
+ {
+
+ /* AND request is present. */
+
+ /* Calculate the flags present. */
+ flags_satisfied = (current_flags & requested_flags);
+
+ /* Determine if they satisfy the AND request. */
+ if (flags_satisfied != requested_flags)
+ {
+
+ /* No, not all the requested flags are present. Clear the flags present variable. */
+ flags_satisfied = ((ULONG) 0);
+ }
+ }
+ else
+ {
+
+ /* OR request is present. Simply AND together the requested flags and the current flags
+ to see if any are present. */
+ flags_satisfied = (current_flags & requested_flags);
+ }
+
+ /* Determine if the request is satisfied. */
+ if (flags_satisfied != ((ULONG) 0))
+ {
+
+ /* Yes, this request can be handled immediately. */
+
+ /* Return the actual event flags that satisfied the request. */
+ *actual_flags_ptr = current_flags;
+
+ /* Pickup the clear bit. */
+ clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
+
+ /* Determine whether or not clearing needs to take place. */
+ if (clear_request == TX_TRUE)
+ {
+
+ /* Set interrupted set request flag to false. */
+ interrupted_set_request = TX_FALSE;
+
+ /* Determine if the suspension list is being processed by an interrupted
+ set request. */
+ if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL)
+ {
+
+ /* Set the interrupted set request flag. */
+ interrupted_set_request = TX_TRUE;
+ }
+ }
+
+ /* Was a set request interrupted? */
+ if (interrupted_set_request == TX_TRUE)
+ {
+
+ /* A previous set operation is was interrupted, we need to defer the
+ event clearing until the set operation is complete. */
+
+ /* Remember the events to clear. */
+ group_ptr -> tx_event_flags_group_delayed_clear =
+ group_ptr -> tx_event_flags_group_delayed_clear | requested_flags;
+ }
+ else
+ {
+
+ /* Yes, clear the flags that satisfied this request. */
+ group_ptr -> tx_event_flags_group_current =
+ group_ptr -> tx_event_flags_group_current & ~requested_flags;
+ }
+ }
+
+ /* Set status to success. */
+ status = TX_SUCCESS;
+ }
+
+#endif
+ else
+ {
+
+ /* Determine if the request specifies suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */
+ status = TX_NO_EVENTS;
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total event flags suspensions counter. */
+ _tx_event_flags_performance_suspension_count++;
+
+ /* Increment the number of event flags suspensions on this semaphore. */
+ group_ptr -> tx_event_flags_group___performance_suspension_count++;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
+
+ /* Remember which event flags we are looking for. */
+ thread_ptr -> tx_thread_suspend_info = requested_flags;
+
+ /* Save the get option as well. */
+ thread_ptr -> tx_thread_suspend_option = get_option;
+
+ /* Save the destination for the current events. */
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) actual_flags_ptr;
+
+ /* Setup cleanup information, i.e. this event flags group control
+ block. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) group_ptr;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Pickup the suspended count. */
+ suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
+
+ /* Setup suspension list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ group_ptr -> tx_event_flags_group_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = group_ptr -> tx_event_flags_group_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Increment the number of threads suspended. */
+ group_ptr -> tx_event_flags_group_suspended_count++;
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_EVENT_FLAG;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+#endif
+ }
+ }
+ else
+ {
+
+ /* Immediate return, return error completion. */
+ status = TX_NO_EVENTS;
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_event_flags_info_get.c b/common/src/tx_event_flags_info_get.c
new file mode 100644
index 00000000..608be7df
--- /dev/null
+++ b/common/src/tx_event_flags_info_get.c
@@ -0,0 +1,143 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified event flag */
+/* group. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to event flag group */
+/* name Destination for the event flag */
+/* group name */
+/* current_flags Current event flags */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on event flags */
+/* suspended_count Destination for suspended count */
+/* next_group Destination for pointer to next */
+/* event flag group on the created */
+/* list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_EVENT_FLAGS_GROUP **next_group)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the event flag group. */
+ if (name != TX_NULL)
+ {
+
+ *name = group_ptr -> tx_event_flags_group_name;
+ }
+
+ /* Retrieve the current event flags in the event flag group. */
+ if (current_flags != TX_NULL)
+ {
+
+ /* Pickup the current flags and apply delayed clearing. */
+ *current_flags = group_ptr -> tx_event_flags_group_current &
+ ~group_ptr -> tx_event_flags_group_delayed_clear;
+ }
+
+ /* Retrieve the first thread suspended on this event flag group. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = group_ptr -> tx_event_flags_group_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this event flag group. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) group_ptr -> tx_event_flags_group_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next event flag group created. */
+ if (next_group != TX_NULL)
+ {
+
+ *next_group = group_ptr -> tx_event_flags_group_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_event_flags_initialize.c b/common/src/tx_event_flags_initialize.c
new file mode 100644
index 00000000..99800fe1
--- /dev/null
+++ b/common/src/tx_event_flags_initialize.c
@@ -0,0 +1,130 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Locate event flags component data in this file. */
+/* Define the head pointer of the created event flags list. */
+
+TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr;
+
+
+/* Define the variable that holds the number of created event flag groups. */
+
+ULONG _tx_event_flags_created_count;
+
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of event flag sets. */
+
+ULONG _tx_event_flags_performance_set_count;
+
+
+/* Define the total number of event flag gets. */
+
+ULONG _tx_event_flags_performance_get_count;
+
+
+/* Define the total number of event flag suspensions. */
+
+ULONG _tx_event_flags_performance_suspension_count;
+
+
+/* Define the total number of event flag timeouts. */
+
+ULONG _tx_event_flags_performance_timeout_count;
+
+
+#endif
+#endif
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the event flags component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_event_flags_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created event flags list and the
+ number of event flags created. */
+ _tx_event_flags_created_ptr = TX_NULL;
+ _tx_event_flags_created_count = TX_EMPTY;
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize event flags performance counters. */
+ _tx_event_flags_performance_set_count = ((ULONG) 0);
+ _tx_event_flags_performance_get_count = ((ULONG) 0);
+ _tx_event_flags_performance_suspension_count = ((ULONG) 0);
+ _tx_event_flags_performance_timeout_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_event_flags_performance_info_get.c b/common/src/tx_event_flags_performance_info_get.c
new file mode 100644
index 00000000..5607469d
--- /dev/null
+++ b/common/src/tx_event_flags_performance_info_get.c
@@ -0,0 +1,202 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* event flag group. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to event flag group */
+/* sets Destination for the number of */
+/* event flag sets on this group */
+/* gets Destination for the number of */
+/* event flag gets on this group */
+/* suspensions Destination for the number of */
+/* event flag suspensions on this */
+/* group */
+/* timeouts Destination for number of timeouts*/
+/* on this event flag group */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the event group ID is invalid. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of set operations on this event flag group. */
+ if (sets != TX_NULL)
+ {
+
+ *sets = group_ptr -> tx_event_flags_group_performance_set_count;
+ }
+
+ /* Retrieve the number of get operations on this event flag group. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = group_ptr -> tx_event_flags_group__performance_get_count;
+ }
+
+ /* Retrieve the number of thread suspensions on this event flag group. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = group_ptr -> tx_event_flags_group___performance_suspension_count;
+ }
+
+ /* Retrieve the number of thread timeouts on this event flag group. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = group_ptr -> tx_event_flags_group____performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (group_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (sets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_event_flags_performance_system_info_get.c b/common/src/tx_event_flags_performance_system_info_get.c
new file mode 100644
index 00000000..b421dd77
--- /dev/null
+++ b/common/src/tx_event_flags_performance_system_info_get.c
@@ -0,0 +1,174 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves system event flag performance information. */
+/* */
+/* INPUT */
+/* */
+/* sets Destination for total number of */
+/* event flag sets */
+/* gets Destination for total number of */
+/* event flag gets */
+/* suspensions Destination for total number of */
+/* event flag suspensions */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_performance_system_info_get(ULONG *sets, ULONG *gets, ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of event flag set operations. */
+ if (sets != TX_NULL)
+ {
+
+ *sets = _tx_event_flags_performance_set_count;
+ }
+
+ /* Retrieve the total number of event flag get operations. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = _tx_event_flags_performance_get_count;
+ }
+
+ /* Retrieve the total number of event flag thread suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_event_flags_performance_suspension_count;
+ }
+
+ /* Retrieve the total number of event flag thread timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_event_flags_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (sets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_event_flags_set.c b/common/src/tx_event_flags_set.c
new file mode 100644
index 00000000..aebe7d19
--- /dev/null
+++ b/common/src/tx_event_flags_set.c
@@ -0,0 +1,620 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_set PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the specified flags in the event group based on */
+/* the set option specified. All threads suspended on the group whose */
+/* get request can now be satisfied are resumed. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* flags_to_set Event flags to set */
+/* set_option Specified either AND or OR */
+/* operation on the event flags */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Always returns success */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread_ptr;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+TX_THREAD *satisfied_list;
+TX_THREAD *last_satisfied;
+TX_THREAD *suspended_list;
+UINT suspended_count;
+ULONG current_event_flags;
+ULONG requested_flags;
+ULONG flags_satisfied;
+ULONG *suspend_info_ptr;
+UINT and_request;
+UINT get_option;
+UINT clear_request;
+UINT preempt_check;
+#ifndef TX_NOT_INTERRUPTABLE
+UINT interrupted_set_request;
+#endif
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*events_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *notify_group_ptr);
+#endif
+
+
+ /* Disable interrupts to remove the semaphore from the created list. */
+ TX_DISABLE
+
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total event flags set counter. */
+ _tx_event_flags_performance_set_count++;
+
+ /* Increment the number of event flags sets on this semaphore. */
+ group_ptr -> tx_event_flags_group_performance_set_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option, group_ptr -> tx_event_flags_group_suspended_count, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_EVENT_FLAGS_SET_INSERT
+
+ /* Determine how to set this group's event flags. */
+ if ((set_option & TX_EVENT_FLAGS_AND_MASK) == TX_AND)
+ {
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Set interrupted set request flag to false. */
+ interrupted_set_request = TX_FALSE;
+
+ /* Determine if the suspension list is being processed by an interrupted
+ set request. */
+ if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL)
+ {
+
+ /* Set the interrupted set request flag. */
+ interrupted_set_request = TX_TRUE;
+ }
+ }
+
+ /* Was a set request interrupted? */
+ if (interrupted_set_request == TX_TRUE)
+ {
+
+ /* A previous set operation was interrupted, we need to defer the
+ event clearing until the set operation is complete. */
+
+ /* Remember the events to clear. */
+ group_ptr -> tx_event_flags_group_delayed_clear =
+ group_ptr -> tx_event_flags_group_delayed_clear | ~flags_to_set;
+ }
+ else
+ {
+#endif
+
+ /* Previous set operation was not interrupted, simply clear the
+ specified flags by "ANDing" the flags into the current events
+ of the group. */
+ group_ptr -> tx_event_flags_group_current =
+ group_ptr -> tx_event_flags_group_current & flags_to_set;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this event flag group. */
+ events_set_notify = group_ptr -> tx_event_flags_group_set_notify;
+#endif
+
+ /* "OR" the flags into the current events of the group. */
+ group_ptr -> tx_event_flags_group_current =
+ group_ptr -> tx_event_flags_group_current | flags_to_set;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Determine if there are any delayed flags to clear. */
+ if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
+ {
+
+ /* Yes, we need to neutralize the delayed clearing as well. */
+ group_ptr -> tx_event_flags_group_delayed_clear =
+ group_ptr -> tx_event_flags_group_delayed_clear & ~flags_to_set;
+ }
+#endif
+
+ /* Clear the preempt check flag. */
+ preempt_check = TX_FALSE;
+
+ /* Pickup the thread suspended count. */
+ suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
+
+ /* Determine if there are any threads suspended on the event flag group. */
+ if (group_ptr -> tx_event_flags_group_suspension_list != TX_NULL)
+ {
+
+ /* Determine if there is just a single thread waiting on the event
+ flag group. */
+ if (suspended_count == ((UINT) 1))
+ {
+
+ /* Single thread waiting for event flags. Bypass the multiple thread
+ logic. */
+
+ /* Setup thread pointer. */
+ thread_ptr = group_ptr -> tx_event_flags_group_suspension_list;
+
+ /* Pickup the current event flags. */
+ current_event_flags = group_ptr -> tx_event_flags_group_current;
+
+ /* Pickup the suspend information. */
+ requested_flags = thread_ptr -> tx_thread_suspend_info;
+
+ /* Pickup the suspend option. */
+ get_option = thread_ptr -> tx_thread_suspend_option;
+
+ /* Isolate the AND selection. */
+ and_request = (get_option & TX_AND);
+
+ /* Check for AND condition. All flags must be present to satisfy request. */
+ if (and_request == TX_AND)
+ {
+
+ /* AND request is present. */
+
+ /* Calculate the flags present. */
+ flags_satisfied = (current_event_flags & requested_flags);
+
+ /* Determine if they satisfy the AND request. */
+ if (flags_satisfied != requested_flags)
+ {
+
+ /* No, not all the requested flags are present. Clear the flags present variable. */
+ flags_satisfied = ((ULONG) 0);
+ }
+ }
+ else
+ {
+
+ /* OR request is present. Simply or the requested flags and the current flags. */
+ flags_satisfied = (current_event_flags & requested_flags);
+ }
+
+ /* Determine if the request is satisfied. */
+ if (flags_satisfied != ((ULONG) 0))
+ {
+
+ /* Yes, resume the thread and apply any event flag
+ clearing. */
+
+ /* Set the preempt check flag. */
+ preempt_check = TX_TRUE;
+
+ /* Return the actual event flags that satisfied the request. */
+ suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ *suspend_info_ptr = current_event_flags;
+
+ /* Pickup the clear bit. */
+ clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
+
+ /* Determine whether or not clearing needs to take place. */
+ if (clear_request == TX_TRUE)
+ {
+
+ /* Yes, clear the flags that satisfied this request. */
+ group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & (~requested_flags);
+ }
+
+ /* Clear the suspension information in the event flag group. */
+ group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
+ group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts to remove the semaphore from the created list. */
+ TX_DISABLE
+#endif
+ }
+ }
+ else
+ {
+
+ /* Otherwise, the event flag requests of multiple threads must be
+ examined. */
+
+ /* Setup thread pointer, keep a local copy of the head pointer. */
+ suspended_list = group_ptr -> tx_event_flags_group_suspension_list;
+ thread_ptr = suspended_list;
+
+ /* Clear the suspended list head pointer to thwart manipulation of
+ the list in ISR's while we are processing here. */
+ group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
+
+ /* Setup the satisfied thread pointers. */
+ satisfied_list = TX_NULL;
+ last_satisfied = TX_NULL;
+
+ /* Pickup the current event flags. */
+ current_event_flags = group_ptr -> tx_event_flags_group_current;
+
+ /* Disable preemption while we process the suspended list. */
+ _tx_thread_preempt_disable++;
+
+ /* Loop to examine all of the suspended threads. */
+ do
+ {
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+#endif
+
+ /* Determine if we need to reset the search. */
+ if (group_ptr -> tx_event_flags_group_reset_search != TX_FALSE)
+ {
+
+ /* Clear the reset search flag. */
+ group_ptr -> tx_event_flags_group_reset_search = TX_FALSE;
+
+ /* Move the thread pointer to the beginning of the search list. */
+ thread_ptr = suspended_list;
+
+ /* Reset the suspended count. */
+ suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
+
+ /* Update the current events with any new ones that might
+ have been set in a nested set events call from an ISR. */
+ current_event_flags = current_event_flags | group_ptr -> tx_event_flags_group_current;
+ }
+
+ /* Save next thread pointer. */
+ next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
+
+ /* Pickup the suspend information. */
+ requested_flags = thread_ptr -> tx_thread_suspend_info;
+
+ /* Pickup this thread's suspension get option. */
+ get_option = thread_ptr -> tx_thread_suspend_option;
+
+ /* Isolate the AND selection. */
+ and_request = (get_option & TX_AND);
+
+ /* Check for AND condition. All flags must be present to satisfy request. */
+ if (and_request == TX_AND)
+ {
+
+ /* AND request is present. */
+
+ /* Calculate the flags present. */
+ flags_satisfied = (current_event_flags & requested_flags);
+
+ /* Determine if they satisfy the AND request. */
+ if (flags_satisfied != requested_flags)
+ {
+
+ /* No, not all the requested flags are present. Clear the flags present variable. */
+ flags_satisfied = ((ULONG) 0);
+ }
+ }
+ else
+ {
+
+ /* OR request is present. Simply or the requested flags and the current flags. */
+ flags_satisfied = (current_event_flags & requested_flags);
+ }
+
+ /* Check to see if the thread had a timeout or wait abort during the event search processing.
+ If so, just set the flags satisfied to ensure the processing here removes the thread from
+ the suspension list. */
+ if (thread_ptr -> tx_thread_state != TX_EVENT_FLAG)
+ {
+
+ /* Simply set the satisfied flags to 1 in order to remove the thread from the suspension list. */
+ flags_satisfied = ((ULONG) 1);
+ }
+
+ /* Determine if the request is satisfied. */
+ if (flags_satisfied != ((ULONG) 0))
+ {
+
+ /* Yes, this request can be handled now. */
+
+ /* Set the preempt check flag. */
+ preempt_check = TX_TRUE;
+
+ /* Determine if the thread is still suspended on the event flag group. If not, a wait
+ abort must have been done from an ISR. */
+ if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
+ {
+
+ /* Return the actual event flags that satisfied the request. */
+ suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ *suspend_info_ptr = current_event_flags;
+
+ /* Pickup the clear bit. */
+ clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
+
+ /* Determine whether or not clearing needs to take place. */
+ if (clear_request == TX_TRUE)
+ {
+
+ /* Yes, clear the flags that satisfied this request. */
+ group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & ~requested_flags;
+ }
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+ }
+
+ /* We need to remove the thread from the suspension list and place it in the
+ expired list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ suspended_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Update the list head pointer, if removing the head of the
+ list. */
+ if (suspended_list == thread_ptr)
+ {
+
+ /* Yes, head pointer needs to be updated. */
+ suspended_list = thread_ptr -> tx_thread_suspended_next;
+ }
+ }
+
+ /* Decrement the suspension count. */
+ group_ptr -> tx_event_flags_group_suspended_count--;
+
+ /* Place this thread on the expired list. */
+ if (satisfied_list == TX_NULL)
+ {
+
+ /* First thread on the satisfied list. */
+ satisfied_list = thread_ptr;
+ last_satisfied = thread_ptr;
+
+ /* Setup initial next pointer. */
+ thread_ptr -> tx_thread_suspended_next = TX_NULL;
+ }
+ else
+ {
+
+ /* Not the first thread on the satisfied list. */
+
+ /* Link it up at the end. */
+ last_satisfied -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = TX_NULL;
+ last_satisfied = thread_ptr;
+ }
+ }
+
+ /* Copy next thread pointer to working thread ptr. */
+ thread_ptr = next_thread_ptr;
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ } while (suspended_count != TX_NO_SUSPENSIONS);
+
+ /* Setup the group's suspension list head again. */
+ group_ptr -> tx_event_flags_group_suspension_list = suspended_list;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Determine if there is any delayed event clearing to perform. */
+ if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
+ {
+
+ /* Perform the delayed event clearing. */
+ group_ptr -> tx_event_flags_group_current =
+ group_ptr -> tx_event_flags_group_current & ~(group_ptr -> tx_event_flags_group_delayed_clear);
+
+ /* Clear the delayed event flag clear value. */
+ group_ptr -> tx_event_flags_group_delayed_clear = ((ULONG) 0);
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the satisfied list, setup initial thread pointer. */
+ thread_ptr = satisfied_list;
+ while(thread_ptr != TX_NULL)
+ {
+
+ /* Get next pointer first. */
+ next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupt posture. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move next thread to current. */
+ thread_ptr = next_thread_ptr;
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release thread preemption disable. */
+ _tx_thread_preempt_disable--;
+ }
+ }
+ else
+ {
+
+ /* Determine if we need to set the reset search field. */
+ if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* We interrupted a search of an event flag group suspension
+ list. Make sure we reset the search. */
+ group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (events_set_notify != TX_NULL)
+ {
+
+ /* Call application event flags set notification. */
+ (events_set_notify)(group_ptr);
+ }
+#endif
+
+ /* Determine if a check for preemption is necessary. */
+ if (preempt_check == TX_TRUE)
+ {
+
+ /* Yes, one or more threads were resumed, check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+ }
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_event_flags_set_notify.c b/common/src/tx_event_flags_set_notify.c
new file mode 100644
index 00000000..b65cd30b
--- /dev/null
+++ b/common/src/tx_event_flags_set_notify.c
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_event_flags_set_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application callback function that is */
+/* called whenever an event flag is set in this group. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block*/
+/* group_put_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr))
+{
+
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+
+ TX_EVENT_FLAGS_GROUP_NOT_USED(group_ptr);
+ TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(events_set_notify);
+
+ /* Feature is not enabled, return error. */
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Make entry in event log. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET_NOTIFY, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
+
+ /* Make entry in event log. */
+ TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT
+
+ /* Setup event flag group set notification callback function. */
+ group_ptr -> tx_event_flags_group_set_notify = events_set_notify;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success to caller. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_initialize_high_level.c b/common/src/tx_initialize_high_level.c
new file mode 100644
index 00000000..12dbd143
--- /dev/null
+++ b/common/src/tx_initialize_high_level.c
@@ -0,0 +1,150 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+/* Determine if in-line initialization is required. */
+#ifdef TX_INLINE_INITIALIZATION
+#define TX_INVOKE_INLINE_INITIALIZATION
+#endif
+
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_semaphore.h"
+#include "tx_queue.h"
+#include "tx_event_flags.h"
+#include "tx_mutex.h"
+#include "tx_block_pool.h"
+#include "tx_byte_pool.h"
+
+
+/* Define the unused memory pointer. The value of the first available
+ memory address is placed in this variable in the low-level
+ initialization function. The content of this variable is passed
+ to the application's system definition function. */
+
+VOID *_tx_initialize_unused_memory;
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_high_level PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for initializing all of the other */
+/* components in the ThreadX real-time kernel. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_initialize Initialize the thread control */
+/* component */
+/* _tx_timer_initialize Initialize the timer control */
+/* component */
+/* _tx_semaphore_initialize Initialize the semaphore control */
+/* component */
+/* _tx_queue_initialize Initialize the queue control */
+/* component */
+/* _tx_event_flags_initialize Initialize the event flags control*/
+/* component */
+/* _tx_block_pool_initialize Initialize the block pool control */
+/* component */
+/* _tx_byte_pool_initialize Initialize the byte pool control */
+/* component */
+/* _tx_mutex_initialize Initialize the mutex control */
+/* component */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter Kernel entry function */
+/* _tx_initialize_kernel_setup Early kernel setup function that */
+/* is optionally called by */
+/* compiler's startup code. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_initialize_high_level(VOID)
+{
+
+ /* Initialize event tracing, if enabled. */
+ TX_TRACE_INITIALIZE
+
+ /* Initialize the event log, if enabled. */
+ TX_EL_INITIALIZE
+
+ /* Call the thread control initialization function. */
+ _tx_thread_initialize();
+
+#ifndef TX_NO_TIMER
+
+ /* Call the timer control initialization function. */
+ _tx_timer_initialize();
+#endif
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Call the semaphore initialization function. */
+ _tx_semaphore_initialize();
+
+ /* Call the queue initialization function. */
+ _tx_queue_initialize();
+
+ /* Call the event flag initialization function. */
+ _tx_event_flags_initialize();
+
+ /* Call the block pool initialization function. */
+ _tx_block_pool_initialize();
+
+ /* Call the byte pool initialization function. */
+ _tx_byte_pool_initialize();
+
+ /* Call the mutex initialization function. */
+ _tx_mutex_initialize();
+#endif
+}
+
diff --git a/common/src/tx_initialize_kernel_enter.c b/common/src/tx_initialize_kernel_enter.c
new file mode 100644
index 00000000..5f9af949
--- /dev/null
+++ b/common/src/tx_initialize_kernel_enter.c
@@ -0,0 +1,148 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/* Define any port-specific scheduling data structures. */
+
+TX_PORT_SPECIFIC_DATA
+
+
+#ifdef TX_SAFETY_CRITICAL
+TX_SAFETY_CRITICAL_EXCEPTION_HANDLER
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_kernel_enter PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is the first ThreadX function called during */
+/* initialization. It is called from the application's "main()" */
+/* function. It is important to note that this routine never */
+/* returns. The processing of this function is relatively simple: */
+/* it calls several ThreadX initialization functions (if needed), */
+/* calls the application define function, and then invokes the */
+/* scheduler. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_initialize_low_level Low-level initialization */
+/* _tx_initialize_high_level High-level initialization */
+/* tx_application_define Application define function */
+/* _tx_thread_scheduler ThreadX scheduling loop */
+/* */
+/* CALLED BY */
+/* */
+/* main Application main program */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_initialize_kernel_enter(VOID)
+{
+
+ /* Determine if the compiler has pre-initialized ThreadX. */
+ if (_tx_thread_system_state != TX_INITIALIZE_ALMOST_DONE)
+ {
+
+ /* No, the initialization still needs to take place. */
+
+ /* Ensure that the system state variable is set to indicate
+ initialization is in progress. Note that this variable is
+ later used to represent interrupt nesting. */
+ _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
+
+ /* Call any port specific preprocessing. */
+ TX_PORT_SPECIFIC_PRE_INITIALIZATION
+
+ /* Invoke the low-level initialization to handle all processor specific
+ initialization issues. */
+ _tx_initialize_low_level();
+
+ /* Invoke the high-level initialization to exercise all of the
+ ThreadX components and the application's initialization
+ function. */
+ _tx_initialize_high_level();
+
+ /* Call any port specific post-processing. */
+ TX_PORT_SPECIFIC_POST_INITIALIZATION
+ }
+
+ /* Optional processing extension. */
+ TX_INITIALIZE_KERNEL_ENTER_EXTENSION
+
+ /* Ensure that the system state variable is set to indicate
+ initialization is in progress. Note that this variable is
+ later used to represent interrupt nesting. */
+ _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
+
+ /* Call the application provided initialization function. Pass the
+ first available memory address to it. */
+ tx_application_define(_tx_initialize_unused_memory);
+
+ /* Set the system state in preparation for entering the thread
+ scheduler. */
+ _tx_thread_system_state = TX_INITIALIZE_IS_FINISHED;
+
+ /* Call any port specific pre-scheduler processing. */
+ TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
+
+ /* Enter the scheduling loop to start executing threads! */
+ _tx_thread_schedule();
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
+
diff --git a/common/src/tx_initialize_kernel_setup.c b/common/src/tx_initialize_kernel_setup.c
new file mode 100644
index 00000000..b961007e
--- /dev/null
+++ b/common/src/tx_initialize_kernel_setup.c
@@ -0,0 +1,100 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_kernel_setup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is called by the compiler's startup code to make */
+/* ThreadX objects accessible to the compiler's library. If this */
+/* function is not called by the compiler, all ThreadX initialization */
+/* takes place from the kernel enter function defined previously. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_initialize_low_level Low-level initialization */
+/* _tx_initialize_high_level High-level initialization */
+/* */
+/* CALLED BY */
+/* */
+/* startup code Compiler startup code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_initialize_kernel_setup(VOID)
+{
+
+ /* Ensure that the system state variable is set to indicate
+ initialization is in progress. Note that this variable is
+ later used to represent interrupt nesting. */
+ _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
+
+ /* Call any port specific preprocessing. */
+ TX_PORT_SPECIFIC_PRE_INITIALIZATION
+
+ /* Invoke the low-level initialization to handle all processor specific
+ initialization issues. */
+ _tx_initialize_low_level();
+
+ /* Invoke the high-level initialization to exercise all of the
+ ThreadX components and the application's initialization
+ function. */
+ _tx_initialize_high_level();
+
+ /* Call any port specific post-processing. */
+ TX_PORT_SPECIFIC_POST_INITIALIZATION
+
+ /* Set the system state to indicate initialization is almost done. */
+ _tx_thread_system_state = TX_INITIALIZE_ALMOST_DONE;
+}
+
diff --git a/common/src/tx_misra.c b/common/src/tx_misra.c
new file mode 100644
index 00000000..814205a7
--- /dev/null
+++ b/common/src/tx_misra.c
@@ -0,0 +1,833 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** _tx_version_id */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_MISRA_ENABLE
+#define TX_THREAD_INIT
+//CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.0 MISRA C Compliant *";
+#endif
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size)
+{
+ memset(ptr, value, size);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount)
+{
+ ptr = ptr + amount;
+ return(ptr);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount)
+{
+ ptr = ptr - amount;
+ return(ptr);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2)
+{
+
+ULONG value;
+
+ value = ptr1 - ptr2;
+ return(value);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr)
+{
+ return((ULONG) ptr);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount)
+{
+ ptr = ptr + amount;
+ return(ptr);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount)
+{
+
+ ptr = ptr - amount;
+ return(ptr);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2)
+{
+ULONG value;
+
+ value = ptr1 - ptr2;
+ return(value);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID *_tx_misra_ulong_to_pointer_convert(ULONG input)
+{
+
+ return((VOID *) input);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, UINT size)
+{
+
+ULONG *s, *d;
+UINT z;
+
+ s = *source;
+ d = *destination;
+ z = size;
+
+ *(d) = *(s);
+ (d)++;
+ (s)++;
+ if ((z) > ((UINT) 1))
+ {
+ (z)--;
+ while ((z))
+ {
+ *(d) = *(s);
+ (d)++;
+ (s)++;
+ (z)--;
+ }
+ }
+
+ *source = s;
+ *destination = d;
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, TX_TIMER_INTERNAL **ptr2)
+{
+
+ULONG value;
+
+ value = ptr1 - ptr2;
+ return(value);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL **ptr1, ULONG amount)
+{
+ ptr1 = ptr1 + amount;
+ return(ptr1);
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL *internal_timer, TX_TIMER **user_timer)
+{
+
+UCHAR *working_ptr;
+TX_TIMER *temp_timer;
+
+
+ working_ptr = (UCHAR *) internal_timer;
+
+ temp_timer = (TX_TIMER *) working_ptr;
+ working_ptr = working_ptr - (((UCHAR *) &temp_timer -> tx_timer_internal) - ((UCHAR *) &temp_timer -> tx_timer_id));
+ *user_timer = (TX_TIMER *) working_ptr;
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, VOID **highest_stack)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ TX_DISABLE
+ if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID))
+ {
+ if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) *highest_stack))
+ {
+ *highest_stack = (thread_ptr) -> tx_thread_stack_ptr;
+ }
+ if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) ||
+ (*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) ||
+ (((ULONG *) *highest_stack) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start)))
+ {
+ TX_RESTORE
+ _tx_thread_stack_error_handler((thread_ptr));
+ TX_DISABLE
+ }
+ if (*(((ULONG *) *highest_stack) - 1) != TX_STACK_FILL)
+ {
+ TX_RESTORE
+ _tx_thread_stack_analyze((thread_ptr));
+ TX_DISABLE
+ }
+ }
+ TX_RESTORE
+}
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID _tx_misra_trace_event_insert(ULONG event_id, VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, ULONG time_stamp)
+{
+
+TX_TRACE_BUFFER_ENTRY *trace_event_ptr;
+ULONG trace_system_state;
+ULONG trace_priority;
+TX_THREAD *trace_thread_ptr;
+
+
+ trace_event_ptr = _tx_trace_buffer_current_ptr;
+ if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (filter))))
+ {
+ TX_TRACE_PORT_EXTENSION
+ trace_system_state = (ULONG) _tx_thread_system_state;
+ trace_thread_ptr = _tx_thread_current_ptr;
+
+ if (trace_system_state == 0)
+ {
+ trace_priority = trace_thread_ptr -> tx_thread_priority;
+ trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16);
+ }
+ else if (trace_system_state < 0xF0F0F0F0UL)
+ {
+ trace_priority = (ULONG) trace_thread_ptr;
+ trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL;
+ }
+ else
+ {
+ trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL;
+ trace_priority = 0;
+ }
+ trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr;
+ trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority;
+ trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (event_id);
+ trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) (time_stamp);
+#ifdef TX_MISRA_ENABLE
+ trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (info_field_1);
+ trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (info_field_2);
+ trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (info_field_3);
+ trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (info_field_4);
+#else
+ trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (info_field_1);
+ trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (info_field_2);
+ trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (info_field_3);
+ trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (info_field_4);
+#endif
+ trace_event_ptr++;
+ if (trace_event_ptr >= _tx_trace_buffer_end_ptr)
+ {
+ trace_event_ptr = _tx_trace_buffer_start_ptr;
+ _tx_trace_buffer_current_ptr = trace_event_ptr;
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr;
+ if (_tx_trace_full_notify_function)
+ (_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr);
+ }
+ else
+ {
+ _tx_trace_buffer_current_ptr = trace_event_ptr;
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr;
+ }
+ }
+}
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ULONG _tx_misra_time_stamp_get(VOID)
+{
+
+ /* Return time stamp. */
+ return(0);
+}
+
+#endif
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+UINT _tx_misra_always_true(void)
+{
+ return(TX_TRUE);
+}
+
+
+/******************************************************************************************/
+/******************************************************************************************/
+/** */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** */
+/******************************************************************************************/
+/******************************************************************************************/
+UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr)
+{
+
+ /* Return an indirect UCHAR pointer. */
+ return((UCHAR **) ((VOID *) return_ptr));
+}
+
+
+/***************************************************************************************/
+/***************************************************************************************/
+/** */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** */
+/***************************************************************************************/
+/***************************************************************************************/
+UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return an indirect UCHAR pointer. */
+ return((UCHAR **) ((VOID *) pointer));
+}
+
+
+/***********************************************************************************/
+/***********************************************************************************/
+/** */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** */
+/***********************************************************************************/
+/***********************************************************************************/
+UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pool));
+}
+
+
+/******************************************************************************************/
+/******************************************************************************************/
+/** */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** */
+/******************************************************************************************/
+/******************************************************************************************/
+TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer)
+{
+
+ /* Return a block pool pointer. */
+ return((TX_BLOCK_POOL *) ((VOID *) pointer));
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/** */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** */
+/*****************************************************************************/
+/*****************************************************************************/
+UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pointer));
+}
+
+
+/************************************************************************************/
+/************************************************************************************/
+/** */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** */
+/************************************************************************************/
+/************************************************************************************/
+TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((TX_BLOCK_POOL *) ((VOID *) pointer));
+}
+
+
+/**************************************************************************************/
+/**************************************************************************************/
+/** */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** */
+/**************************************************************************************/
+/**************************************************************************************/
+UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR **) ((VOID *) pointer));
+}
+
+
+/*****************************************************************************************/
+/*****************************************************************************************/
+/** */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** */
+/*****************************************************************************************/
+/*****************************************************************************************/
+TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer)
+{
+
+ /* Return a byte pool pointer. */
+ return((TX_BYTE_POOL *) ((VOID *) pointer));
+}
+
+
+/***************************************************************************************/
+/***************************************************************************************/
+/** */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** */
+/***************************************************************************************/
+/***************************************************************************************/
+UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pool));
+}
+
+
+/*****************************************************************************************/
+/*****************************************************************************************/
+/** */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** */
+/*****************************************************************************************/
+/*****************************************************************************************/
+ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return an align time pointer. */
+ return((ALIGN_TYPE *) ((VOID *) pointer));
+}
+
+
+/****************************************************************************************************/
+/****************************************************************************************************/
+/** */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** */
+/****************************************************************************************************/
+/****************************************************************************************************/
+TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return a byte pool pointer. */
+ return((TX_BYTE_POOL **) ((VOID *) pointer));
+}
+
+
+/**************************************************************************************************/
+/**************************************************************************************************/
+/** */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** */
+/**************************************************************************************************/
+/**************************************************************************************************/
+TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer)
+{
+
+ /* Return event flags pointer. */
+ return((TX_EVENT_FLAGS_GROUP *) ((VOID *) pointer));
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/** */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** */
+/*****************************************************************************/
+/*****************************************************************************/
+ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer)
+{
+
+ /* Return a ULONG pointer. */
+ return((ULONG *) ((VOID *) pointer));
+}
+
+
+/********************************************************************************/
+/********************************************************************************/
+/** */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** */
+/********************************************************************************/
+/********************************************************************************/
+TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer)
+{
+
+ /* Return a mutex pointer. */
+ return((TX_MUTEX *) ((VOID *) pointer));
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+UINT _tx_misra_status_get(UINT status)
+{
+
+ /* Return a successful status. */
+ return(TX_SUCCESS);
+}
+
+
+/********************************************************************************/
+/********************************************************************************/
+/** */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** */
+/********************************************************************************/
+/********************************************************************************/
+TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer)
+{
+
+ /* Return queue pointer. */
+ return((TX_QUEUE *) ((VOID *) pointer));
+}
+
+
+/****************************************************************************************/
+/****************************************************************************************/
+/** */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** */
+/****************************************************************************************/
+/****************************************************************************************/
+TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer)
+{
+
+ /* Return semaphore pointer. */
+ return((TX_SEMAPHORE *) ((VOID *) pointer));
+}
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return a VOID pointer. */
+ return((VOID *) ((VOID *) pointer));
+}
+
+
+/*********************************************************************************/
+/*********************************************************************************/
+/** */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** */
+/*********************************************************************************/
+/*********************************************************************************/
+TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value)
+{
+
+ /* Return a thread pointer. */
+ return((TX_THREAD *) ((VOID *) value));
+}
+
+
+/***************************************************************************************************/
+/***************************************************************************************************/
+/** */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** */
+/***************************************************************************************************/
+/***************************************************************************************************/
+VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer)
+{
+
+ /* Return a void pointer. */
+ return((VOID *) ((VOID *) pointer));
+}
+
+
+/***************************************************************************************/
+/***************************************************************************************/
+/** */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** */
+/***************************************************************************************/
+/***************************************************************************************/
+CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer)
+{
+
+ /* Return a CHAR pointer. */
+ return((CHAR *) ((VOID *) pointer));
+}
+
+
+/**********************************************************************************/
+/**********************************************************************************/
+/** */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** */
+/**********************************************************************************/
+/**********************************************************************************/
+TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer)
+{
+
+ /* Return thread pointer. */
+ return((TX_THREAD *) ((VOID *) pointer));
+}
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/************************************************************************************************/
+/************************************************************************************************/
+/** */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** */
+/************************************************************************************************/
+/************************************************************************************************/
+UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pointer));
+}
+
+
+/************************************************************************************************/
+/************************************************************************************************/
+/** */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** */
+/************************************************************************************************/
+/************************************************************************************************/
+TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return an object entry pointer. */
+ return((TX_TRACE_OBJECT_ENTRY *) ((VOID *) pointer));
+}
+
+
+/******************************************************************************************/
+/******************************************************************************************/
+/** */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** */
+/******************************************************************************************/
+/******************************************************************************************/
+TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return a trace header pointer. */
+ return((TX_TRACE_HEADER *) ((VOID *) pointer));
+}
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer)
+{
+
+ /* Return a trace buffer entry pointer. */
+ return((TX_TRACE_BUFFER_ENTRY *) ((VOID *) pointer));
+}
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pointer));
+}
+
+#endif
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer)
+{
+
+ /* Return a UCHAR pointer. */
+ return((UCHAR *) ((VOID *) pointer));
+}
+
+
+
diff --git a/common/src/tx_mutex_cleanup.c b/common/src/tx_mutex_cleanup.c
new file mode 100644
index 00000000..f076c772
--- /dev/null
+++ b/common/src/tx_mutex_cleanup.c
@@ -0,0 +1,313 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes mutex timeout and thread terminate */
+/* actions that require the mutex data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_MUTEX *mutex_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the mutex. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_mutex_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to mutex control block. */
+ mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for NULL mutex pointer. */
+ if (mutex_ptr != TX_NULL)
+ {
+
+ /* Determine if the mutex ID is valid. */
+ if (mutex_ptr -> tx_mutex_id == TX_MUTEX_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to mutex control block. */
+ mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Yes, we still have thread suspension! */
+
+ /* Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Decrement the suspension count. */
+ mutex_ptr -> tx_mutex_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = mutex_ptr -> tx_mutex_suspended_count;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (mutex_ptr -> tx_mutex_suspension_list == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ mutex_ptr -> tx_mutex_suspension_list = next_thread;
+ }
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP)
+ {
+
+ /* Timeout condition and the thread still suspended on the mutex.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_mutex_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this semaphore. */
+ mutex_ptr -> tx_mutex_performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ thread_ptr -> tx_thread_suspend_status = TX_NOT_AVAILABLE;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_thread_release PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function releases all mutexes owned by the thread. This */
+/* function is called when the thread completes or is terminated. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread's control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_put Release the mutex */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_shell_entry Thread completion processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_MUTEX *mutex_ptr;
+#ifdef TX_MISRA_ENABLE
+UINT status;
+#endif
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Loop to look at all the mutexes. */
+ do
+ {
+
+ /* Pickup the mutex head pointer. */
+ mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list;
+
+ /* Determine if there is a mutex. */
+ if (mutex_ptr != TX_NULL)
+ {
+
+ /* Yes, set the ownership count to 1. */
+ mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifdef TX_MISRA_ENABLE
+ /* Release the mutex. */
+ do
+ {
+ status = _tx_mutex_put(mutex_ptr);
+ } while (status != TX_SUCCESS);
+#else
+ _tx_mutex_put(mutex_ptr);
+#endif
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Move to the next mutex. */
+ mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list;
+ }
+ } while (mutex_ptr != TX_NULL);
+
+ /* Restore preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+
diff --git a/common/src/tx_mutex_create.c b/common/src/tx_mutex_create.c
new file mode 100644
index 00000000..3b70289d
--- /dev/null
+++ b/common/src/tx_mutex_create.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_trace.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a mutex with optional priority inheritance as */
+/* specified in this call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block*/
+/* name_ptr Pointer to mutex name */
+/* inherit Priority inheritance option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_MUTEX *next_mutex;
+TX_MUTEX *previous_mutex;
+
+
+ /* Initialize mutex control block to all zeros. */
+ TX_MEMSET(mutex_ptr, 0, (sizeof(TX_MUTEX)));
+
+ /* Setup the basic mutex fields. */
+ mutex_ptr -> tx_mutex_name = name_ptr;
+ mutex_ptr -> tx_mutex_inherit = inherit;
+
+ /* Disable interrupts to place the mutex on the created list. */
+ TX_DISABLE
+
+ /* Setup the mutex ID to make it valid. */
+ mutex_ptr -> tx_mutex_id = TX_MUTEX_ID;
+
+ /* Setup the thread mutex release function pointer. */
+ _tx_thread_mutex_release = &(_tx_mutex_thread_release);
+
+ /* Place the mutex on the list of created mutexes. First,
+ check for an empty list. */
+ if (_tx_mutex_created_count == TX_EMPTY)
+ {
+
+ /* The created mutex list is empty. Add mutex to empty list. */
+ _tx_mutex_created_ptr = mutex_ptr;
+ mutex_ptr -> tx_mutex_created_next = mutex_ptr;
+ mutex_ptr -> tx_mutex_created_previous = mutex_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_mutex = _tx_mutex_created_ptr;
+ previous_mutex = next_mutex -> tx_mutex_created_previous;
+
+ /* Place the new mutex in the list. */
+ next_mutex -> tx_mutex_created_previous = mutex_ptr;
+ previous_mutex -> tx_mutex_created_next = mutex_ptr;
+
+ /* Setup this mutex's next and previous created links. */
+ mutex_ptr -> tx_mutex_created_previous = previous_mutex;
+ mutex_ptr -> tx_mutex_created_next = next_mutex;
+ }
+
+ /* Increment the ownership count. */
+ _tx_mutex_created_count++;
+
+ /* Optional mutex create extended processing. */
+ TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, name_ptr, inherit, 0)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_CREATE, mutex_ptr, inherit, TX_POINTER_TO_ULONG_CONVERT(&next_mutex), 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_mutex_delete.c b/common/src/tx_mutex_delete.c
new file mode 100644
index 00000000..0b2dc079
--- /dev/null
+++ b/common/src/tx_mutex_delete.c
@@ -0,0 +1,243 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified mutex. All threads */
+/* suspended on the mutex are resumed with the TX_DELETED status */
+/* code. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_put Release an owned mutex */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+TX_THREAD *owner_thread;
+UINT suspended_count;
+TX_MUTEX *next_mutex;
+TX_MUTEX *previous_mutex;
+#ifdef TX_MISRA_ENABLE
+UINT status;
+#endif
+
+ /* Disable interrupts to remove the mutex from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_DELETE, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Optional mutex delete extended processing. */
+ TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(mutex_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_DELETE_INSERT
+
+ /* Clear the mutex ID to make it invalid. */
+ mutex_ptr -> tx_mutex_id = TX_CLEAR_ID;
+
+ /* Decrement the created count. */
+ _tx_mutex_created_count--;
+
+ /* See if the mutex is the only one on the list. */
+ if (_tx_mutex_created_count == TX_EMPTY)
+ {
+
+ /* Only created mutex, just set the created list to NULL. */
+ _tx_mutex_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_mutex = mutex_ptr -> tx_mutex_created_next;
+ previous_mutex = mutex_ptr -> tx_mutex_created_previous;
+ next_mutex -> tx_mutex_created_previous = previous_mutex;
+ previous_mutex -> tx_mutex_created_next = next_mutex;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_mutex_created_ptr == mutex_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_mutex_created_ptr = next_mutex;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
+ mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
+ suspended_count = mutex_ptr -> tx_mutex_suspended_count;
+ mutex_ptr -> tx_mutex_suspended_count = TX_NO_SUSPENSIONS;
+
+
+ /* Determine if the mutex is currently on a thread's ownership list. */
+
+ /* Setup pointer to owner of mutex. */
+ owner_thread = mutex_ptr -> tx_mutex_owner;
+
+ /* Determine if there is a valid thread pointer. */
+ if (owner_thread != TX_NULL)
+ {
+
+ /* Yes, remove this mutex from the owned list. */
+
+ /* Set the ownership count to 1. */
+ mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifdef TX_MISRA_ENABLE
+ /* Release the mutex. */
+ do
+ {
+ status = _tx_mutex_put(mutex_ptr);
+ } while (status != TX_SUCCESS);
+#else
+ _tx_mutex_put(mutex_ptr);
+#endif
+
+ /* Disable interrupts. */
+ TX_DISABLE
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the mutex list to resume any and all threads suspended
+ on this mutex. */
+ while (suspended_count != ((ULONG) 0))
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_MUTEX_DELETE_PORT_COMPLETION(mutex_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_mutex_get.c b/common/src/tx_mutex_get.c
new file mode 100644
index 00000000..1d805c84
--- /dev/null
+++ b/common/src/tx_mutex_get.c
@@ -0,0 +1,409 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets the specified mutex. If the calling thread */
+/* already owns the mutex, an ownership count is simply increased. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Suspend thread service */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* _tx_mutex_priority_change Inherit thread priority */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_MUTEX *next_mutex;
+TX_MUTEX *previous_mutex;
+TX_THREAD *mutex_owner;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+
+
+ /* Disable interrupts to get an instance from the mutex. */
+ TX_DISABLE
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total mutex get counter. */
+ _tx_mutex_performance_get_count++;
+
+ /* Increment the number of attempts to get this mutex. */
+ mutex_ptr -> tx_mutex_performance_get_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_GET_INSERT
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Determine if this mutex is available. */
+ if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0))
+ {
+
+ /* Set the ownership count to 1. */
+ mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
+
+ /* Remember that the calling thread owns the mutex. */
+ mutex_ptr -> tx_mutex_owner = thread_ptr;
+
+ /* Determine if the thread pointer is valid. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Determine if priority inheritance is required. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Remember the current priority of thread. */
+ mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority;
+
+ /* Setup the highest priority waiting thread. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = ((UINT) TX_MAX_PRIORITIES);
+ }
+
+ /* Pickup next mutex pointer, which is the head of the list. */
+ next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
+
+ /* Determine if this thread owns any other mutexes that have priority inheritance. */
+ if (next_mutex != TX_NULL)
+ {
+
+ /* Non-empty list. Link up the mutex. */
+
+ /* Pickup the next and previous mutex pointer. */
+ previous_mutex = next_mutex -> tx_mutex_owned_previous;
+
+ /* Place the owned mutex in the list. */
+ next_mutex -> tx_mutex_owned_previous = mutex_ptr;
+ previous_mutex -> tx_mutex_owned_next = mutex_ptr;
+
+ /* Setup this mutex's next and previous created links. */
+ mutex_ptr -> tx_mutex_owned_previous = previous_mutex;
+ mutex_ptr -> tx_mutex_owned_next = next_mutex;
+ }
+ else
+ {
+
+ /* The owned mutex list is empty. Add mutex to empty list. */
+ thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr;
+ mutex_ptr -> tx_mutex_owned_next = mutex_ptr;
+ mutex_ptr -> tx_mutex_owned_previous = mutex_ptr;
+ }
+
+ /* Increment the number of mutexes owned counter. */
+ thread_ptr -> tx_thread_owned_mutex_count++;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success. */
+ status = TX_SUCCESS;
+ }
+
+ /* Otherwise, see if the owning thread is trying to obtain the same mutex. */
+ else if (mutex_ptr -> tx_mutex_owner == thread_ptr)
+ {
+
+ /* The owning thread is requesting the mutex again, just
+ increment the ownership count. */
+ mutex_ptr -> tx_mutex_ownership_count++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Determine if the request specifies suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_NOT_AVAILABLE;
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+ /* Pickup the mutex owner. */
+ mutex_owner = mutex_ptr -> tx_mutex_owner;
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total mutex suspension counter. */
+ _tx_mutex_performance_suspension_count++;
+
+ /* Increment the number of suspensions on this mutex. */
+ mutex_ptr -> tx_mutex_performance_suspension_count++;
+
+ /* Determine if a priority inversion is present. */
+ if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority)
+ {
+
+ /* Yes, priority inversion is present! */
+
+ /* Increment the total mutex priority inversions counter. */
+ _tx_mutex_performance_priority_inversion_count++;
+
+ /* Increment the number of priority inversions on this mutex. */
+ mutex_ptr -> tx_mutex_performance_priority_inversion_count++;
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the number of total thread priority inversions. */
+ _tx_thread_performance_priority_inversion_count++;
+
+ /* Increment the number of priority inversions for this thread. */
+ thread_ptr -> tx_thread_performance_priority_inversion_count++;
+#endif
+ }
+#endif
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
+
+ /* Setup cleanup information, i.e. this mutex control
+ block. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) mutex_ptr;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Setup suspension list. */
+ if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ mutex_ptr -> tx_mutex_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = mutex_ptr -> tx_mutex_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Increment the suspension count. */
+ mutex_ptr -> tx_mutex_suspended_count++;
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_MUTEX_SUSP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Determine if we need to raise the priority of the thread
+ owning the mutex. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Determine if this is the highest priority to raise for this mutex. */
+ if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
+ {
+
+ /* Remember this priority. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority;
+ }
+
+ /* Determine if we have to update inherit priority level of the mutex owner. */
+ if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
+ {
+
+ /* Remember the new priority inheritance priority. */
+ mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority;
+ }
+
+ /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */
+ if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, raise the suspended, owning thread's priority to that
+ of the current thread. */
+ _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total mutex priority inheritance counter. */
+ _tx_mutex_performance__priority_inheritance_count++;
+
+ /* Increment the number of priority inheritance situations on this mutex. */
+ mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
+#endif
+ }
+ }
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if we need to raise the priority of the thread
+ owning the mutex. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Determine if this is the highest priority to raise for this mutex. */
+ if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
+ {
+
+ /* Remember this priority. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority;
+ }
+
+ /* Determine if we have to update inherit priority level of the mutex owner. */
+ if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
+ {
+
+ /* Remember the new priority inheritance priority. */
+ mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority;
+ }
+
+ /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */
+ if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, raise the suspended, owning thread's priority to that
+ of the current thread. */
+ _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total mutex priority inheritance counter. */
+ _tx_mutex_performance__priority_inheritance_count++;
+
+ /* Increment the number of priority inheritance situations on this mutex. */
+ mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
+#endif
+ }
+ }
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Immediate return, return error completion. */
+ status = TX_NOT_AVAILABLE;
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_mutex_info_get.c b/common/src/tx_mutex_info_get.c
new file mode 100644
index 00000000..a148850b
--- /dev/null
+++ b/common/src/tx_mutex_info_get.c
@@ -0,0 +1,147 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified mutex. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* name Destination for the mutex name */
+/* count Destination for the owner count */
+/* owner Destination for the owner's */
+/* thread control block pointer */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on the mutex */
+/* suspended_count Destination for suspended count */
+/* next_mutex Destination for pointer to next */
+/* mutex on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_MUTEX **next_mutex)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the mutex. */
+ if (name != TX_NULL)
+ {
+
+ *name = mutex_ptr -> tx_mutex_name;
+ }
+
+ /* Retrieve the current ownership count of the mutex. */
+ if (count != TX_NULL)
+ {
+
+ *count = ((ULONG) mutex_ptr -> tx_mutex_ownership_count);
+ }
+
+ /* Retrieve the current owner of the mutex. */
+ if (owner != TX_NULL)
+ {
+
+ *owner = mutex_ptr -> tx_mutex_owner;
+ }
+
+ /* Retrieve the first thread suspended on this mutex. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = mutex_ptr -> tx_mutex_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this mutex. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) mutex_ptr -> tx_mutex_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next mutex created. */
+ if (next_mutex != TX_NULL)
+ {
+
+ *next_mutex = mutex_ptr -> tx_mutex_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_mutex_initialize.c b/common/src/tx_mutex_initialize.c
new file mode 100644
index 00000000..3b546ee7
--- /dev/null
+++ b/common/src/tx_mutex_initialize.c
@@ -0,0 +1,141 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Locate mutex component data in this file. */
+
+/* Define the head pointer of the created mutex list. */
+
+TX_MUTEX * _tx_mutex_created_ptr;
+
+
+/* Define the variable that holds the number of created mutexes. */
+
+ULONG _tx_mutex_created_count;
+
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of mutex puts. */
+
+ULONG _tx_mutex_performance_put_count;
+
+
+/* Define the total number of mutex gets. */
+
+ULONG _tx_mutex_performance_get_count;
+
+
+/* Define the total number of mutex suspensions. */
+
+ULONG _tx_mutex_performance_suspension_count;
+
+
+/* Define the total number of mutex timeouts. */
+
+ULONG _tx_mutex_performance_timeout_count;
+
+
+/* Define the total number of priority inversions. */
+
+ULONG _tx_mutex_performance_priority_inversion_count;
+
+
+/* Define the total number of priority inheritance conditions. */
+
+ULONG _tx_mutex_performance__priority_inheritance_count;
+
+#endif
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the mutex component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_mutex_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created mutexes list and the
+ number of mutexes created. */
+ _tx_mutex_created_ptr = TX_NULL;
+ _tx_mutex_created_count = TX_EMPTY;
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize the mutex performance counters. */
+ _tx_mutex_performance_put_count = ((ULONG) 0);
+ _tx_mutex_performance_get_count = ((ULONG) 0);
+ _tx_mutex_performance_suspension_count = ((ULONG) 0);
+ _tx_mutex_performance_timeout_count = ((ULONG) 0);
+ _tx_mutex_performance_priority_inversion_count = ((ULONG) 0);
+ _tx_mutex_performance__priority_inheritance_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_mutex_performance_info_get.c b/common/src/tx_mutex_performance_info_get.c
new file mode 100644
index 00000000..3dbd35e4
--- /dev/null
+++ b/common/src/tx_mutex_performance_info_get.c
@@ -0,0 +1,230 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* mutex. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* puts Destination for the number of */
+/* puts on to this mutex */
+/* gets Destination for the number of */
+/* gets on this mutex */
+/* suspensions Destination for the number of */
+/* suspensions on this mutex */
+/* timeouts Destination for number of timeouts*/
+/* on this mutex */
+/* inversions Destination for number of priority*/
+/* inversions on this mutex */
+/* inheritances Destination for number of priority*/
+/* inheritances on this mutex */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts, ULONG *inversions, ULONG *inheritances)
+{
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Determine if this is a legal request. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the mutex ID is invalid. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of puts on this mutex. */
+ if (puts != TX_NULL)
+ {
+
+ *puts = mutex_ptr -> tx_mutex_performance_put_count;
+ }
+
+ /* Retrieve the number of gets on this mutex. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = mutex_ptr -> tx_mutex_performance_get_count;
+ }
+
+ /* Retrieve the number of suspensions on this mutex. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = mutex_ptr -> tx_mutex_performance_suspension_count;
+ }
+
+ /* Retrieve the number of timeouts on this mutex. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = mutex_ptr -> tx_mutex_performance_timeout_count;
+ }
+
+ /* Retrieve the number of priority inversions on this mutex. */
+ if (inversions != TX_NULL)
+ {
+
+ *inversions = mutex_ptr -> tx_mutex_performance_priority_inversion_count;
+ }
+
+ /* Retrieve the number of priority inheritances on this mutex. */
+ if (inheritances != TX_NULL)
+ {
+
+ *inheritances = mutex_ptr -> tx_mutex_performance__priority_inheritance_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (mutex_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (puts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (inversions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (inheritances != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_mutex_performance_system_info_get.c b/common/src/tx_mutex_performance_system_info_get.c
new file mode 100644
index 00000000..f2cb61fb
--- /dev/null
+++ b/common/src/tx_mutex_performance_system_info_get.c
@@ -0,0 +1,205 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves system mutex performance information. */
+/* */
+/* INPUT */
+/* */
+/* puts Destination for total number of */
+/* mutex puts */
+/* gets Destination for total number of */
+/* mutex gets */
+/* suspensions Destination for total number of */
+/* mutex suspensions */
+/* timeouts Destination for total number of */
+/* mutex timeouts */
+/* inversions Destination for total number of */
+/* mutex priority inversions */
+/* inheritances Destination for total number of */
+/* mutex priority inheritances */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions,
+ ULONG *timeouts, ULONG *inversions, ULONG *inheritances)
+{
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of mutex puts. */
+ if (puts != TX_NULL)
+ {
+
+ *puts = _tx_mutex_performance_put_count;
+ }
+
+ /* Retrieve the total number of mutex gets. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = _tx_mutex_performance_get_count;
+ }
+
+ /* Retrieve the total number of mutex suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_mutex_performance_suspension_count;
+ }
+
+ /* Retrieve the total number of mutex timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_mutex_performance_timeout_count;
+ }
+
+ /* Retrieve the total number of mutex priority inversions. */
+ if (inversions != TX_NULL)
+ {
+
+ *inversions = _tx_mutex_performance_priority_inversion_count;
+ }
+
+ /* Retrieve the total number of mutex priority inheritances. */
+ if (inheritances != TX_NULL)
+ {
+
+ *inheritances = _tx_mutex_performance__priority_inheritance_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (puts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (inversions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (inheritances != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_mutex_prioritize.c b/common/src/tx_mutex_prioritize.c
new file mode 100644
index 00000000..dddc7e54
--- /dev/null
+++ b/common/src/tx_mutex_prioritize.c
@@ -0,0 +1,265 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the highest priority suspended thread at the */
+/* front of the suspension list. All other threads remain in the same */
+/* FIFO suspension order. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *priority_thread_ptr;
+TX_THREAD *head_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT list_changed;
+#ifdef TX_MISRA_ENABLE
+UINT status;
+#endif
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PRIORITIZE, mutex_ptr, mutex_ptr -> tx_mutex_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_PRIORITIZE_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = mutex_ptr -> tx_mutex_suspended_count;
+
+ /* Determine if there are fewer than 2 suspended threads. */
+ if (suspended_count < ((UINT) 2))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if there how many threads are suspended on this mutex. */
+ else if (suspended_count == ((UINT) 2))
+ {
+
+ /* Pickup the head pointer and the next pointer. */
+ head_ptr = mutex_ptr -> tx_mutex_suspension_list;
+ next_thread = head_ptr -> tx_thread_suspended_next;
+
+ /* Determine if the next suspended thread has a higher priority. */
+ if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
+ {
+
+ /* Yes, move the list head to the next thread. */
+ mutex_ptr -> tx_mutex_suspension_list = next_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = mutex_ptr -> tx_mutex_suspension_list;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the list changed flag to false. */
+ list_changed = TX_FALSE;
+
+ /* Search through the list to find the highest priority thread. */
+ do
+ {
+
+ /* Is the current thread higher priority? */
+ if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, remember that this thread is the highest priority. */
+ priority_thread_ptr = thread_ptr;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Determine if any changes to the list have occurred while
+ interrupts were enabled. */
+
+ /* Is the list head the same? */
+ if (head_ptr != mutex_ptr -> tx_mutex_suspension_list)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ else
+ {
+
+ /* Is the suspended count the same? */
+ if (suspended_count != mutex_ptr -> tx_mutex_suspended_count)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ }
+
+ /* Determine if the list has changed. */
+ if (list_changed == TX_FALSE)
+ {
+
+ /* Move the thread pointer to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = mutex_ptr -> tx_mutex_suspension_list;
+ suspended_count = mutex_ptr -> tx_mutex_suspended_count;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Reset the list changed flag. */
+ list_changed = TX_FALSE;
+ }
+
+ } while (thread_ptr != head_ptr);
+
+ /* Release preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Now determine if the highest priority thread is at the front
+ of the list. */
+ if (priority_thread_ptr != head_ptr)
+ {
+
+ /* No, we need to move the highest priority suspended thread to the
+ front of the list. */
+
+ /* First, remove the highest priority thread by updating the
+ adjacent suspended threads. */
+ next_thread = priority_thread_ptr -> tx_thread_suspended_next;
+ previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Now, link the highest priority thread at the front of the list. */
+ previous_thread = head_ptr -> tx_thread_suspended_previous;
+ priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
+ priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
+ head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
+
+ /* Move the list head pointer to the highest priority suspended thread. */
+ mutex_ptr -> tx_mutex_suspension_list = priority_thread_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+#ifdef TX_MISRA_ENABLE
+
+ /* Initialize status to success. */
+ status = TX_SUCCESS;
+
+ /* Define extended processing option. */
+ status = TX_MUTEX_PRIORITIZE_MISRA_EXTENSION(status);
+
+ /* Return completion status. */
+ return(status);
+#else
+
+ /* Return successful completion. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_mutex_priority_change.c b/common/src/tx_mutex_priority_change.c
new file mode 100644
index 00000000..6bb905d1
--- /dev/null
+++ b/common/src/tx_mutex_priority_change.c
@@ -0,0 +1,328 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_priority_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function changes the priority of the specified thread for the */
+/* priority inheritance option of the mutex service. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* new_priority New thread priority */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_thread_system_suspend Suspend thread */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_mutex_get Inherit priority */
+/* _tx_mutex_put Restore previous priority */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_THREAD *execute_ptr;
+TX_THREAD *next_execute_ptr;
+UINT original_priority;
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+ULONG priority_bit;
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+#endif
+
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Lockout interrupts while the thread is being suspended. */
+ TX_DISABLE
+#endif
+
+ /* Determine if this thread is currently ready. */
+ if (thread_ptr -> tx_thread_state != TX_READY)
+ {
+
+ /* Change thread priority to the new mutex priority-inheritance priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+
+ /* Determine how to setup the thread's preemption-threshold. */
+ if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
+ {
+
+ /* Change thread preemption-threshold to the user's preemption-threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
+ }
+ else
+ {
+
+ /* Change the thread preemption-threshold to the new threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+ }
+ else
+ {
+
+ /* Pickup the next thread to execute. */
+ execute_ptr = _tx_thread_execute_ptr;
+
+ /* Save the original priority. */
+ original_priority = thread_ptr -> tx_thread_priority;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+
+ /* At this point, the preempt disable flag is still set, so we still have
+ protection against all preemption. */
+
+ /* Change thread priority to the new mutex priority-inheritance priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+
+ /* Determine how to setup the thread's preemption-threshold. */
+ if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
+ {
+
+ /* Change thread preemption-threshold to the user's preemption-threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
+ }
+ else
+ {
+
+ /* Change the thread preemption-threshold to the new threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+
+ /* Resume the thread with the new priority. */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+#else
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable = _tx_thread_preempt_disable + ((UINT) 2);
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* The thread is ready and must first be removed from the list. Call the
+ system suspend function to accomplish this. */
+ _tx_thread_system_suspend(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* At this point, the preempt disable flag is still set, so we still have
+ protection against all preemption. */
+
+ /* Change thread priority to the new mutex priority-inheritance priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+
+ /* Determine how to setup the thread's preemption-threshold. */
+ if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
+ {
+
+ /* Change thread preemption-threshold to the user's preemption-threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
+ }
+ else
+ {
+
+ /* Change the thread preemption-threshold to the new threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread with the new priority. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Optional processing extension. */
+ TX_MUTEX_PRIORITY_CHANGE_EXTENSION
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+
+ /* Pickup the next thread to execute. */
+ next_execute_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if this thread is not the next thread to execute. */
+ if (thread_ptr != next_execute_ptr)
+ {
+
+ /* Make sure the thread is still ready. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Now check and see if this thread has an equal or higher priority. */
+ if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority)
+ {
+
+ /* Now determine if this thread was the previously executing thread. */
+ if (thread_ptr == execute_ptr)
+ {
+
+ /* Yes, this thread was previously executing before we temporarily suspended and resumed
+ it in order to change the priority. A lower or same priority thread cannot be the next thread
+ to execute in this case since this thread really didn't suspend. Simply reset the execute
+ pointer to this thread. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+ /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */
+ if (original_priority < new_priority)
+ {
+
+ /* Ensure that this thread is placed at the front of the priority list. */
+ _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr;
+ }
+ }
+ }
+ else
+ {
+
+ /* Now determine if this thread's preemption-threshold needs to be enforced. */
+ if (thread_ptr -> tx_thread_preempt_threshold < thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, preemption-threshold is in force for this thread. */
+
+ /* Compare the next thread to execute thread's priority against the thread's preemption-threshold. */
+ if (thread_ptr -> tx_thread_preempt_threshold <= next_execute_ptr -> tx_thread_priority)
+ {
+
+ /* We must swap execute pointers to enforce the preemption-threshold of a thread coming out of
+ priority inheritance. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+ /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */
+ if (original_priority < new_priority)
+ {
+
+ /* Ensure that this thread is placed at the front of the priority list. */
+ _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr;
+ }
+ }
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ else
+ {
+
+ /* In this case, we need to mark the preempted map to indicate a thread executed above the
+ preemption-threshold. */
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = (next_execute_ptr -> tx_thread_priority)/ ((UINT) 32);
+
+ /* Set the active bit to remember that the preempt map has something set. */
+ TX_DIV32_BIT_SET(next_execute_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit;
+#endif
+
+ /* Remember that this thread was preempted by a thread above the thread's threshold. */
+ TX_MOD32_BIT_SET(next_execute_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
+ }
+#endif
+ }
+ }
+ }
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+ }
+}
+
diff --git a/common/src/tx_mutex_put.c b/common/src/tx_mutex_put.c
new file mode 100644
index 00000000..93cfad07
--- /dev/null
+++ b/common/src/tx_mutex_put.c
@@ -0,0 +1,654 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function puts back an instance of the specified mutex. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Success completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_mutex_priority_change Restore previous thread priority */
+/* _tx_mutex_prioritize Prioritize the mutex suspension */
+/* _tx_mutex_thread_release Release all thread's mutexes */
+/* _tx_mutex_delete Release ownership upon mutex */
+/* deletion */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_mutex_put(TX_MUTEX *mutex_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *old_owner;
+UINT old_priority;
+UINT status;
+TX_MUTEX *next_mutex;
+TX_MUTEX *previous_mutex;
+UINT owned_count;
+UINT suspended_count;
+TX_THREAD *current_thread;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+TX_THREAD *suspended_thread;
+UINT inheritance_priority;
+
+
+ /* Setup status to indicate the processing is not complete. */
+ status = TX_NOT_DONE;
+
+ /* Disable interrupts to put an instance back to the mutex. */
+ TX_DISABLE
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total mutex put counter. */
+ _tx_mutex_performance_put_count++;
+
+ /* Increment the number of attempts to put this mutex. */
+ mutex_ptr -> tx_mutex_performance_put_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PUT, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_POINTER_TO_ULONG_CONVERT(&old_priority), TX_TRACE_MUTEX_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_MUTEX_PUT_INSERT
+
+ /* Determine if this mutex is owned. */
+ if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0))
+ {
+
+ /* Pickup the owning thread pointer. */
+ thread_ptr = mutex_ptr -> tx_mutex_owner;
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Check to see if the mutex is owned by the calling thread. */
+ if (mutex_ptr -> tx_mutex_owner != current_thread)
+ {
+
+ /* Determine if the preempt disable flag is set, indicating that
+ the caller is not the application but from ThreadX. In such
+ cases, the thread mutex owner does not need to match. */
+ if (_tx_thread_preempt_disable == ((UINT) 0))
+ {
+
+ /* Invalid mutex release. */
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Caller does not own the mutex. */
+ status = TX_NOT_OWNED;
+ }
+ }
+
+ /* Determine if we should continue. */
+ if (status == TX_NOT_DONE)
+ {
+
+ /* Decrement the mutex ownership count. */
+ mutex_ptr -> tx_mutex_ownership_count--;
+
+ /* Determine if the mutex is still owned by the current thread. */
+ if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Mutex is still owned, just return successful status. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Check for a NULL thread pointer, which can only happen during initialization. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Mutex is now available, return successful status. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* The mutex is now available. */
+
+ /* Remove this mutex from the owned mutex list. */
+
+ /* Decrement the ownership count. */
+ thread_ptr -> tx_thread_owned_mutex_count--;
+
+ /* Determine if this mutex was the only one on the list. */
+ if (thread_ptr -> tx_thread_owned_mutex_count == ((UINT) 0))
+ {
+
+ /* Yes, the list is empty. Simply set the head pointer to NULL. */
+ thread_ptr -> tx_thread_owned_mutex_list = TX_NULL;
+ }
+ else
+ {
+
+ /* No, there are more mutexes on the list. */
+
+ /* Link-up the neighbors. */
+ next_mutex = mutex_ptr -> tx_mutex_owned_next;
+ previous_mutex = mutex_ptr -> tx_mutex_owned_previous;
+ next_mutex -> tx_mutex_owned_previous = previous_mutex;
+ previous_mutex -> tx_mutex_owned_next = next_mutex;
+
+ /* See if we have to update the created list head pointer. */
+ if (thread_ptr -> tx_thread_owned_mutex_list == mutex_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ thread_ptr -> tx_thread_owned_mutex_list = next_mutex;
+ }
+ }
+
+ /* Determine if the simple, non-suspension, non-priority inheritance case is present. */
+ if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL)
+ {
+
+ /* Is this a priority inheritance mutex? */
+ if (mutex_ptr -> tx_mutex_inherit == TX_FALSE)
+ {
+
+ /* Yes, we are done - set the mutex owner to NULL. */
+ mutex_ptr -> tx_mutex_owner = TX_NULL;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Mutex is now available, return successful status. */
+ status = TX_SUCCESS;
+ }
+ }
+
+ /* Determine if the processing is complete. */
+ if (status == TX_NOT_DONE)
+ {
+
+ /* Initialize original owner and thread priority. */
+ old_owner = TX_NULL;
+ old_priority = thread_ptr -> tx_thread_user_priority;
+
+ /* Does this mutex support priority inheritance? */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Default the inheritance priority to disabled. */
+ inheritance_priority = ((UINT) TX_MAX_PRIORITIES);
+
+ /* Search the owned mutexes for this thread to determine the highest priority for this
+ former mutex owner to return to. */
+ next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
+ while (next_mutex != TX_NULL)
+ {
+
+ /* Does this mutex support priority inheritance? */
+ if (next_mutex -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Determine if highest priority field of the mutex is higher than the priority to
+ restore. */
+ if (next_mutex -> tx_mutex_highest_priority_waiting < inheritance_priority)
+ {
+
+ /* Use this priority to return releasing thread to. */
+ inheritance_priority = next_mutex -> tx_mutex_highest_priority_waiting;
+ }
+ }
+
+ /* Move mutex pointer to the next mutex in the list. */
+ next_mutex = next_mutex -> tx_mutex_owned_next;
+
+ /* Are we at the end of the list? */
+ if (next_mutex == thread_ptr -> tx_thread_owned_mutex_list)
+ {
+
+ /* Yes, set the next mutex to NULL. */
+ next_mutex = TX_NULL;
+ }
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Undo the temporarily preemption disable. */
+ _tx_thread_preempt_disable--;
+#endif
+
+ /* Set the inherit priority to that of the highest priority thread waiting on the mutex. */
+ thread_ptr -> tx_thread_inherit_priority = inheritance_priority;
+
+ /* Determine if the inheritance priority is less than the default old priority. */
+ if (inheritance_priority < old_priority)
+ {
+
+ /* Yes, update the old priority. */
+ old_priority = inheritance_priority;
+ }
+ }
+
+ /* Determine if priority inheritance is in effect and there are one or more
+ threads suspended on the mutex. */
+ if (mutex_ptr -> tx_mutex_suspended_count > ((UINT) 1))
+ {
+
+ /* Is priority inheritance in effect? */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Yes, this code is simply to ensure the highest priority thread is positioned
+ at the front of the suspension list. */
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Call the mutex prioritize processing to ensure the
+ highest priority thread is resumed. */
+#ifdef TX_MISRA_ENABLE
+ do
+ {
+ status = _tx_mutex_prioritize(mutex_ptr);
+ } while (status != TX_SUCCESS);
+#else
+ _tx_mutex_prioritize(mutex_ptr);
+#endif
+
+ /* At this point, the highest priority thread is at the
+ front of the suspension list. */
+
+ /* Optional processing extension. */
+ TX_MUTEX_PUT_EXTENSION_1
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Back off the preemption disable. */
+ _tx_thread_preempt_disable--;
+#endif
+ }
+ }
+
+ /* Now determine if there are any threads still waiting on the mutex. */
+ if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL)
+ {
+
+ /* No, there are no longer any threads waiting on the mutex. */
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Mutex is not owned, but it is possible that a thread that
+ caused a priority inheritance to occur is no longer waiting
+ on the mutex. */
+
+ /* Setup the highest priority waiting thread. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES;
+
+ /* Determine if we need to restore priority. */
+ if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority)
+ {
+
+ /* Yes, restore the priority of thread. */
+ _tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority);
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Back off the preemption disable. */
+ _tx_thread_preempt_disable--;
+#endif
+
+ /* Set the mutex owner to NULL. */
+ mutex_ptr -> tx_mutex_owner = TX_NULL;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Set status to success. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Pickup the thread at the front of the suspension list. */
+ thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
+
+ /* Save the previous ownership information, if inheritance is
+ in effect. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Remember the old mutex owner. */
+ old_owner = mutex_ptr -> tx_mutex_owner;
+
+ /* Setup owner thread priority information. */
+ mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority;
+
+ /* Setup the highest priority waiting thread. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES;
+ }
+
+ /* Determine how many mutexes are owned by this thread. */
+ owned_count = thread_ptr -> tx_thread_owned_mutex_count;
+
+ /* Determine if this thread owns any other mutexes that have priority inheritance. */
+ if (owned_count == ((UINT) 0))
+ {
+
+ /* The owned mutex list is empty. Add mutex to empty list. */
+ thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr;
+ mutex_ptr -> tx_mutex_owned_next = mutex_ptr;
+ mutex_ptr -> tx_mutex_owned_previous = mutex_ptr;
+ }
+ else
+ {
+
+ /* Non-empty list. Link up the mutex. */
+
+ /* Pickup tail pointer. */
+ next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
+ previous_mutex = next_mutex -> tx_mutex_owned_previous;
+
+ /* Place the owned mutex in the list. */
+ next_mutex -> tx_mutex_owned_previous = mutex_ptr;
+ previous_mutex -> tx_mutex_owned_next = mutex_ptr;
+
+ /* Setup this mutex's next and previous created links. */
+ mutex_ptr -> tx_mutex_owned_previous = previous_mutex;
+ mutex_ptr -> tx_mutex_owned_next = next_mutex;
+ }
+
+ /* Increment the number of mutexes owned counter. */
+ thread_ptr -> tx_thread_owned_mutex_count = owned_count + ((UINT) 1);
+
+ /* Mark the Mutex as owned and fill in the corresponding information. */
+ mutex_ptr -> tx_mutex_ownership_count = (UINT) 1;
+ mutex_ptr -> tx_mutex_owner = thread_ptr;
+
+ /* Remove the suspended thread from the list. */
+
+ /* Decrement the suspension count. */
+ mutex_ptr -> tx_mutex_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = mutex_ptr -> tx_mutex_suspended_count;
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ mutex_ptr -> tx_mutex_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Determine if priority inheritance is enabled for this mutex. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Yes, priority inheritance is requested. */
+
+ /* Determine if there are any more threads still suspended on the mutex. */
+ if (mutex_ptr -> tx_mutex_suspended_count != ((ULONG) 0))
+ {
+
+ /* Determine if there are more than one thread suspended on the mutex. */
+ if (mutex_ptr -> tx_mutex_suspended_count > ((ULONG) 1))
+ {
+
+ /* If so, prioritize the list so the highest priority thread is placed at the
+ front of the suspension list. */
+#ifdef TX_MISRA_ENABLE
+ do
+ {
+ status = _tx_mutex_prioritize(mutex_ptr);
+ } while (status != TX_SUCCESS);
+#else
+ _tx_mutex_prioritize(mutex_ptr);
+#endif
+ }
+
+ /* Now, pickup the list head and set the priority. */
+
+ /* Determine if there still are threads suspended for this mutex. */
+ suspended_thread = mutex_ptr -> tx_mutex_suspension_list;
+ if (suspended_thread != TX_NULL)
+ {
+
+ /* Setup the highest priority thread waiting on this mutex. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority;
+ }
+ }
+
+ /* Restore previous priority needs to be restored after priority
+ inheritance. */
+
+ /* Determine if we need to restore priority. */
+ if (old_owner -> tx_thread_priority != old_priority)
+ {
+
+ /* Restore priority of thread. */
+ _tx_mutex_priority_change(old_owner, old_priority);
+ }
+ }
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if priority inheritance is enabled for this mutex. */
+ if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+ {
+
+ /* Yes, priority inheritance is requested. */
+
+ /* Determine if there are any more threads still suspended on the mutex. */
+ if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Prioritize the list so the highest priority thread is placed at the
+ front of the suspension list. */
+#ifdef TX_MISRA_ENABLE
+ do
+ {
+ status = _tx_mutex_prioritize(mutex_ptr);
+ } while (status != TX_SUCCESS);
+#else
+ _tx_mutex_prioritize(mutex_ptr);
+#endif
+
+ /* Now, pickup the list head and set the priority. */
+
+ /* Optional processing extension. */
+ TX_MUTEX_PUT_EXTENSION_2
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if there still are threads suspended for this mutex. */
+ suspended_thread = mutex_ptr -> tx_mutex_suspension_list;
+ if (suspended_thread != TX_NULL)
+ {
+
+ /* Setup the highest priority thread waiting on this mutex. */
+ mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Restore previous priority needs to be restored after priority
+ inheritance. */
+
+ /* Is the priority different? */
+ if (old_owner -> tx_thread_priority != old_priority)
+ {
+
+ /* Restore the priority of thread. */
+ _tx_mutex_priority_change(old_owner, old_priority);
+ }
+ }
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Return a successful status. */
+ status = TX_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Caller does not own the mutex. */
+ status = TX_NOT_OWNED;
+ }
+
+ /* Return the completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_queue_cleanup.c b/common/src/tx_queue_cleanup.c
new file mode 100644
index 00000000..6583ec6e
--- /dev/null
+++ b/common/src/tx_queue_cleanup.c
@@ -0,0 +1,225 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes queue timeout and thread terminate */
+/* actions that require the queue data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_QUEUE *queue_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the queue. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_queue_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to queue control block. */
+ queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for NULL queue pointer. */
+ if (queue_ptr != TX_NULL)
+ {
+
+ /* Is the queue ID valid? */
+ if (queue_ptr -> tx_queue_id == TX_QUEUE_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to queue control block. */
+ queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Yes, we still have thread suspension! */
+
+ /* Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Decrement the suspended count. */
+ queue_ptr -> tx_queue_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (queue_ptr -> tx_queue_suspension_list == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+ }
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_QUEUE_SUSP)
+ {
+
+ /* Timeout condition and the thread still suspended on the queue.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_queue_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this queue. */
+ queue_ptr -> tx_queue_performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
+ {
+
+ /* Queue full timeout! */
+ thread_ptr -> tx_thread_suspend_status = TX_QUEUE_FULL;
+ }
+ else
+ {
+
+ /* Queue empty timeout! */
+ thread_ptr -> tx_thread_suspend_status = TX_QUEUE_EMPTY;
+ }
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_queue_create.c b/common/src/tx_queue_create.c
new file mode 100644
index 00000000..ae105019
--- /dev/null
+++ b/common/src/tx_queue_create.c
@@ -0,0 +1,170 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a message queue. The message size and depth */
+/* of the queue is specified by the caller. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* name_ptr Pointer to queue name */
+/* message_size Size of each queue message */
+/* queue_start Starting address of the queue area*/
+/* queue_size Number of bytes in the queue */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+ VOID *queue_start, ULONG queue_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT capacity;
+UINT used_words;
+TX_QUEUE *next_queue;
+TX_QUEUE *previous_queue;
+
+
+ /* Initialize queue control block to all zeros. */
+ TX_MEMSET(queue_ptr, 0, (sizeof(TX_QUEUE)));
+
+ /* Setup the basic queue fields. */
+ queue_ptr -> tx_queue_name = name_ptr;
+
+ /* Save the message size in the control block. */
+ queue_ptr -> tx_queue_message_size = message_size;
+
+ /* Determine how many messages will fit in the queue area and the number
+ of ULONGs used. */
+ capacity = (UINT) (queue_size / ((ULONG) (((ULONG) message_size) * (sizeof(ULONG)))));
+ used_words = capacity * message_size;
+
+ /* Save the starting address and calculate the ending address of
+ the queue. Note that the ending address is really one past the
+ end! */
+ queue_ptr -> tx_queue_start = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+ queue_ptr -> tx_queue_end = TX_ULONG_POINTER_ADD(queue_ptr -> tx_queue_start, used_words);
+
+ /* Set the read and write pointers to the beginning of the queue
+ area. */
+ queue_ptr -> tx_queue_read = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+ queue_ptr -> tx_queue_write = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+
+ /* Setup the number of enqueued messages and the number of message
+ slots available in the queue. */
+ queue_ptr -> tx_queue_available_storage = (UINT) capacity;
+ queue_ptr -> tx_queue_capacity = (UINT) capacity;
+
+ /* Disable interrupts to put the queue on the created list. */
+ TX_DISABLE
+
+ /* Setup the queue ID to make it valid. */
+ queue_ptr -> tx_queue_id = TX_QUEUE_ID;
+
+ /* Place the queue on the list of created queues. First,
+ check for an empty list. */
+ if (_tx_queue_created_count == TX_EMPTY)
+ {
+
+ /* The created queue list is empty. Add queue to empty list. */
+ _tx_queue_created_ptr = queue_ptr;
+ queue_ptr -> tx_queue_created_next = queue_ptr;
+ queue_ptr -> tx_queue_created_previous = queue_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_queue = _tx_queue_created_ptr;
+ previous_queue = next_queue -> tx_queue_created_previous;
+
+ /* Place the new queue in the list. */
+ next_queue -> tx_queue_created_previous = queue_ptr;
+ previous_queue -> tx_queue_created_next = queue_ptr;
+
+ /* Setup this queues's created links. */
+ queue_ptr -> tx_queue_created_previous = previous_queue;
+ queue_ptr -> tx_queue_created_next = next_queue;
+ }
+
+ /* Increment the created queue count. */
+ _tx_queue_created_count++;
+
+ /* Optional queue create extended processing. */
+ TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, name_ptr, queue_size, message_size)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_CREATE, queue_ptr, message_size, TX_POINTER_TO_ULONG_CONVERT(queue_start), queue_size, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_queue_delete.c b/common/src/tx_queue_delete.c
new file mode 100644
index 00000000..343af731
--- /dev/null
+++ b/common/src/tx_queue_delete.c
@@ -0,0 +1,206 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified queue. All threads suspended */
+/* on the queue are resumed with the TX_DELETED status code. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_delete(TX_QUEUE *queue_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+UINT suspended_count;
+TX_QUEUE *next_queue;
+TX_QUEUE *previous_queue;
+
+
+ /* Disable interrupts to remove the queue from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_DELETE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Optional queue delete extended processing. */
+ TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(queue_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_DELETE_INSERT
+
+ /* Clear the queue ID to make it invalid. */
+ queue_ptr -> tx_queue_id = TX_CLEAR_ID;
+
+ /* Decrement the number of created queues. */
+ _tx_queue_created_count--;
+
+ /* See if the queue is the only one on the list. */
+ if (_tx_queue_created_count == TX_EMPTY)
+ {
+
+ /* Only created queue, just set the created list to NULL. */
+ _tx_queue_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_queue = queue_ptr -> tx_queue_created_next;
+ previous_queue = queue_ptr -> tx_queue_created_previous;
+ next_queue -> tx_queue_created_previous = previous_queue;
+ previous_queue -> tx_queue_created_next = next_queue;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_queue_created_ptr == queue_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_queue_created_ptr = next_queue;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = queue_ptr -> tx_queue_suspension_list;
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+ queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the queue list to resume any and all threads suspended
+ on this queue. */
+ while (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_QUEUE_DELETE_PORT_COMPLETION(queue_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_queue_flush.c b/common/src/tx_queue_flush.c
new file mode 100644
index 00000000..ca338e8a
--- /dev/null
+++ b/common/src/tx_queue_flush.c
@@ -0,0 +1,205 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_flush PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function resets the specified queue, if there are any messages */
+/* in it. Messages waiting to be placed on the queue are also thrown */
+/* out. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_flush(TX_QUEUE *queue_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *suspension_list;
+UINT suspended_count;
+TX_THREAD *thread_ptr;
+
+
+ /* Initialize the suspended count and list. */
+ suspended_count = TX_NO_SUSPENSIONS;
+ suspension_list = TX_NULL;
+
+ /* Disable interrupts to reset various queue parameters. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FLUSH, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_FLUSH_INSERT
+
+ /* Determine if there is something on the queue. */
+ if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
+ {
+
+ /* Yes, there is something in the queue. */
+
+ /* Reset the queue parameters to erase all of the queued messages. */
+ queue_ptr -> tx_queue_enqueued = TX_NO_MESSAGES;
+ queue_ptr -> tx_queue_available_storage = queue_ptr -> tx_queue_capacity;
+ queue_ptr -> tx_queue_read = queue_ptr -> tx_queue_start;
+ queue_ptr -> tx_queue_write = queue_ptr -> tx_queue_start;
+
+ /* Now determine if there are any threads suspended on a full queue. */
+ if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, there are threads suspended on this queue, they must be
+ resumed! */
+
+ /* Copy the information into temporary variables. */
+ suspension_list = queue_ptr -> tx_queue_suspension_list;
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Clear the queue variables. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the queue list to resume any and all threads suspended
+ on this queue. */
+ if (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Pickup the thread to resume. */
+ thread_ptr = suspension_list;
+ while (suspended_count != ((ULONG) 0))
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Check for a NULL thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Get out of the loop. */
+ break;
+ }
+
+ /* Resume the next suspended thread. */
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_SUCCESS. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+ /* Move the thread pointer ahead. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr -> tx_thread_suspended_previous);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr -> tx_thread_suspended_previous);
+#endif
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Restore previous preempt posture. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_queue_front_send.c b/common/src/tx_queue_front_send.c
new file mode 100644
index 00000000..3becd09d
--- /dev/null
+++ b/common/src/tx_queue_front_send.c
@@ -0,0 +1,421 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_front_send PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places a message at the front of the specified queue. */
+/* If there is no room in the queue, this function returns the */
+/* queue full status. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* source_ptr Pointer to message source */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread routine */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_thread_system_suspend Suspend thread routine */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+ULONG *source;
+ULONG *destination;
+UINT size;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr);
+#endif
+
+
+ /* Default the status to TX_SUCCESS. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts to place message in the queue. */
+ TX_DISABLE
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total messages sent counter. */
+ _tx_queue_performance_messages_sent_count++;
+
+ /* Increment the number of messages sent to this queue. */
+ queue_ptr -> tx_queue_performance_messages_sent_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FRONT_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_FRONT_SEND_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Now check for room in the queue for placing the new message in front. */
+ if (queue_ptr -> tx_queue_available_storage != ((UINT) 0))
+ {
+
+ /* Yes there is room in the queue. Now determine if there is a thread waiting
+ for a message. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No thread suspended while waiting for a message from
+ this queue. */
+
+ /* Adjust the read pointer since we are adding to the front of the
+ queue. */
+
+ /* See if the read pointer is at the beginning of the queue area. */
+ if (queue_ptr -> tx_queue_read == queue_ptr -> tx_queue_start)
+ {
+
+ /* Adjust the read pointer to the last message at the end of the
+ queue. */
+ queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_end, queue_ptr -> tx_queue_message_size);
+ }
+ else
+ {
+
+ /* Not at the beginning of the queue, just move back one message. */
+ queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_read, queue_ptr -> tx_queue_message_size);
+ }
+
+ /* Simply place the message in the queue. */
+
+ /* Reduce the amount of available storage. */
+ queue_ptr -> tx_queue_available_storage--;
+
+ /* Increase the enqueued count. */
+ queue_ptr -> tx_queue_enqueued++;
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+ destination = queue_ptr -> tx_queue_read;
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+#endif
+ }
+ else
+ {
+
+ /* Thread suspended waiting for a message. Remove it and copy this message
+ into its storage area. */
+ thread_ptr = queue_ptr -> tx_queue_suspension_list;
+
+ /* See if this is the only suspended thread on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next;
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+ destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+#endif
+ }
+ }
+
+ /* Determine if the caller has requested suspension. */
+ else if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_QUEUE_FULL;
+ }
+ else
+ {
+
+ /* Yes, suspension is requested. */
+
+ /* Prepare for suspension of this thread. */
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
+
+ /* Setup cleanup information, i.e. this queue control
+ block and the source pointer. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr;
+
+ /* Set the flag to true to indicate a queue front send suspension. */
+ thread_ptr -> tx_thread_suspend_option = TX_TRUE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Place this thread at the front of the suspension list, since it is a
+ queue front send suspension. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = queue_ptr -> tx_queue_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+
+ /* Update the suspension list to put this thread in front, which will put
+ the message that was removed in the proper relative order when room is
+ made in the queue. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr;
+ }
+
+ /* Increment the suspended thread count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS)
+ {
+
+ /* Check for a notify callback. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+ }
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* No room in queue and no suspension requested, return error completion. */
+ status = TX_QUEUE_FULL;
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_queue_info_get.c b/common/src/tx_queue_info_get.c
new file mode 100644
index 00000000..e0496929
--- /dev/null
+++ b/common/src/tx_queue_info_get.c
@@ -0,0 +1,145 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified queue. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* name Destination for the queue name */
+/* enqueued Destination for enqueued count */
+/* available_storage Destination for available storage */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on this queue */
+/* suspended_count Destination for suspended count */
+/* next_queue Destination for pointer to next */
+/* queue on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
+ TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the queue. */
+ if (name != TX_NULL)
+ {
+
+ *name = queue_ptr -> tx_queue_name;
+ }
+
+ /* Retrieve the number of messages currently in the queue. */
+ if (enqueued != TX_NULL)
+ {
+
+ *enqueued = (ULONG) queue_ptr -> tx_queue_enqueued;
+ }
+
+ /* Retrieve the number of messages that will still fit in the queue. */
+ if (available_storage != TX_NULL)
+ {
+
+ *available_storage = (ULONG) queue_ptr -> tx_queue_available_storage;
+ }
+
+ /* Retrieve the first thread suspended on this queue. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = queue_ptr -> tx_queue_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this queue. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) queue_ptr -> tx_queue_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next queue created. */
+ if (next_queue != TX_NULL)
+ {
+
+ *next_queue = queue_ptr -> tx_queue_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_queue_initialize.c b/common/src/tx_queue_initialize.c
new file mode 100644
index 00000000..0e9bb622
--- /dev/null
+++ b/common/src/tx_queue_initialize.c
@@ -0,0 +1,138 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Define the head pointer of the created queue list. */
+
+TX_QUEUE * _tx_queue_created_ptr;
+
+
+/* Define the variable that holds the number of created queues. */
+
+ULONG _tx_queue_created_count;
+
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of messages sent. */
+
+ULONG _tx_queue_performance_messages_sent_count;
+
+
+/* Define the total number of messages received. */
+
+ULONG _tx_queue_performance__messages_received_count;
+
+
+/* Define the total number of queue empty suspensions. */
+
+ULONG _tx_queue_performance_empty_suspension_count;
+
+
+/* Define the total number of queue full suspensions. */
+
+ULONG _tx_queue_performance_full_suspension_count;
+
+
+/* Define the total number of queue full errors. */
+
+ULONG _tx_queue_performance_full_error_count;
+
+
+/* Define the total number of queue timeouts. */
+
+ULONG _tx_queue_performance_timeout_count;
+
+#endif
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the queue component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_queue_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created queue list and the
+ number of queues created. */
+ _tx_queue_created_ptr = TX_NULL;
+ _tx_queue_created_count = TX_EMPTY;
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize the queue performance counters. */
+ _tx_queue_performance_messages_sent_count = ((ULONG) 0);
+ _tx_queue_performance__messages_received_count = ((ULONG) 0);
+ _tx_queue_performance_empty_suspension_count = ((ULONG) 0);
+ _tx_queue_performance_full_suspension_count = ((ULONG) 0);
+ _tx_queue_performance_timeout_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_queue_performance_info_get.c b/common/src/tx_queue_performance_info_get.c
new file mode 100644
index 00000000..48d561b4
--- /dev/null
+++ b/common/src/tx_queue_performance_info_get.c
@@ -0,0 +1,229 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* queue. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* messages_sent Destination for messages sent */
+/* messages_received Destination for messages received */
+/* empty_suspensions Destination for number of empty */
+/* queue suspensions */
+/* full_suspensions Destination for number of full */
+/* queue suspensions */
+/* full_errors Destination for queue full errors */
+/* returned - no suspension */
+/* timeouts Destination for number of timeouts*/
+/* on this queue */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received,
+ ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts)
+{
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the queue ID is invalid. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of messages sent to this queue. */
+ if (messages_sent != TX_NULL)
+ {
+
+ *messages_sent = queue_ptr -> tx_queue_performance_messages_sent_count;
+ }
+
+ /* Retrieve the number of messages received from this queue. */
+ if (messages_received != TX_NULL)
+ {
+
+ *messages_received = queue_ptr -> tx_queue_performance_messages_received_count;
+ }
+
+ /* Retrieve the number of empty queue suspensions on this queue. */
+ if (empty_suspensions != TX_NULL)
+ {
+
+ *empty_suspensions = queue_ptr -> tx_queue_performance_empty_suspension_count;
+ }
+
+ /* Retrieve the number of full queue suspensions on this queue. */
+ if (full_suspensions != TX_NULL)
+ {
+
+ *full_suspensions = queue_ptr -> tx_queue_performance_full_suspension_count;
+ }
+
+ /* Retrieve the number of full errors (no suspension!) on this queue. */
+ if (full_errors != TX_NULL)
+ {
+
+ *full_errors = queue_ptr -> tx_queue_performance_full_error_count;
+ }
+
+ /* Retrieve the number of timeouts on this queue. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = queue_ptr -> tx_queue_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (queue_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (messages_sent != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (messages_received != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (empty_suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (full_suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (full_errors != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_queue_performance_system_info_get.c b/common/src/tx_queue_performance_system_info_get.c
new file mode 100644
index 00000000..ebc58815
--- /dev/null
+++ b/common/src/tx_queue_performance_system_info_get.c
@@ -0,0 +1,205 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves queue system performance information. */
+/* */
+/* INPUT */
+/* */
+/* messages_sent Destination for total messages */
+/* sent */
+/* messages_received Destination for total messages */
+/* received */
+/* empty_suspensions Destination for total empty */
+/* queue suspensions */
+/* full_suspensions Destination for total full */
+/* queue suspensions */
+/* full_errors Destination for total queue full */
+/* errors returned - no suspension */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_performance_system_info_get(ULONG *messages_sent, ULONG *messages_received,
+ ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts)
+{
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of queue messages sent. */
+ if (messages_sent != TX_NULL)
+ {
+
+ *messages_sent = _tx_queue_performance_messages_sent_count;
+ }
+
+ /* Retrieve the total number of queue messages received. */
+ if (messages_received != TX_NULL)
+ {
+
+ *messages_received = _tx_queue_performance__messages_received_count;
+ }
+
+ /* Retrieve the total number of empty queue suspensions. */
+ if (empty_suspensions != TX_NULL)
+ {
+
+ *empty_suspensions = _tx_queue_performance_empty_suspension_count;
+ }
+
+ /* Retrieve the total number of full queue suspensions. */
+ if (full_suspensions != TX_NULL)
+ {
+
+ *full_suspensions = _tx_queue_performance_full_suspension_count;
+ }
+
+ /* Retrieve the total number of full errors. */
+ if (full_errors != TX_NULL)
+ {
+
+ *full_errors = _tx_queue_performance_full_error_count;
+ }
+
+ /* Retrieve the total number of queue timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_queue_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (messages_sent != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (messages_received != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (empty_suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (full_suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (full_errors != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_queue_prioritize.c b/common/src/tx_queue_prioritize.c
new file mode 100644
index 00000000..632e03b6
--- /dev/null
+++ b/common/src/tx_queue_prioritize.c
@@ -0,0 +1,249 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the highest priority suspended thread at the */
+/* front of the suspension list. All other threads remain in the same */
+/* FIFO suspension order. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_prioritize(TX_QUEUE *queue_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *priority_thread_ptr;
+TX_THREAD *head_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT list_changed;
+
+
+ /* Disable interrupts to place message in the queue. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PRIORITIZE, queue_ptr, queue_ptr -> tx_queue_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_PRIORITIZE_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Determine if there are fewer than 2 suspended threads. */
+ if (suspended_count < ((UINT) 2))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if there how many threads are suspended on this queue. */
+ else if (suspended_count == ((UINT) 2))
+ {
+
+ /* Pickup the head pointer and the next pointer. */
+ head_ptr = queue_ptr -> tx_queue_suspension_list;
+ next_thread = head_ptr -> tx_thread_suspended_next;
+
+ /* Determine if the next suspended thread has a higher priority. */
+ if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
+ {
+
+ /* Yes, move the list head to the next thread. */
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = queue_ptr -> tx_queue_suspension_list;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the list changed flag to false. */
+ list_changed = TX_FALSE;
+
+ /* Search through the list to find the highest priority thread. */
+ do
+ {
+
+ /* Is the current thread higher priority? */
+ if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, remember that this thread is the highest priority. */
+ priority_thread_ptr = thread_ptr;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Determine if any changes to the list have occurred while
+ interrupts were enabled. */
+
+ /* Is the list head the same? */
+ if (head_ptr != queue_ptr -> tx_queue_suspension_list)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ else
+ {
+
+ /* Is the suspended count the same? */
+ if (suspended_count != queue_ptr -> tx_queue_suspended_count)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ }
+
+ /* Determine if the list has changed. */
+ if (list_changed == TX_FALSE)
+ {
+
+ /* Move the thread pointer to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+ }
+ else
+ {
+
+ /* Save the suspension count and head pointer. */
+ head_ptr = queue_ptr -> tx_queue_suspension_list;
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Reset the list changed flag. */
+ list_changed = TX_FALSE;
+ }
+
+ } while (thread_ptr != head_ptr);
+
+ /* Release preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Now determine if the highest priority thread is at the front
+ of the list. */
+ if (priority_thread_ptr != head_ptr)
+ {
+
+ /* No, we need to move the highest priority suspended thread to the
+ front of the list. */
+
+ /* First, remove the highest priority thread by updating the
+ adjacent suspended threads. */
+ next_thread = priority_thread_ptr -> tx_thread_suspended_next;
+ previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Now, link the highest priority thread at the front of the list. */
+ previous_thread = head_ptr -> tx_thread_suspended_previous;
+ priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
+ priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
+ head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
+
+ /* Move the list head pointer to the highest priority suspended thread. */
+ queue_ptr -> tx_queue_suspension_list = priority_thread_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return successful status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_queue_receive.c b/common/src/tx_queue_receive.c
new file mode 100644
index 00000000..72555df8
--- /dev/null
+++ b/common/src/tx_queue_receive.c
@@ -0,0 +1,486 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_receive PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function receives a message from the specified queue. If there */
+/* are no messages in the queue, this function waits according to the */
+/* option specified. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* destination_ptr Pointer to message destination */
+/* **** MUST BE LARGE ENOUGH TO */
+/* HOLD MESSAGE **** */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread routine */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_thread_system_suspend Suspend thread routine */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+ULONG *source;
+ULONG *destination;
+UINT size;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+
+
+ /* Default the status to TX_SUCCESS. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts to receive message from queue. */
+ TX_DISABLE
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total messages received counter. */
+ _tx_queue_performance__messages_received_count++;
+
+ /* Increment the number of messages received from this queue. */
+ queue_ptr -> tx_queue_performance_messages_received_count++;
+
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_RECEIVE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(destination_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_RECEIVE_INSERT
+
+ /* Pickup the thread suspension count. */
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Determine if there is anything in the queue. */
+ if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
+ {
+
+ /* Determine if there are any suspensions. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* There is a message waiting in the queue and there are no suspensi. */
+
+ /* Setup source and destination pointers. */
+ source = queue_ptr -> tx_queue_read;
+ destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Determine if we are at the end. */
+ if (source == queue_ptr -> tx_queue_end)
+ {
+
+ /* Yes, wrap around to the beginning. */
+ source = queue_ptr -> tx_queue_start;
+ }
+
+ /* Setup the queue read pointer. */
+ queue_ptr -> tx_queue_read = source;
+
+ /* Increase the amount of available storage. */
+ queue_ptr -> tx_queue_available_storage++;
+
+ /* Decrease the enqueued count. */
+ queue_ptr -> tx_queue_enqueued--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* At this point we know the queue is full. */
+
+ /* Pickup thread suspension list head pointer. */
+ thread_ptr = queue_ptr -> tx_queue_suspension_list;
+
+ /* Now determine if there is a queue front suspension active. */
+
+ /* Is the front suspension flag set? */
+ if (thread_ptr -> tx_thread_suspend_option == TX_TRUE)
+ {
+
+ /* Yes, a queue front suspension is present. */
+
+ /* Return the message associated with this suspension. */
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Message is now in the caller's destination. See if this is the only suspended thread
+ on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+ }
+ else
+ {
+
+ /* At this point, we know that the queue is full and there
+ are one or more threads suspended trying to send another
+ message to this queue. */
+
+ /* Setup source and destination pointers. */
+ source = queue_ptr -> tx_queue_read;
+ destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Determine if we are at the end. */
+ if (source == queue_ptr -> tx_queue_end)
+ {
+
+ /* Yes, wrap around to the beginning. */
+ source = queue_ptr -> tx_queue_start;
+ }
+
+ /* Setup the queue read pointer. */
+ queue_ptr -> tx_queue_read = source;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Interrupts are enabled briefly here to keep the interrupt
+ lockout time deterministic. */
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+#endif
+
+ /* Decrement the preemption disable variable. */
+ _tx_thread_preempt_disable--;
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ destination = queue_ptr -> tx_queue_write;
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Determine if we are at the end. */
+ if (destination == queue_ptr -> tx_queue_end)
+ {
+
+ /* Yes, wrap around to the beginning. */
+ destination = queue_ptr -> tx_queue_start;
+ }
+
+ /* Adjust the write pointer. */
+ queue_ptr -> tx_queue_write = destination;
+
+ /* Pickup thread pointer. */
+ thread_ptr = queue_ptr -> tx_queue_suspension_list;
+
+ /* Message is now in the queue. See if this is the only suspended thread
+ on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+ }
+ }
+ }
+
+ /* Determine if the request specifies suspension. */
+ else if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_QUEUE_EMPTY;
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total queue empty suspensions counter. */
+ _tx_queue_performance_empty_suspension_count++;
+
+ /* Increment the number of empty suspensions on this queue. */
+ queue_ptr -> tx_queue_performance_empty_suspension_count++;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
+
+ /* Setup cleanup information, i.e. this queue control
+ block and the source pointer. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) destination_ptr;
+ thread_ptr -> tx_thread_suspend_option = TX_FALSE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Setup suspension list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = queue_ptr -> tx_queue_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Increment the suspended thread count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Immediate return, return error completion. */
+ status = TX_QUEUE_EMPTY;
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_queue_send.c b/common/src/tx_queue_send.c
new file mode 100644
index 00000000..4d242947
--- /dev/null
+++ b/common/src/tx_queue_send.c
@@ -0,0 +1,426 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_send PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places a message into the specified queue. If there */
+/* is no room in the queue, this function waits according to the */
+/* option specified. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* source_ptr Pointer to message source */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread routine */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_thread_system_suspend Suspend thread routine */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+ULONG *source;
+ULONG *destination;
+UINT size;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr);
+#endif
+
+
+ /* Default the status to TX_SUCCESS. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts to place message in the queue. */
+ TX_DISABLE
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total messages sent counter. */
+ _tx_queue_performance_messages_sent_count++;
+
+ /* Increment the number of messages sent to this queue. */
+ queue_ptr -> tx_queue_performance_messages_sent_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_QUEUE_SEND_INSERT
+
+ /* Pickup the thread suspension count. */
+ suspended_count = queue_ptr -> tx_queue_suspended_count;
+
+ /* Determine if there is room in the queue. */
+ if (queue_ptr -> tx_queue_available_storage != TX_NO_MESSAGES)
+ {
+
+ /* There is room for the message in the queue. */
+
+ /* Determine if there are suspended on this queue. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No suspended threads, simply place the message in the queue. */
+
+ /* Reduce the amount of available storage. */
+ queue_ptr -> tx_queue_available_storage--;
+
+ /* Increase the enqueued count. */
+ queue_ptr -> tx_queue_enqueued++;
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+ destination = queue_ptr -> tx_queue_write;
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Determine if we are at the end. */
+ if (destination == queue_ptr -> tx_queue_end)
+ {
+
+ /* Yes, wrap around to the beginning. */
+ destination = queue_ptr -> tx_queue_start;
+ }
+
+ /* Adjust the write pointer. */
+ queue_ptr -> tx_queue_write = destination;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+ /* No thread suspended, just return to caller. */
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+#endif
+ }
+ else
+ {
+
+ /* There is a thread suspended on an empty queue. Simply
+ copy the message to the suspended thread's destination
+ pointer. */
+
+ /* Pickup the head of the suspension list. */
+ thread_ptr = queue_ptr -> tx_queue_suspension_list;
+
+ /* See if this is the only suspended thread on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ queue_ptr -> tx_queue_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next;
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ queue_ptr -> tx_queue_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Setup source and destination pointers. */
+ source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+ destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+ size = queue_ptr -> tx_queue_message_size;
+
+ /* Copy message. Note that the source and destination pointers are
+ incremented by the macro. */
+ TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+#endif
+ }
+ }
+
+ /* At this point, the queue is full. Determine if suspension is requested. */
+ else if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_QUEUE_FULL;
+ }
+ else
+ {
+
+ /* Yes, prepare for suspension of this thread. */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total number of queue full suspensions. */
+ _tx_queue_performance_full_suspension_count++;
+
+ /* Increment the number of full suspensions on this queue. */
+ queue_ptr -> tx_queue_performance_full_suspension_count++;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
+
+ /* Setup cleanup information, i.e. this queue control
+ block and the source pointer. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
+ thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr;
+ thread_ptr -> tx_thread_suspend_option = TX_FALSE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Setup suspension list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ queue_ptr -> tx_queue_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = queue_ptr -> tx_queue_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Increment the suspended thread count. */
+ queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the notify callback routine for this queue. */
+ queue_send_notify = queue_ptr -> tx_queue_send_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if a notify callback is required. */
+ if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS)
+ {
+
+ /* Determine if there is a notify callback. */
+ if (queue_send_notify != TX_NULL)
+ {
+
+ /* Call application queue send notification. */
+ (queue_send_notify)(queue_ptr);
+ }
+ }
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Otherwise, just return a queue full error message to the caller. */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the number of full non-suspensions on this queue. */
+ queue_ptr -> tx_queue_performance_full_error_count++;
+
+ /* Increment the total number of full non-suspensions. */
+ _tx_queue_performance_full_error_count++;
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return error completion. */
+ status = TX_QUEUE_FULL;
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_queue_send_notify.c b/common/src/tx_queue_send_notify.c
new file mode 100644
index 00000000..67b26dea
--- /dev/null
+++ b/common/src/tx_queue_send_notify.c
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_queue_send_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application callback function that is */
+/* called whenever a messages is sent to this queue. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block*/
+/* queue_send_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr))
+{
+
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+
+ TX_QUEUE_NOT_USED(queue_ptr);
+ TX_QUEUE_SEND_NOTIFY_NOT_USED(queue_send_notify);
+
+ /* Feature is not enabled, return error. */
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Make entry in event log. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND_NOTIFY, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
+
+ /* Make entry in event log. */
+ TX_EL_QUEUE_SEND_NOTIFY_INSERT
+
+ /* Setup queue send notification callback function. */
+ queue_ptr -> tx_queue_send_notify = queue_send_notify;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success to caller. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_semaphore_ceiling_put.c b/common/src/tx_semaphore_ceiling_put.c
new file mode 100644
index 00000000..7b101228
--- /dev/null
+++ b/common/src/tx_semaphore_ceiling_put.c
@@ -0,0 +1,243 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_ceiling_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function puts an instance into the specified counting */
+/* semaphore up to the specified semaphore ceiling. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore */
+/* ceiling Maximum value of semaphore */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume */
+/* thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr);
+#endif
+
+TX_THREAD *thread_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+
+
+ /* Default the status to TX_SUCCESS. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts to put an instance back to the semaphore. */
+ TX_DISABLE
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total semaphore put counter. */
+ _tx_semaphore_performance_put_count++;
+
+ /* Increment the number of puts on this semaphore. */
+ semaphore_ptr -> tx_semaphore_performance_put_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, ceiling, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_CEILING_PUT_INSERT
+
+ /* Pickup the number of suspended threads. */
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+
+ /* Determine if there are any threads suspended on the semaphore. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Determine if the ceiling has been exceeded. */
+ if (semaphore_ptr -> tx_semaphore_count >= ceiling)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return an error. */
+ status = TX_CEILING_EXCEEDED;
+ }
+ else
+ {
+
+ /* Increment the semaphore count. */
+ semaphore_ptr -> tx_semaphore_count++;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the application notify function. */
+ semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if notification is required. */
+ if (semaphore_put_notify != TX_NULL)
+ {
+
+ /* Yes, call the appropriate notify callback function. */
+ (semaphore_put_notify)(semaphore_ptr);
+ }
+#endif
+
+ /* Return successful completion status. */
+ status = TX_SUCCESS;
+ }
+ }
+ else
+ {
+
+ /* Remove the suspended thread from the list. */
+
+ /* Pickup the pointer to the first suspended thread. */
+ thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+
+ /* See if this is the only suspended thread on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ semaphore_ptr -> tx_semaphore_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the application notify function. */
+ semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if notification is required. */
+ if (semaphore_put_notify != TX_NULL)
+ {
+
+ /* Yes, call the appropriate notify callback function. */
+ (semaphore_put_notify)(semaphore_ptr);
+ }
+#endif
+ }
+
+ /* Return successful completion. */
+ return(status);
+}
+
diff --git a/common/src/tx_semaphore_cleanup.c b/common/src/tx_semaphore_cleanup.c
new file mode 100644
index 00000000..498f9d7d
--- /dev/null
+++ b/common/src/tx_semaphore_cleanup.c
@@ -0,0 +1,215 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_cleanup PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes semaphore timeout and thread terminate */
+/* actions that require the semaphore data structures to be cleaned */
+/* up. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to suspended thread's */
+/* control block */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_timeout Thread timeout processing */
+/* _tx_thread_terminate Thread terminate processing */
+/* _tx_thread_wait_abort Thread wait abort processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_SEMAPHORE *semaphore_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts to remove the suspended thread from the semaphore. */
+ TX_DISABLE
+
+ /* Determine if the cleanup is still required. */
+ if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_semaphore_cleanup))
+ {
+
+ /* Check for valid suspension sequence. */
+ if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+ {
+
+ /* Setup pointer to semaphore control block. */
+ semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+ /* Check for a NULL semaphore pointer. */
+ if (semaphore_ptr != TX_NULL)
+ {
+
+ /* Check for a valid semaphore ID. */
+ if (semaphore_ptr -> tx_semaphore_id == TX_SEMAPHORE_ID)
+ {
+
+ /* Determine if there are any thread suspensions. */
+ if (semaphore_ptr -> tx_semaphore_suspended_count != TX_NO_SUSPENSIONS)
+ {
+#else
+
+ /* Setup pointer to semaphore control block. */
+ semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+ /* Yes, we still have thread suspension! */
+
+ /* Clear the suspension cleanup flag. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Decrement the suspended count. */
+ semaphore_ptr -> tx_semaphore_suspended_count--;
+
+ /* Pickup the suspended count. */
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same suspension list. */
+
+ /* Update the links of the adjacent threads. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Determine if we need to update the head pointer. */
+ if (semaphore_ptr -> tx_semaphore_suspension_list == thread_ptr)
+ {
+
+ /* Update the list head pointer. */
+ semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
+ }
+ }
+
+ /* Now we need to determine if this cleanup is from a terminate, timeout,
+ or from a wait abort. */
+ if (thread_ptr -> tx_thread_state == TX_SEMAPHORE_SUSP)
+ {
+
+ /* Timeout condition and the thread is still suspended on the semaphore.
+ Setup return error status and resume the thread. */
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total timeouts counter. */
+ _tx_semaphore_performance_timeout_count++;
+
+ /* Increment the number of timeouts on this semaphore. */
+ semaphore_ptr -> tx_semaphore_performance_timeout_count++;
+#endif
+
+ /* Setup return status. */
+ thread_ptr -> tx_thread_suspend_status = TX_NO_INSTANCE;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread! */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+#ifndef TX_NOT_INTERRUPTABLE
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_semaphore_create.c b/common/src/tx_semaphore_create.c
new file mode 100644
index 00000000..377a7777
--- /dev/null
+++ b/common/src/tx_semaphore_create.c
@@ -0,0 +1,142 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a counting semaphore with the initial count */
+/* specified in this call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* name_ptr Pointer to semaphore name */
+/* initial_count Initial semaphore count */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_SEMAPHORE *next_semaphore;
+TX_SEMAPHORE *previous_semaphore;
+
+
+ /* Initialize semaphore control block to all zeros. */
+ TX_MEMSET(semaphore_ptr, 0, (sizeof(TX_SEMAPHORE)));
+
+ /* Setup the basic semaphore fields. */
+ semaphore_ptr -> tx_semaphore_name = name_ptr;
+ semaphore_ptr -> tx_semaphore_count = initial_count;
+
+ /* Disable interrupts to place the semaphore on the created list. */
+ TX_DISABLE
+
+ /* Setup the semaphore ID to make it valid. */
+ semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID;
+
+ /* Place the semaphore on the list of created semaphores. First,
+ check for an empty list. */
+ if (_tx_semaphore_created_count == TX_EMPTY)
+ {
+
+ /* The created semaphore list is empty. Add semaphore to empty list. */
+ _tx_semaphore_created_ptr = semaphore_ptr;
+ semaphore_ptr -> tx_semaphore_created_next = semaphore_ptr;
+ semaphore_ptr -> tx_semaphore_created_previous = semaphore_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_semaphore = _tx_semaphore_created_ptr;
+ previous_semaphore = next_semaphore -> tx_semaphore_created_previous;
+
+ /* Place the new semaphore in the list. */
+ next_semaphore -> tx_semaphore_created_previous = semaphore_ptr;
+ previous_semaphore -> tx_semaphore_created_next = semaphore_ptr;
+
+ /* Setup this semaphore's next and previous created links. */
+ semaphore_ptr -> tx_semaphore_created_previous = previous_semaphore;
+ semaphore_ptr -> tx_semaphore_created_next = next_semaphore;
+ }
+
+ /* Increment the created count. */
+ _tx_semaphore_created_count++;
+
+ /* Optional semaphore create extended processing. */
+ TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, name_ptr, initial_count, 0)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CREATE, semaphore_ptr, initial_count, TX_POINTER_TO_ULONG_CONVERT(&next_semaphore), 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_CREATE_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_semaphore_delete.c b/common/src/tx_semaphore_delete.c
new file mode 100644
index 00000000..a8297463
--- /dev/null
+++ b/common/src/tx_semaphore_delete.c
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified semaphore. All threads */
+/* suspended on the semaphore are resumed with the TX_DELETED status */
+/* code. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+UINT suspended_count;
+TX_SEMAPHORE *next_semaphore;
+TX_SEMAPHORE *previous_semaphore;
+
+
+ /* Disable interrupts to remove the semaphore from the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_DELETE, semaphore_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Optional semaphore delete extended processing. */
+ TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(semaphore_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_DELETE_INSERT
+
+ /* Clear the semaphore ID to make it invalid. */
+ semaphore_ptr -> tx_semaphore_id = TX_CLEAR_ID;
+
+ /* Decrement the number of semaphores. */
+ _tx_semaphore_created_count--;
+
+ /* See if the semaphore is the only one on the list. */
+ if (_tx_semaphore_created_count == TX_EMPTY)
+ {
+
+ /* Only created semaphore, just set the created list to NULL. */
+ _tx_semaphore_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_semaphore = semaphore_ptr -> tx_semaphore_created_next;
+ previous_semaphore = semaphore_ptr -> tx_semaphore_created_previous;
+ next_semaphore -> tx_semaphore_created_previous = previous_semaphore;
+ previous_semaphore -> tx_semaphore_created_next = next_semaphore;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_semaphore_created_ptr == semaphore_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_semaphore_created_ptr = next_semaphore;
+ }
+ }
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Pickup the suspension information. */
+ thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+ semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+ semaphore_ptr -> tx_semaphore_suspended_count = TX_NO_SUSPENSIONS;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Walk through the semaphore list to resume any and all threads suspended
+ on this semaphore. */
+ while (suspended_count != TX_NO_SUSPENSIONS)
+ {
+
+ /* Decrement the suspension count. */
+ suspended_count--;
+
+ /* Lockout interrupts. */
+ TX_DISABLE
+
+ /* Clear the cleanup pointer, this prevents the timeout from doing
+ anything. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+ /* Set the return status in the thread to TX_DELETED. */
+ thread_ptr -> tx_thread_suspend_status = TX_DELETED;
+
+ /* Move the thread pointer ahead. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption again. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Move to next thread. */
+ thread_ptr = next_thread;
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_SEMAPHORE_DELETE_PORT_COMPLETION(semaphore_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release previous preempt disable. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_semaphore_get.c b/common/src/tx_semaphore_get.c
new file mode 100644
index 00000000..9e1072dc
--- /dev/null
+++ b/common/src/tx_semaphore_get.c
@@ -0,0 +1,232 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets an instance from the specified counting */
+/* semaphore. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Suspend thread service */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+
+
+ /* Default the status to TX_SUCCESS. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts to get an instance from the semaphore. */
+ TX_DISABLE
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total semaphore get counter. */
+ _tx_semaphore_performance_get_count++;
+
+ /* Increment the number of attempts to get this semaphore. */
+ semaphore_ptr -> tx_semaphore_performance_get_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_GET, semaphore_ptr, wait_option, semaphore_ptr -> tx_semaphore_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_GET_INSERT
+
+ /* Determine if there is an instance of the semaphore. */
+ if (semaphore_ptr -> tx_semaphore_count != ((ULONG) 0))
+ {
+
+ /* Decrement the semaphore count. */
+ semaphore_ptr -> tx_semaphore_count--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if the request specifies suspension. */
+ else if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_NO_INSTANCE;
+ }
+ else
+ {
+
+ /* Prepare for suspension of this thread. */
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total semaphore suspensions counter. */
+ _tx_semaphore_performance_suspension_count++;
+
+ /* Increment the number of suspensions on this semaphore. */
+ semaphore_ptr -> tx_semaphore_performance_suspension_count++;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Setup cleanup routine pointer. */
+ thread_ptr -> tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
+
+ /* Setup cleanup information, i.e. this semaphore control
+ block. */
+ thread_ptr -> tx_thread_suspend_control_block = (VOID *) semaphore_ptr;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the suspension sequence number, which is used to identify
+ this suspension event. */
+ thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+ /* Setup suspension list. */
+ if (semaphore_ptr -> tx_semaphore_suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* No other threads are suspended. Setup the head pointer and
+ just setup this threads pointers to itself. */
+ semaphore_ptr -> tx_semaphore_suspension_list = thread_ptr;
+ thread_ptr -> tx_thread_suspended_next = thread_ptr;
+ thread_ptr -> tx_thread_suspended_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current thread to the end. */
+ next_thread = semaphore_ptr -> tx_semaphore_suspension_list;
+ thread_ptr -> tx_thread_suspended_next = next_thread;
+ previous_thread = next_thread -> tx_thread_suspended_previous;
+ thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = thread_ptr;
+ next_thread -> tx_thread_suspended_previous = thread_ptr;
+ }
+
+ /* Increment the number of suspensions. */
+ semaphore_ptr -> tx_semaphore_suspended_count++;
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SEMAPHORE_SUSP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+ /* Return the completion status. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Immediate return, return error completion. */
+ status = TX_NO_INSTANCE;
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_semaphore_info_get.c b/common/src/tx_semaphore_info_get.c
new file mode 100644
index 00000000..8f983072
--- /dev/null
+++ b/common/src/tx_semaphore_info_get.c
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified semaphore. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* name Destination for the semaphore name*/
+/* current_value Destination for current value of */
+/* the semaphore */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on semaphore */
+/* suspended_count Destination for suspended count */
+/* next_semaphore Destination for pointer to next */
+/* semaphore on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_SEMAPHORE **next_semaphore)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the semaphore. */
+ if (name != TX_NULL)
+ {
+
+ *name = semaphore_ptr -> tx_semaphore_name;
+ }
+
+ /* Retrieve the current value of the semaphore. */
+ if (current_value != TX_NULL)
+ {
+
+ *current_value = semaphore_ptr -> tx_semaphore_count;
+ }
+
+ /* Retrieve the first thread suspended on this semaphore. */
+ if (first_suspended != TX_NULL)
+ {
+
+ *first_suspended = semaphore_ptr -> tx_semaphore_suspension_list;
+ }
+
+ /* Retrieve the number of threads suspended on this semaphore. */
+ if (suspended_count != TX_NULL)
+ {
+
+ *suspended_count = (ULONG) semaphore_ptr -> tx_semaphore_suspended_count;
+ }
+
+ /* Retrieve the pointer to the next semaphore created. */
+ if (next_semaphore != TX_NULL)
+ {
+
+ *next_semaphore = semaphore_ptr -> tx_semaphore_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_semaphore_initialize.c b/common/src/tx_semaphore_initialize.c
new file mode 100644
index 00000000..ff97845c
--- /dev/null
+++ b/common/src/tx_semaphore_initialize.c
@@ -0,0 +1,129 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+#ifndef TX_INLINE_INITIALIZATION
+
+/* Locate semaphore component data in this file. */
+
+/* Define the head pointer of the created semaphore list. */
+
+TX_SEMAPHORE * _tx_semaphore_created_ptr;
+
+
+/* Define the variable that holds the number of created semaphores. */
+
+ULONG _tx_semaphore_created_count;
+
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of semaphore puts. */
+
+ULONG _tx_semaphore_performance_put_count;
+
+
+/* Define the total number of semaphore gets. */
+
+ULONG _tx_semaphore_performance_get_count;
+
+
+/* Define the total number of semaphore suspensions. */
+
+ULONG _tx_semaphore_performance_suspension_count;
+
+
+/* Define the total number of semaphore timeouts. */
+
+ULONG _tx_semaphore_performance_timeout_count;
+
+#endif
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the semaphore component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_semaphore_initialize(VOID)
+{
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created semaphores list and the
+ number of semaphores created. */
+ _tx_semaphore_created_ptr = TX_NULL;
+ _tx_semaphore_created_count = TX_EMPTY;
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize semaphore performance counters. */
+ _tx_semaphore_performance_put_count = ((ULONG) 0);
+ _tx_semaphore_performance_get_count = ((ULONG) 0);
+ _tx_semaphore_performance_suspension_count = ((ULONG) 0);
+ _tx_semaphore_performance_timeout_count = ((ULONG) 0);
+#endif
+#endif
+}
+
diff --git a/common/src/tx_semaphore_performance_info_get.c b/common/src/tx_semaphore_performance_info_get.c
new file mode 100644
index 00000000..fcef0321
--- /dev/null
+++ b/common/src/tx_semaphore_performance_info_get.c
@@ -0,0 +1,201 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* semaphore. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* puts Destination for the number of */
+/* puts on to this semaphore */
+/* gets Destination for the number of */
+/* gets on this semaphore */
+/* suspensions Destination for the number of */
+/* suspensions on this semaphore */
+/* timeouts Destination for number of timeouts*/
+/* on this semaphore */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets,
+ ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the semaphore ID is invalid. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the number of puts on this semaphore. */
+ if (puts != TX_NULL)
+ {
+
+ *puts = semaphore_ptr -> tx_semaphore_performance_put_count;
+ }
+
+ /* Retrieve the number of gets on this semaphore. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = semaphore_ptr -> tx_semaphore_performance_get_count;
+ }
+
+ /* Retrieve the number of suspensions on this semaphore. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = semaphore_ptr -> tx_semaphore_performance_suspension_count;
+ }
+
+ /* Retrieve the number of timeouts on this semaphore. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = semaphore_ptr -> tx_semaphore_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (semaphore_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (puts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_semaphore_performance_system_info_get.c b/common/src/tx_semaphore_performance_system_info_get.c
new file mode 100644
index 00000000..6d37b310
--- /dev/null
+++ b/common/src/tx_semaphore_performance_system_info_get.c
@@ -0,0 +1,174 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves system semaphore performance information. */
+/* */
+/* INPUT */
+/* */
+/* puts Destination for total number of */
+/* semaphore puts */
+/* gets Destination for total number of */
+/* semaphore gets */
+/* suspensions Destination for total number of */
+/* semaphore suspensions */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, ULONG *timeouts)
+{
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the total number of semaphore puts. */
+ if (puts != TX_NULL)
+ {
+
+ *puts = _tx_semaphore_performance_put_count;
+ }
+
+ /* Retrieve the total number of semaphore gets. */
+ if (gets != TX_NULL)
+ {
+
+ *gets = _tx_semaphore_performance_get_count;
+ }
+
+ /* Retrieve the total number of semaphore suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_semaphore_performance_suspension_count;
+ }
+
+ /* Retrieve the total number of semaphore timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_semaphore_performance_timeout_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (puts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (gets != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_semaphore_prioritize.c b/common/src/tx_semaphore_prioritize.c
new file mode 100644
index 00000000..0072b7e6
--- /dev/null
+++ b/common/src/tx_semaphore_prioritize.c
@@ -0,0 +1,251 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the highest priority suspended thread at the */
+/* front of the suspension list. All other threads remain in the same */
+/* FIFO suspension order. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_THREAD *priority_thread_ptr;
+TX_THREAD *head_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT list_changed;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PRIORITIZE, semaphore_ptr, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_PRIORITIZE_INSERT
+
+ /* Pickup the suspended count. */
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+
+ /* Determine if there are fewer than 2 suspended threads. */
+ if (suspended_count < ((UINT) 2))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Determine if there how many threads are suspended on this semaphore. */
+ else if (suspended_count == ((UINT) 2))
+ {
+
+ /* Pickup the head pointer and the next pointer. */
+ head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+ next_thread = head_ptr -> tx_thread_suspended_next;
+
+ /* Determine if the next suspended thread has a higher priority. */
+ if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
+ {
+
+ /* Yes, move the list head to the next thread. */
+ semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Remember the suspension count and head pointer. */
+ head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Set the list changed flag to false. */
+ list_changed = TX_FALSE;
+
+ /* Search through the list to find the highest priority thread. */
+ do
+ {
+
+ /* Is the current thread higher priority? */
+ if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
+ {
+
+ /* Yes, remember that this thread is the highest priority. */
+ priority_thread_ptr = thread_ptr;
+ }
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Determine if any changes to the list have occurred while
+ interrupts were enabled. */
+
+ /* Is the list head the same? */
+ if (head_ptr != semaphore_ptr -> tx_semaphore_suspension_list)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ else
+ {
+
+ /* Is the suspended count the same? */
+ if (suspended_count != semaphore_ptr -> tx_semaphore_suspended_count)
+ {
+
+ /* The list head has changed, set the list changed flag. */
+ list_changed = TX_TRUE;
+ }
+ }
+
+ /* Determine if the list has changed. */
+ if (list_changed == TX_FALSE)
+ {
+
+ /* Yes, everything is the same... move the thread pointer to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_suspended_next;
+ }
+ else
+ {
+
+ /* No, the list is been modified so we need to start the search over. */
+
+ /* Save the suspension count and head pointer. */
+ head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+
+ /* Default the highest priority thread to the thread at the front of the list. */
+ priority_thread_ptr = head_ptr;
+
+ /* Setup search pointer. */
+ thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
+
+ /* Reset the list changed flag. */
+ list_changed = TX_FALSE;
+ }
+
+ } while (thread_ptr != head_ptr);
+
+ /* Release preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Now determine if the highest priority thread is at the front
+ of the list. */
+ if (priority_thread_ptr != head_ptr)
+ {
+
+ /* No, we need to move the highest priority suspended thread to the
+ front of the list. */
+
+ /* First, remove the highest priority thread by updating the
+ adjacent suspended threads. */
+ next_thread = priority_thread_ptr -> tx_thread_suspended_next;
+ previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+
+ /* Now, link the highest priority thread at the front of the list. */
+ previous_thread = head_ptr -> tx_thread_suspended_previous;
+ priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
+ priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
+ head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
+
+ /* Move the list head pointer to the highest priority suspended thread. */
+ semaphore_ptr -> tx_semaphore_suspension_list = priority_thread_ptr;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_semaphore_put.c b/common/src/tx_semaphore_put.c
new file mode 100644
index 00000000..09ae09cb
--- /dev/null
+++ b/common/src/tx_semaphore_put.c
@@ -0,0 +1,222 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function puts an instance into the specified counting */
+/* semaphore. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Success completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread service */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr);
+#endif
+
+TX_THREAD *thread_ptr;
+UINT suspended_count;
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+
+
+ /* Disable interrupts to put an instance back to the semaphore. */
+ TX_DISABLE
+
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total semaphore put counter. */
+ _tx_semaphore_performance_put_count++;
+
+ /* Increment the number of puts on this semaphore. */
+ semaphore_ptr -> tx_semaphore_performance_put_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_SEMAPHORE_PUT_INSERT
+
+ /* Pickup the number of suspended threads. */
+ suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
+
+ /* Determine if there are any threads suspended on the semaphore. */
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Increment the semaphore count. */
+ semaphore_ptr -> tx_semaphore_count++;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the application notify function. */
+ semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if notification is required. */
+ if (semaphore_put_notify != TX_NULL)
+ {
+
+ /* Yes, call the appropriate notify callback function. */
+ (semaphore_put_notify)(semaphore_ptr);
+ }
+#endif
+ }
+ else
+ {
+
+ /* A thread is suspended on this semaphore. */
+
+ /* Pickup the pointer to the first suspended thread. */
+ thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
+
+ /* Remove the suspended thread from the list. */
+
+ /* See if this is the only suspended thread on the list. */
+ suspended_count--;
+ if (suspended_count == TX_NO_SUSPENSIONS)
+ {
+
+ /* Yes, the only suspended thread. */
+
+ /* Update the head pointer. */
+ semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
+ }
+ else
+ {
+
+ /* At least one more thread is on the same expiration list. */
+
+ /* Update the list head pointer. */
+ next_thread = thread_ptr -> tx_thread_suspended_next;
+ semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
+
+ /* Update the links of the adjacent threads. */
+ previous_thread = thread_ptr -> tx_thread_suspended_previous;
+ next_thread -> tx_thread_suspended_previous = previous_thread;
+ previous_thread -> tx_thread_suspended_next = next_thread;
+ }
+
+ /* Decrement the suspension count. */
+ semaphore_ptr -> tx_semaphore_suspended_count = suspended_count;
+
+ /* Prepare for resumption of the first thread. */
+
+ /* Clear cleanup routine to avoid timeout. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the application notify function. */
+ semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
+#endif
+
+ /* Put return status into the thread control block. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Resume thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if notification is required. */
+ if (semaphore_put_notify != TX_NULL)
+ {
+
+ /* Yes, call the appropriate notify callback function. */
+ (semaphore_put_notify)(semaphore_ptr);
+ }
+#endif
+ }
+
+ /* Return successful completion. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_semaphore_put_notify.c b/common/src/tx_semaphore_put_notify.c
new file mode 100644
index 00000000..b5b71e7f
--- /dev/null
+++ b/common/src/tx_semaphore_put_notify.c
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_put_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application callback function that is */
+/* called whenever the this semaphore is put. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore */
+/* semaphore_put_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr))
+{
+
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+
+ TX_SEMAPHORE_NOT_USED(semaphore_ptr);
+ TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(semaphore_put_notify);
+
+ /* Feature is not enabled, return error. */
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Make entry in event log. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
+
+ /* Make entry in event log. */
+ TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT
+
+ /* Setup semaphore put notification callback function. */
+ semaphore_ptr -> tx_semaphore_put_notify = semaphore_put_notify;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success to caller. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_thread_create.c b/common/src/tx_thread_create.c
new file mode 100644
index 00000000..4169d362
--- /dev/null
+++ b/common/src/tx_thread_create.c
@@ -0,0 +1,360 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#include "tx_initialize.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a thread and places it on the list of created */
+/* threads. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* name Pointer to thread name string */
+/* entry_function Entry function of the thread */
+/* entry_input 32-bit input value to thread */
+/* stack_start Pointer to start of stack */
+/* stack_size Stack size in bytes */
+/* priority Priority of thread */
+/* (default 0-31) */
+/* preempt_threshold Preemption threshold */
+/* time_slice Thread time-slice value */
+/* auto_start Automatic start selection */
+/* */
+/* OUTPUT */
+/* */
+/* return status Thread create return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_stack_build Build initial thread stack */
+/* _tx_thread_system_resume Resume automatic start thread */
+/* _tx_thread_system_ni_resume Noninterruptable resume thread*/
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* _tx_timer_initialize Create system timer thread */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input,
+ VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
+ ULONG time_slice, UINT auto_start)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+TX_THREAD *saved_thread_ptr;
+UINT saved_threshold = ((UINT) 0);
+UCHAR *temp_ptr;
+
+#ifdef TX_ENABLE_STACK_CHECKING
+ULONG new_stack_start;
+ULONG updated_stack_start;
+#endif
+
+#ifndef TX_DISABLE_STACK_FILLING
+
+ /* Set the thread stack to a pattern prior to creating the initial
+ stack frame. This pattern is used by the stack checking routines
+ to see how much has been used. */
+ TX_MEMSET(stack_start, ((UCHAR) TX_STACK_FILL), stack_size);
+#endif
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Ensure that there are two ULONG of 0xEF patterns at the top and
+ bottom of the thread's stack. This will be used to check for stack
+ overflow conditions during run-time. */
+ stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG));
+
+ /* Ensure the starting stack address is evenly aligned. */
+ new_stack_start = TX_POINTER_TO_ULONG_CONVERT(stack_start);
+ updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1))));
+
+ /* Determine if the starting stack address is different. */
+ if (new_stack_start != updated_stack_start)
+ {
+
+ /* Yes, subtract another ULONG from the size to avoid going past the stack area. */
+ stack_size = stack_size - (sizeof(ULONG));
+ }
+
+ /* Update the starting stack pointer. */
+ stack_start = TX_ULONG_TO_POINTER_CONVERT(updated_stack_start);
+#endif
+
+ /* Prepare the thread control block prior to placing it on the created
+ list. */
+
+ /* Initialize thread control block to all zeros. */
+ TX_MEMSET(thread_ptr, 0, (sizeof(TX_THREAD)));
+
+ /* Place the supplied parameters into the thread's control block. */
+ thread_ptr -> tx_thread_name = name_ptr;
+ thread_ptr -> tx_thread_entry = entry_function;
+ thread_ptr -> tx_thread_entry_parameter = entry_input;
+ thread_ptr -> tx_thread_stack_start = stack_start;
+ thread_ptr -> tx_thread_stack_size = stack_size;
+ thread_ptr -> tx_thread_priority = priority;
+ thread_ptr -> tx_thread_user_priority = priority;
+ thread_ptr -> tx_thread_time_slice = time_slice;
+ thread_ptr -> tx_thread_new_time_slice = time_slice;
+ thread_ptr -> tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES);
+
+ /* Calculate the end of the thread's stack area. */
+ temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start);
+ temp_ptr = (TX_UCHAR_POINTER_ADD(temp_ptr, (stack_size - ((ULONG) 1))));
+ thread_ptr -> tx_thread_stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(temp_ptr);
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Preemption-threshold is enabled, setup accordingly. */
+ thread_ptr -> tx_thread_preempt_threshold = preempt_threshold;
+ thread_ptr -> tx_thread_user_preempt_threshold = preempt_threshold;
+#else
+
+ /* Preemption-threshold is disabled, determine if preemption-threshold was required. */
+ if (priority != preempt_threshold)
+ {
+
+ /* Preemption-threshold specified. Since specific preemption-threshold is not supported,
+ disable all preemption. */
+ thread_ptr -> tx_thread_preempt_threshold = ((UINT) 0);
+ thread_ptr -> tx_thread_user_preempt_threshold = ((UINT) 0);
+ }
+ else
+ {
+
+ /* Preemption-threshold is not specified, just setup with the priority. */
+ thread_ptr -> tx_thread_preempt_threshold = priority;
+ thread_ptr -> tx_thread_user_preempt_threshold = priority;
+ }
+#endif
+
+ /* Now fill in the values that are required for thread initialization. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Setup the necessary fields in the thread timer block. */
+ TX_THREAD_CREATE_TIMEOUT_SETUP(thread_ptr)
+
+ /* Perform any additional thread setup activities for tool or user purpose. */
+ TX_THREAD_CREATE_INTERNAL_EXTENSION(thread_ptr)
+
+ /* Call the target specific stack frame building routine to build the
+ thread's initial stack and to setup the actual stack pointer in the
+ control block. */
+ _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry);
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Setup the highest usage stack pointer. */
+ thread_ptr -> tx_thread_stack_highest_ptr = thread_ptr -> tx_thread_stack_ptr;
+#endif
+
+ /* Prepare to make this thread a member of the created thread list. */
+ TX_DISABLE
+
+ /* Load the thread ID field in the thread control block. */
+ thread_ptr -> tx_thread_id = TX_THREAD_ID;
+
+ /* Place the thread on the list of created threads. First,
+ check for an empty list. */
+ if (_tx_thread_created_count == TX_EMPTY)
+ {
+
+ /* The created thread list is empty. Add thread to empty list. */
+ _tx_thread_created_ptr = thread_ptr;
+ thread_ptr -> tx_thread_created_next = thread_ptr;
+ thread_ptr -> tx_thread_created_previous = thread_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_thread = _tx_thread_created_ptr;
+ previous_thread = next_thread -> tx_thread_created_previous;
+
+ /* Place the new thread in the list. */
+ next_thread -> tx_thread_created_previous = thread_ptr;
+ previous_thread -> tx_thread_created_next = thread_ptr;
+
+ /* Setup this thread's created links. */
+ thread_ptr -> tx_thread_created_previous = previous_thread;
+ thread_ptr -> tx_thread_created_next = next_thread;
+ }
+
+ /* Increment the thread created count. */
+ _tx_thread_created_count++;
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name_ptr, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size, TX_TRACE_THREAD_EVENTS)
+
+ /* Register thread in the thread array structure. */
+ TX_EL_THREAD_REGISTER(thread_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_CREATE_INSERT
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+#endif
+
+ /* Determine if an automatic start was requested. If so, call the resume
+ thread function and then check for a preemption condition. */
+ if (auto_start == TX_AUTO_START)
+ {
+
+ /* Determine if the create call is being called from initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Yes, this create call was made from initialization. */
+
+ /* Pickup the current thread execute pointer, which corresponds to the
+ highest priority thread ready to execute. Interrupt lockout is
+ not required, since interrupts are assumed to be disabled during
+ initialization. */
+ saved_thread_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if there is thread ready for execution. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, a thread is ready for execution when initialization completes. */
+
+ /* Save the current preemption-threshold. */
+ saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold;
+
+ /* For initialization, temporarily set the preemption-threshold to the
+ priority level to make sure the highest-priority thread runs once
+ initialization is complete. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority;
+ }
+ }
+ else
+ {
+
+ /* Simply set the saved thread pointer to NULL. */
+ saved_thread_ptr = TX_NULL;
+ }
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_CREATE_EXTENSION(thread_ptr)
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore previous interrupt posture. */
+ TX_RESTORE
+#else
+
+ /* Restore previous interrupt posture. */
+ TX_RESTORE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_CREATE_EXTENSION(thread_ptr)
+
+ /* Call the resume thread function to make this thread ready. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Determine if the thread's preemption-threshold needs to be restored. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, restore the previous highest-priority thread's preemption-threshold. This
+ can only happen if this routine is called from initialization. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
+ }
+ }
+ else
+ {
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_CREATE_EXTENSION(thread_ptr)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_CREATE_EXTENSION(thread_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Re-enable preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+#endif
+ }
+
+ /* Always return a success. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_thread_delete.c b/common/src/tx_thread_delete.c
new file mode 100644
index 00000000..3d384966
--- /dev/null
+++ b/common/src/tx_thread_delete.c
@@ -0,0 +1,166 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles application delete thread requests. The */
+/* thread to delete must be in a terminated or completed state, */
+/* otherwise this function just returns an error code. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_delete(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *next_thread;
+TX_THREAD *previous_thread;
+UINT status;
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Lockout interrupts while the thread is being deleted. */
+ TX_DISABLE
+
+ /* Check for proper status of this thread to delete. */
+ if (thread_ptr -> tx_thread_state != TX_COMPLETED)
+ {
+
+ /* Now check for terminated state. */
+ if (thread_ptr -> tx_thread_state != TX_TERMINATED)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Thread not completed or terminated - return an error! */
+ status = TX_DELETE_ERROR;
+ }
+ }
+
+ /* Determine if the delete operation is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, continue with deleting the thread. */
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_DELETE_EXTENSION(thread_ptr)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_DELETE, thread_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_thread), 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(thread_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_DELETE_INSERT
+
+ /* Unregister thread in the thread array structure. */
+ TX_EL_THREAD_UNREGISTER(thread_ptr)
+
+ /* Clear the thread ID to make it invalid. */
+ thread_ptr -> tx_thread_id = TX_CLEAR_ID;
+
+ /* Decrement the number of created threads. */
+ _tx_thread_created_count--;
+
+ /* See if the thread is the only one on the list. */
+ if (_tx_thread_created_count == TX_EMPTY)
+ {
+
+ /* Only created thread, just set the created list to NULL. */
+ _tx_thread_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Otherwise, not the only created thread, link-up the neighbors. */
+ next_thread = thread_ptr -> tx_thread_created_next;
+ previous_thread = thread_ptr -> tx_thread_created_previous;
+ next_thread -> tx_thread_created_previous = previous_thread;
+ previous_thread -> tx_thread_created_next = next_thread;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_thread_created_ptr == thread_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_thread_created_ptr = next_thread;
+ }
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_entry_exit_notify.c b/common/src/tx_thread_entry_exit_notify.c
new file mode 100644
index 00000000..273864f2
--- /dev/null
+++ b/common/src/tx_thread_entry_exit_notify.c
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_entry_exit_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application entry/exit notification */
+/* callback routine for the application. Once registered, the callback */
+/* routine is called when the thread is initially entered and called */
+/* again when the thread completes or is terminated. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* thread_entry_exit_notify Pointer to notify callback */
+/* function, TX_NULL to disable*/
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id))
+{
+
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+
+ TX_THREAD_NOT_USED(thread_ptr);
+ TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(thread_entry_exit_notify);
+
+ /* Feature is not enabled, return error. */
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Make entry in event log. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Make entry in event log. */
+ TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT
+
+ /* Setup thread entry/exit notification callback function. */
+ thread_ptr -> tx_thread_entry_exit_notify = thread_entry_exit_notify;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success to caller. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_thread_identify.c b/common/src/tx_thread_identify.c
new file mode 100644
index 00000000..49f9b338
--- /dev/null
+++ b/common/src/tx_thread_identify.c
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* */
+/* 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"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_trace.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_identify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns the control block pointer of the currently */
+/* executing thread. If the return value is NULL, no thread is */
+/* executing. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD * Pointer to control block of */
+/* currently executing thread */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+TX_THREAD *_tx_thread_identify(VOID)
+{
+
+TX_THREAD *thread_ptr;
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts to put the timer on the created list. */
+ TX_DISABLE
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_IDENTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS)
+#endif
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_IDENTIFY_INSERT
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return the current thread pointer. */
+ return(thread_ptr);
+}
+
diff --git a/common/src/tx_thread_info_get.c b/common/src/tx_thread_info_get.c
new file mode 100644
index 00000000..1f0acc83
--- /dev/null
+++ b/common/src/tx_thread_info_get.c
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified thread. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control block */
+/* name Destination for the thread name */
+/* state Destination for thread state */
+/* run_count Destination for thread run count */
+/* priority Destination for thread priority */
+/* preemption_threshold Destination for thread preemption-*/
+/* threshold */
+/* time_slice Destination for thread time-slice */
+/* next_thread Destination for next created */
+/* thread */
+/* next_suspended_thread Destination for next suspended */
+/* thread */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
+ UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
+ TX_THREAD **next_thread, TX_THREAD **next_suspended_thread)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve the name of the thread. */
+ if (name != TX_NULL)
+ {
+
+ *name = thread_ptr -> tx_thread_name;
+ }
+
+ /* Pickup the thread's current state. */
+ if (state != TX_NULL)
+ {
+
+ *state = thread_ptr -> tx_thread_state;
+ }
+
+ /* Pickup the number of times the thread has been scheduled. */
+ if (run_count != TX_NULL)
+ {
+
+ *run_count = thread_ptr -> tx_thread_run_count;
+ }
+
+ /* Pickup the thread's priority. */
+ if (priority != TX_NULL)
+ {
+
+ *priority = thread_ptr -> tx_thread_user_priority;
+ }
+
+ /* Pickup the thread's preemption-threshold. */
+ if (preemption_threshold != TX_NULL)
+ {
+
+ *preemption_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
+ }
+
+ /* Pickup the thread's current time-slice. */
+ if (time_slice != TX_NULL)
+ {
+
+ *time_slice = thread_ptr -> tx_thread_time_slice;
+ }
+
+ /* Pickup the next created thread. */
+ if (next_thread != TX_NULL)
+ {
+
+ *next_thread = thread_ptr -> tx_thread_created_next;
+ }
+
+ /* Pickup the next thread suspended. */
+ if (next_suspended_thread != TX_NULL)
+ {
+
+ *next_suspended_thread = thread_ptr -> tx_thread_suspended_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_thread_initialize.c b/common/src/tx_thread_initialize.c
new file mode 100644
index 00000000..99127066
--- /dev/null
+++ b/common/src/tx_thread_initialize.c
@@ -0,0 +1,448 @@
+/**************************************************************************/
+/* */
+/* 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
+
+
+#ifndef TX_MISRA_ENABLE
+#define TX_THREAD_INIT
+#endif
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+
+
+/* Define the pointer that contains the system stack pointer. This is
+ utilized when control returns from a thread to the system to reset the
+ current stack. This is setup in the low-level initialization function. */
+
+VOID * _tx_thread_system_stack_ptr;
+
+
+/* Define the current thread pointer. This variable points to the currently
+ executing thread. If this variable is NULL, no thread is executing. */
+
+TX_THREAD * _tx_thread_current_ptr;
+
+
+/* Define the variable that holds the next thread to execute. It is important
+ to remember that this is not necessarily equal to the current thread
+ pointer. */
+
+TX_THREAD * _tx_thread_execute_ptr;
+
+
+/* Define the head pointer of the created thread list. */
+
+TX_THREAD * _tx_thread_created_ptr;
+
+
+/* Define the variable that holds the number of created threads. */
+
+ULONG _tx_thread_created_count;
+
+
+/* Define the current state variable. When this value is 0, a thread
+ is executing or the system is idle. Other values indicate that
+ interrupt or initialization processing is active. This variable is
+ initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
+ active. */
+
+volatile ULONG _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
+
+
+/* Define the 32-bit priority bit-maps. There is one priority bit map for each
+ 32 priority levels supported. If only 32 priorities are supported there is
+ only one bit map. Each bit within a priority bit map represents that one
+ or more threads at the associated thread priority are ready. */
+
+ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
+
+
+/* Define the priority map active bit map that specifies which of the previously
+ defined priority maps have something set. This is only necessary if more than
+ 32 priorities are supported. */
+
+#if TX_MAX_PRIORITIES > 32
+ULONG _tx_thread_priority_map_active;
+#endif
+
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+/* Define the 32-bit preempt priority bit maps. There is one preempt bit map
+ for each 32 priority levels supported. If only 32 priorities are supported
+ there is only one bit map. Each set set bit corresponds to a preempted priority
+ level that had preemption-threshold active to protect against preemption of a
+ range of relatively higher priority threads. */
+
+ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
+
+
+/* Define the preempt map active bit map that specifies which of the previously
+ defined preempt maps have something set. This is only necessary if more than
+ 32 priorities are supported. */
+
+#if TX_MAX_PRIORITIES > 32
+ULONG _tx_thread_preempted_map_active;
+#endif
+#endif
+
+/* Define the variable that holds the highest priority group ready for
+ execution. It is important to note that this is not necessarily the same
+ as the priority of the thread pointed to by _tx_execute_thread. */
+
+UINT _tx_thread_highest_priority;
+
+
+/* Define the array of thread pointers. Each entry represents the threads that
+ are ready at that priority group. For example, index 10 in this array
+ represents the first thread ready at priority 10. If this entry is NULL,
+ no threads are ready at that priority. */
+
+TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES];
+
+
+/* Define the global preempt disable variable. If this is non-zero, preemption is
+ disabled. It is used internally by ThreadX to prevent preemption of a thread in
+ the middle of a service that is resuming or suspending another thread. */
+
+volatile UINT _tx_thread_preempt_disable;
+
+
+/* Define the global function pointer for mutex cleanup on thread completion or
+ termination. This pointer is setup during mutex initialization. */
+
+VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
+
+
+/* Define the global build options variable. This contains a bit map representing
+ how the ThreadX library was built. The following are the bit field definitions:
+
+ Bit(s) Meaning
+
+ 31 TX_NOT_INTERRUPTABLE defined
+ 30 TX_INLINE_THREAD_RESUME_SUSPEND define
+ 29-24 Priority groups 1 -> 32 priorities
+ 2 -> 64 priorities
+ 3 -> 96 priorities
+
+ ...
+
+ 32 -> 1024 priorities
+ 23 TX_TIMER_PROCESS_IN_ISR defined
+ 22 TX_REACTIVATE_INLINE defined
+ 21 TX_DISABLE_STACK_FILLING defined
+ 20 TX_ENABLE_STACK_CHECKING defined
+ 19 TX_DISABLE_PREEMPTION_THRESHOLD defined
+ 18 TX_DISABLE_REDUNDANT_CLEARING defined
+ 17 TX_DISABLE_NOTIFY_CALLBACKS defined
+ 16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
+ 15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
+ 14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
+ 13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
+ 12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
+ 11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
+ 10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined
+ 9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined
+ 8 TX_ENABLE_EVENT_TRACE defined
+ 7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
+ 6-0 Port Specific */
+
+ULONG _tx_build_options;
+
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+/* Define the global function pointer for stack error handling. If a stack error is
+ detected and the application has registered a stack error handler, it will be
+ called via this function pointer. */
+
+VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
+
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of thread resumptions. Each time a thread enters the
+ ready state this variable is incremented. */
+
+ULONG _tx_thread_performance_resume_count;
+
+
+/* Define the total number of thread suspensions. Each time a thread enters a
+ suspended state this variable is incremented. */
+
+ULONG _tx_thread_performance_suspend_count;
+
+
+/* Define the total number of solicited thread preemptions. Each time a thread is
+ preempted by directly calling a ThreadX service, this variable is incremented. */
+
+ULONG _tx_thread_performance_solicited_preemption_count;
+
+
+/* Define the total number of interrupt thread preemptions. Each time a thread is
+ preempted as a result of an ISR calling a ThreadX service, this variable is
+ incremented. */
+
+ULONG _tx_thread_performance_interrupt_preemption_count;
+
+
+/* Define the total number of priority inversions. Each time a thread is blocked by
+ a mutex owned by a lower-priority thread, this variable is incremented. */
+
+ULONG _tx_thread_performance_priority_inversion_count;
+
+
+/* Define the total number of time-slices. Each time a time-slice operation is
+ actually performed (another thread is setup for running) this variable is
+ incremented. */
+
+ULONG _tx_thread_performance_time_slice_count;
+
+
+/* Define the total number of thread relinquish operations. Each time a thread
+ relinquish operation is actually performed (another thread is setup for running)
+ this variable is incremented. */
+
+ULONG _tx_thread_performance_relinquish_count;
+
+
+/* Define the total number of thread timeouts. Each time a thread has a
+ timeout this variable is incremented. */
+
+ULONG _tx_thread_performance_timeout_count;
+
+
+/* Define the total number of thread wait aborts. Each time a thread's suspension
+ is lifted by the tx_thread_wait_abort call this variable is incremented. */
+
+ULONG _tx_thread_performance_wait_abort_count;
+
+
+/* Define the total number of idle system thread returns. Each time a thread returns to
+ an idle system (no other thread is ready to run) this variable is incremented. */
+
+ULONG _tx_thread_performance_idle_return_count;
+
+
+/* Define the total number of non-idle system thread returns. Each time a thread returns to
+ a non-idle system (another thread is ready to run) this variable is incremented. */
+
+ULONG _tx_thread_performance_non_idle_return_count;
+
+
+/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
+ is a circular list, where the index points to the oldest entry. */
+
+ULONG _tx_thread_performance__execute_log_index;
+TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
+#endif
+
+
+/* Define special string. */
+
+#ifndef TX_MISRA_ENABLE
+const CHAR _tx_thread_special_string[] =
+ "G-ML-EL-ML-BL-DL-BL-GB-GL-M-D-DL-GZ-KH-EL-CM-NH-HA-GF-DD-JC-YZ-CT-AT-DW-USA-CA-SD-SDSU";
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the thread control component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_initialize(VOID)
+{
+
+ /* Note: the system stack pointer and the system state variables are
+ initialized by the low and high-level initialization functions,
+ respectively. */
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Set current thread pointer to NULL. */
+ TX_THREAD_SET_CURRENT(TX_NULL)
+
+ /* Initialize the execute thread pointer to NULL. */
+ _tx_thread_execute_ptr = TX_NULL;
+
+ /* Initialize the priority information. */
+ TX_MEMSET(&_tx_thread_priority_maps[0], 0, (sizeof(_tx_thread_priority_maps)));
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+ TX_MEMSET(&_tx_thread_preempted_maps[0], 0, (sizeof(_tx_thread_preempted_maps)));
+#endif
+#endif
+
+ /* Setup the highest priority variable to the max, indicating no thread is currently
+ ready. */
+ _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES);
+
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the array of priority head pointers. */
+ TX_MEMSET(&_tx_thread_priority_list[0], 0, (sizeof(_tx_thread_priority_list)));
+
+ /* Initialize the head pointer of the created threads list and the
+ number of threads created. */
+ _tx_thread_created_ptr = TX_NULL;
+ _tx_thread_created_count = TX_EMPTY;
+
+ /* Clear the global preempt disable variable. */
+ _tx_thread_preempt_disable = ((UINT) 0);
+
+ /* Initialize the thread mutex release function pointer. */
+ _tx_thread_mutex_release = TX_NULL;
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Clear application registered stack error handler. */
+ _tx_thread_application_stack_error_handler = TX_NULL;
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Clear performance counters. */
+ _tx_thread_performance_resume_count = ((ULONG) 0);
+ _tx_thread_performance_suspend_count = ((ULONG) 0);
+ _tx_thread_performance_solicited_preemption_count = ((ULONG) 0);
+ _tx_thread_performance_interrupt_preemption_count = ((ULONG) 0);
+ _tx_thread_performance_priority_inversion_count = ((ULONG) 0);
+ _tx_thread_performance_time_slice_count = ((ULONG) 0);
+ _tx_thread_performance_relinquish_count = ((ULONG) 0);
+ _tx_thread_performance_timeout_count = ((ULONG) 0);
+ _tx_thread_performance_wait_abort_count = ((ULONG) 0);
+ _tx_thread_performance_idle_return_count = ((ULONG) 0);
+ _tx_thread_performance_non_idle_return_count = ((ULONG) 0);
+
+ /* Initialize the execute thread log. */
+ TX_MEMSET(&_tx_thread_performance_execute_log[0], 0, (sizeof(_tx_thread_performance_execute_log)));
+#endif
+#endif
+
+ /* Setup the build options flag. This is used to identify how the ThreadX library was constructed. */
+ _tx_build_options = _tx_build_options
+ | (((ULONG) (TX_MAX_PRIORITIES/32)) << 24)
+#ifdef TX_NOT_INTERRUPTABLE
+ | (((ULONG) 1) << 31)
+#endif
+#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
+ | (((ULONG) 1) << 30)
+#endif
+#ifdef TX_TIMER_PROCESS_IN_ISR
+ | (((ULONG) 1) << 23)
+#endif
+#ifdef TX_REACTIVATE_INLINE
+ | (((ULONG) 1) << 22)
+#endif
+#ifdef TX_DISABLE_STACK_FILLING
+ | (((ULONG) 1) << 21)
+#endif
+#ifdef TX_ENABLE_STACK_CHECKING
+ | (((ULONG) 1) << 20)
+#endif
+#ifdef TX_DISABLE_PREEMPTION_THRESHOLD
+ | (((ULONG) 1) << 19)
+#endif
+#ifdef TX_DISABLE_REDUNDANT_CLEARING
+ | (((ULONG) 1) << 18)
+#endif
+#ifdef TX_DISABLE_NOTIFY_CALLBACKS
+ | (((ULONG) 1) << 17)
+#endif
+#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 16)
+#endif
+#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 15)
+#endif
+#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 14)
+#endif
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 13)
+#endif
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 12)
+#endif
+#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 11)
+#endif
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 10)
+#endif
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+ | (((ULONG) 1) << 9)
+#endif
+#ifdef TX_ENABLE_EVENT_TRACE
+ | (((ULONG) 1) << 8)
+#endif
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ | (((ULONG) 1) << 7)
+#endif
+#if TX_PORT_SPECIFIC_BUILD_OPTIONS != 0
+ | TX_PORT_SPECIFIC_BUILD_OPTIONS
+#endif
+ ;
+}
+
diff --git a/common/src/tx_thread_performance_info_get.c b/common/src/tx_thread_performance_info_get.c
new file mode 100644
index 00000000..ba22b346
--- /dev/null
+++ b/common/src/tx_thread_performance_info_get.c
@@ -0,0 +1,297 @@
+/**************************************************************************/
+/* */
+/* 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"
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* thread. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control block */
+/* resumptions Destination for number of times */
+/* thread was resumed */
+/* suspensions Destination for number of times */
+/* thread was suspended */
+/* solicited_preemptions Destination for number of times */
+/* thread called another service */
+/* that resulted in preemption */
+/* interrupt_preemptions Destination for number of times */
+/* thread was preempted by another */
+/* thread made ready in Interrupt */
+/* Service Routine (ISR) */
+/* priority_inversions Destination for number of times */
+/* a priority inversion was */
+/* detected for this thread */
+/* time_slices Destination for number of times */
+/* thread was time-sliced */
+/* relinquishes Destination for number of thread */
+/* relinquishes */
+/* timeouts Destination for number of timeouts*/
+/* for thread */
+/* wait_aborts Destination for number of wait */
+/* aborts for thread */
+/* last_preempted_by Destination for pointer of the */
+/* thread that last preempted this */
+/* thread */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_performance_info_get(TX_THREAD *thread_ptr, ULONG *resumptions, ULONG *suspensions,
+ ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
+ ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts, TX_THREAD **last_preempted_by)
+{
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the thread ID is invalid. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve number of resumptions for this thread. */
+ if (resumptions != TX_NULL)
+ {
+
+ *resumptions = thread_ptr -> tx_thread_performance_resume_count;
+ }
+
+ /* Retrieve number of suspensions for this thread. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = thread_ptr -> tx_thread_performance_suspend_count;
+ }
+
+ /* Retrieve number of solicited preemptions for this thread. */
+ if (solicited_preemptions != TX_NULL)
+ {
+
+ *solicited_preemptions = thread_ptr -> tx_thread_performance_solicited_preemption_count;
+ }
+
+ /* Retrieve number of interrupt preemptions for this thread. */
+ if (interrupt_preemptions != TX_NULL)
+ {
+
+ *interrupt_preemptions = thread_ptr -> tx_thread_performance_interrupt_preemption_count;
+ }
+
+ /* Retrieve number of priority inversions for this thread. */
+ if (priority_inversions != TX_NULL)
+ {
+
+ *priority_inversions = thread_ptr -> tx_thread_performance_priority_inversion_count;
+ }
+
+ /* Retrieve number of time-slices for this thread. */
+ if (time_slices != TX_NULL)
+ {
+
+ *time_slices = thread_ptr -> tx_thread_performance_time_slice_count;
+ }
+
+ /* Retrieve number of relinquishes for this thread. */
+ if (relinquishes != TX_NULL)
+ {
+
+ *relinquishes = thread_ptr -> tx_thread_performance_relinquish_count;
+ }
+
+ /* Retrieve number of timeouts for this thread. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = thread_ptr -> tx_thread_performance_timeout_count;
+ }
+
+ /* Retrieve number of wait aborts for this thread. */
+ if (wait_aborts != TX_NULL)
+ {
+
+ *wait_aborts = thread_ptr -> tx_thread_performance_wait_abort_count;
+ }
+
+ /* Retrieve the pointer of the last thread that preempted this thread. */
+ if (last_preempted_by != TX_NULL)
+ {
+
+ *last_preempted_by = thread_ptr -> tx_thread_performance_last_preempting_thread;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (resumptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (solicited_preemptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (interrupt_preemptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (priority_inversions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (time_slices != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (relinquishes != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (wait_aborts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (last_preempted_by != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_performance_system_info_get.c b/common/src/tx_thread_performance_system_info_get.c
new file mode 100644
index 00000000..0d85cc10
--- /dev/null
+++ b/common/src/tx_thread_performance_system_info_get.c
@@ -0,0 +1,287 @@
+/**************************************************************************/
+/* */
+/* 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"
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves thread system performance information. */
+/* */
+/* INPUT */
+/* */
+/* resumptions Destination for total number of */
+/* thread resumptions */
+/* suspensions Destination for total number of */
+/* thread suspensions */
+/* solicited_preemptions Destination for total number of */
+/* thread preemption from thread */
+/* API calls */
+/* interrupt_preemptions Destination for total number of */
+/* thread preemptions as a result */
+/* of threads made ready inside of */
+/* Interrupt Service Routines */
+/* priority_inversions Destination for total number of */
+/* priority inversions */
+/* time_slices Destination for total number of */
+/* time-slices */
+/* relinquishes Destination for total number of */
+/* relinquishes */
+/* timeouts Destination for total number of */
+/* timeouts */
+/* wait_aborts Destination for total number of */
+/* wait aborts */
+/* non_idle_returns Destination for total number of */
+/* times threads return when */
+/* another thread is ready */
+/* idle_returns Destination for total number of */
+/* times threads return when no */
+/* other thread is ready */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_performance_system_info_get(ULONG *resumptions, ULONG *suspensions,
+ ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
+ ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts,
+ ULONG *non_idle_returns, ULONG *idle_returns)
+{
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Retrieve total number of thread resumptions. */
+ if (resumptions != TX_NULL)
+ {
+
+ *resumptions = _tx_thread_performance_resume_count;
+ }
+
+ /* Retrieve total number of thread suspensions. */
+ if (suspensions != TX_NULL)
+ {
+
+ *suspensions = _tx_thread_performance_suspend_count;
+ }
+
+ /* Retrieve total number of solicited thread preemptions. */
+ if (solicited_preemptions != TX_NULL)
+ {
+
+ *solicited_preemptions = _tx_thread_performance_solicited_preemption_count;
+ }
+
+ /* Retrieve total number of interrupt thread preemptions. */
+ if (interrupt_preemptions != TX_NULL)
+ {
+
+ *interrupt_preemptions = _tx_thread_performance_interrupt_preemption_count;
+ }
+
+ /* Retrieve total number of thread priority inversions. */
+ if (priority_inversions != TX_NULL)
+ {
+
+ *priority_inversions = _tx_thread_performance_priority_inversion_count;
+ }
+
+ /* Retrieve total number of thread time-slices. */
+ if (time_slices != TX_NULL)
+ {
+
+ *time_slices = _tx_thread_performance_time_slice_count;
+ }
+
+ /* Retrieve total number of thread relinquishes. */
+ if (relinquishes != TX_NULL)
+ {
+
+ *relinquishes = _tx_thread_performance_relinquish_count;
+ }
+
+ /* Retrieve total number of thread timeouts. */
+ if (timeouts != TX_NULL)
+ {
+
+ *timeouts = _tx_thread_performance_timeout_count;
+ }
+
+ /* Retrieve total number of thread wait aborts. */
+ if (wait_aborts != TX_NULL)
+ {
+
+ *wait_aborts = _tx_thread_performance_wait_abort_count;
+ }
+
+ /* Retrieve total number of thread non-idle system returns. */
+ if (non_idle_returns != TX_NULL)
+ {
+
+ *non_idle_returns = _tx_thread_performance_non_idle_return_count;
+ }
+
+ /* Retrieve total number of thread idle system returns. */
+ if (idle_returns != TX_NULL)
+ {
+
+ *idle_returns = _tx_thread_performance_idle_return_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (resumptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (suspensions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (solicited_preemptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (interrupt_preemptions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (priority_inversions != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (time_slices != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (relinquishes != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (timeouts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (wait_aborts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (non_idle_returns != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (idle_returns != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_thread_preemption_change.c b/common/src/tx_thread_preemption_change.c
new file mode 100644
index 00000000..3c6dd51e
--- /dev/null
+++ b/common/src/tx_thread_preemption_change.c
@@ -0,0 +1,280 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_preemption_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes preemption-threshold change requests. The */
+/* previous preemption is returned to the caller. If the new request */
+/* allows a higher priority thread to execute, preemption takes place */
+/* inside of this function. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* new_threshold New preemption threshold */
+/* old_threshold Old preemption threshold */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+ULONG priority_bit;
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+#endif
+UINT status;
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+#ifdef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Only allow 0 (disable all preemption) and returning preemption-threshold to the
+ current thread priority if preemption-threshold is disabled. All other threshold
+ values are converted to 0. */
+ if (thread_ptr -> tx_thread_user_priority != new_threshold)
+ {
+
+ /* Is the new threshold zero? */
+ if (new_threshold != ((UINT) 0))
+ {
+
+ /* Convert the new threshold to disable all preemption, since preemption-threshold is
+ not supported. */
+ new_threshold = ((UINT) 0);
+ }
+ }
+#endif
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PREEMPTION_CHANGE, thread_ptr, new_threshold, thread_ptr -> tx_thread_preempt_threshold, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_PREEMPTION_CHANGE_INSERT
+
+ /* Determine if the new threshold is greater than the current user priority. */
+ if (new_threshold > thread_ptr -> tx_thread_user_priority)
+ {
+
+ /* Return error. */
+ status = TX_THRESH_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Determine if the new threshold is the same as the priority. */
+ if (thread_ptr -> tx_thread_user_priority == new_threshold)
+ {
+
+ /* Determine if this thread is at the head of the list. */
+ if (_tx_thread_priority_list[thread_ptr -> tx_thread_priority] == thread_ptr)
+ {
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32);
+#endif
+
+ /* Yes, this thread is at the front of the list. Make sure
+ the preempted bit is cleared for this thread. */
+ TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+ }
+#endif
+
+ /* Return the user's preemption-threshold. */
+ *old_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
+
+ /* Setup the new threshold. */
+ thread_ptr -> tx_thread_user_preempt_threshold = new_threshold;
+
+ /* Determine if the new threshold represents a higher priority than the priority inheritance threshold. */
+ if (new_threshold < thread_ptr -> tx_thread_inherit_priority)
+ {
+
+ /* Update the actual preemption-threshold with the new threshold. */
+ thread_ptr -> tx_thread_preempt_threshold = new_threshold;
+ }
+ else
+ {
+
+ /* Update the actual preemption-threshold with the priority inheritance. */
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority;
+ }
+
+ /* Is the thread priority less than the current highest priority? If not, no preemption is required. */
+ if (_tx_thread_highest_priority < thread_ptr -> tx_thread_priority)
+ {
+
+ /* Is the new thread preemption-threshold less than the current highest priority? If not, no preemption is required. */
+ if (_tx_thread_highest_priority < new_threshold)
+ {
+
+ /* If the current execute pointer is the same at this thread, preemption needs to take place. */
+ if (_tx_thread_execute_ptr == thread_ptr)
+ {
+
+ /* Preemption needs to take place. */
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Determine if this thread has preemption threshold set. */
+ if (thread_ptr -> tx_thread_preempt_threshold != thread_ptr -> tx_thread_priority)
+ {
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32);
+
+ /* Set the active bit to remember that the preempt map has something set. */
+ TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit;
+#endif
+
+ /* Remember that this thread was preempted by a thread above the thread's threshold. */
+ TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
+ }
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if the caller is an interrupt or from a thread. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
+ {
+
+ /* Caller is a thread, so this is a solicited preemption. */
+ _tx_thread_performance_solicited_preemption_count++;
+
+ /* Increment the thread's solicited preemption counter. */
+ thread_ptr -> tx_thread_performance_solicited_preemption_count++;
+ }
+
+ /* Remember the thread that preempted this thread. */
+ thread_ptr -> tx_thread_performance_last_preempting_thread = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+ /* Is the execute pointer different? */
+ if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+ /* Setup the highest priority thread to execute. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Disable interrupts. */
+ TX_DISABLE
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_priority_change.c b/common/src/tx_thread_priority_change.c
new file mode 100644
index 00000000..8a18fb4b
--- /dev/null
+++ b/common/src/tx_thread_priority_change.c
@@ -0,0 +1,280 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_priority_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function changes the priority of the specified thread. It */
+/* also returns the old priority and handles preemption if the calling */
+/* thread is currently executing and the priority change results in a */
+/* higher priority thread ready for execution. */
+/* */
+/* Note: the preemption threshold is automatically changed to the new */
+/* priority. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* new_priority New thread priority */
+/* old_priority Old thread priority */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_thread_system_suspend Suspend thread */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT *old_priority)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *execute_ptr;
+TX_THREAD *next_execute_ptr;
+UINT original_priority;
+
+
+ /* Lockout interrupts while the thread is being suspended. */
+ TX_DISABLE
+
+ /* Save the previous priority. */
+ *old_priority = thread_ptr -> tx_thread_user_priority;
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PRIORITY_CHANGE, thread_ptr, new_priority, thread_ptr -> tx_thread_priority, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_PRIORITY_CHANGE_INSERT
+
+ /* Determine if this thread is currently ready. */
+ if (thread_ptr -> tx_thread_state != TX_READY)
+ {
+
+ /* Setup the user priority and threshold in the thread's control
+ block. */
+ thread_ptr -> tx_thread_user_priority = new_priority;
+ thread_ptr -> tx_thread_user_preempt_threshold = new_priority;
+
+ /* Determine if the actual thread priority should be setup, which is the
+ case if the new priority is higher than the priority inheritance. */
+ if (new_priority < thread_ptr -> tx_thread_inherit_priority)
+ {
+
+ /* Change thread priority to the new user's priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+ else
+ {
+
+ /* Change thread priority to the priority inheritance. */
+ thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority;
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Pickup the next thread to execute. */
+ execute_ptr = _tx_thread_execute_ptr;
+
+ /* Save the original priority. */
+ original_priority = thread_ptr -> tx_thread_priority;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+
+ /* At this point, the preempt disable flag is still set, so we still have
+ protection against all preemption. */
+
+ /* Setup the new priority for this thread. */
+ thread_ptr -> tx_thread_user_priority = new_priority;
+ thread_ptr -> tx_thread_user_preempt_threshold = new_priority;
+
+ /* Determine if the actual thread priority should be setup, which is the
+ case if the new priority is higher than the priority inheritance. */
+ if (new_priority < thread_ptr -> tx_thread_inherit_priority)
+ {
+
+ /* Change thread priority to the new user's priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+ else
+ {
+
+ /* Change thread priority to the priority inheritance. */
+ thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority;
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority;
+ }
+
+ /* Resume the thread with the new priority. */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+#else
+
+ /* Increment the preempt disable flag by 2 to prevent system suspend from
+ returning to the system. */
+ _tx_thread_preempt_disable = _tx_thread_preempt_disable + ((UINT) 3);
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* The thread is ready and must first be removed from the list. Call the
+ system suspend function to accomplish this. */
+ _tx_thread_system_suspend(thread_ptr);
+
+ /* At this point, the preempt disable flag is still set, so we still have
+ protection against all preemption. */
+
+ /* Setup the new priority for this thread. */
+ thread_ptr -> tx_thread_user_priority = new_priority;
+ thread_ptr -> tx_thread_user_preempt_threshold = new_priority;
+
+ /* Determine if the actual thread priority should be setup, which is the
+ case if the new priority is higher than the priority inheritance. */
+ if (new_priority < thread_ptr -> tx_thread_inherit_priority)
+ {
+
+ /* Change thread priority to the new user's priority. */
+ thread_ptr -> tx_thread_priority = new_priority;
+ thread_ptr -> tx_thread_preempt_threshold = new_priority;
+ }
+ else
+ {
+
+ /* Change thread priority to the priority inheritance. */
+ thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority;
+ thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority;
+ }
+
+ /* Resume the thread with the new priority. */
+ _tx_thread_system_resume(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Pickup the next thread to execute. */
+ next_execute_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if this thread is not the next thread to execute. */
+ if (thread_ptr != next_execute_ptr)
+ {
+
+ /* Make sure the thread is still ready. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Now check and see if this thread has an equal or higher priority. */
+ if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority)
+ {
+
+ /* Now determine if this thread was the previously executing thread. */
+ if (thread_ptr == execute_ptr)
+ {
+
+ /* Yes, this thread was previously executing before we temporarily suspended and resumed
+ it in order to change the priority. A lower or same priority thread cannot be the next thread
+ to execute in this case since this thread really didn't suspend. Simply reset the execute
+ pointer to this thread. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+ /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */
+ if (original_priority < new_priority)
+ {
+
+ /* Ensure that this thread is placed at the front of the priority list. */
+ _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr;
+ }
+ }
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+ }
+
+ /* Return success if we get here! */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_thread_relinquish.c b/common/src/tx_thread_relinquish.c
new file mode 100644
index 00000000..4dcfb76c
--- /dev/null
+++ b/common/src/tx_thread_relinquish.c
@@ -0,0 +1,169 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#ifndef TX_NO_TIMER
+#include "tx_timer.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_relinquish PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function moves the currently executing thread to the end of */
+/* the list of threads ready at the same priority. If no other threads */
+/* of the same or higher priority are ready, this function simply */
+/* returns. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_return Return to the system */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_relinquish(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT priority;
+TX_THREAD *thread_ptr;
+
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+#ifndef TX_NO_TIMER
+
+ /* Reset time slice for current thread. */
+ _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice;
+#endif
+
+ /* Pickup the thread's priority. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Determine if there is another thread at the same priority. */
+ if (thread_ptr -> tx_thread_ready_next != thread_ptr)
+ {
+
+ /* Yes, there is another thread at this priority, make it the highest at
+ this priority level. */
+ _tx_thread_priority_list[priority] = thread_ptr -> tx_thread_ready_next;
+
+ /* Mark the new thread as the one to execute. */
+ _tx_thread_execute_ptr = thread_ptr -> tx_thread_ready_next;
+ }
+
+ /* Determine if there is a higher-priority thread ready. */
+ if (_tx_thread_highest_priority < priority)
+ {
+
+ /* Yes, there is a higher priority thread ready to execute. Make
+ it visible to the thread scheduler. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+ /* No need to clear the preempted bit in this case, since the currently running
+ thread must already have its preempted bit clear. */
+ }
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RELINQUISH, &thread_ptr, TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_RELINQUISH_INSERT
+
+ /* Restore previous interrupt posture. */
+ TX_RESTORE
+
+ /* Determine if this thread needs to return to the system. */
+ if (_tx_thread_execute_ptr != thread_ptr)
+ {
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the number of thread relinquishes. */
+ thread_ptr -> tx_thread_performance_relinquish_count++;
+
+ /* Increment the total number of thread relinquish operations. */
+ _tx_thread_performance_relinquish_count++;
+
+ /* Increment the non-idle return count. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+#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
+
+ /* Transfer control to the system so the scheduler can execute
+ the next thread. */
+ _tx_thread_system_return();
+ }
+}
+
diff --git a/common/src/tx_thread_reset.c b/common/src/tx_thread_reset.c
new file mode 100644
index 00000000..5eca80d3
--- /dev/null
+++ b/common/src/tx_thread_reset.c
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_reset PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function prepares the thread to run again from the entry */
+/* point specified during thread creation. The application must */
+/* call tx_thread_resume after this call completes for the thread */
+/* to actually run. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to reset */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_stack_build Build initial thread stack */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_reset(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *current_thread;
+UINT status;
+
+
+ /* Default a successful completion status. */
+ status = TX_SUCCESS;
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Check for a call from the current thread, which is not allowed! */
+ if (current_thread == thread_ptr)
+ {
+
+ /* Thread not completed or terminated - return an error! */
+ status = TX_NOT_DONE;
+ }
+ else
+ {
+
+ /* Check for proper status of this thread to reset. */
+ if (thread_ptr -> tx_thread_state != TX_COMPLETED)
+ {
+
+ /* Now check for terminated state. */
+ if (thread_ptr -> tx_thread_state != TX_TERMINATED)
+ {
+
+ /* Thread not completed or terminated - return an error! */
+ status = TX_NOT_DONE;
+ }
+ }
+ }
+
+ /* Is the request valid? */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Modify the thread status to prevent additional reset calls. */
+ thread_ptr -> tx_thread_state = TX_NOT_DONE;
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_THREAD_RESET_PORT_COMPLETION(thread_ptr)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifndef TX_DISABLE_STACK_FILLING
+
+ /* Set the thread stack to a pattern prior to creating the initial
+ stack frame. This pattern is used by the stack checking routines
+ to see how much has been used. */
+ TX_MEMSET(thread_ptr -> tx_thread_stack_start, ((UCHAR) TX_STACK_FILL), thread_ptr -> tx_thread_stack_size);
+#endif
+
+ /* Call the target specific stack frame building routine to build the
+ thread's initial stack and to setup the actual stack pointer in the
+ control block. */
+ _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Finally, move into a suspended state to allow for the thread to be resumed. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_RESET_INSERT
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_SUSPENDED)
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status to caller. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_resume.c b/common/src/tx_thread_resume.c
new file mode 100644
index 00000000..43e789f7
--- /dev/null
+++ b/common/src/tx_thread_resume.c
@@ -0,0 +1,581 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#include "tx_initialize.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_resume PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes application resume thread services. Actual */
+/* thread resumption is performed in the core service. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to resume */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Resume thread */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_resume(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+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;
+
+#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
+
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+#endif
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_RESUME_INSERT
+
+ /* Determine if the thread is suspended or in the process of suspending.
+ If so, call the thread resume processing. */
+ if (thread_ptr -> tx_thread_state == TX_SUSPENDED)
+ {
+
+ /* Determine if the create call is being called from initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Yes, this resume call was made from initialization. */
+
+ /* Pickup the current thread execute pointer, which corresponds to the
+ highest priority thread ready to execute. Interrupt lockout is
+ not required, since interrupts are assumed to be disabled during
+ initialization. */
+ saved_thread_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if there is thread ready for execution. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, a thread is ready for execution when initialization completes. */
+
+ /* Save the current preemption-threshold. */
+ saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold;
+
+ /* For initialization, temporarily set the preemption-threshold to the
+ priority level to make sure the highest-priority thread runs once
+ initialization is complete. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority;
+ }
+ }
+ else
+ {
+
+ /* Simply set the saved thread pointer to NULL. */
+ saved_thread_ptr = TX_NULL;
+ }
+
+#ifndef TX_INLINE_THREAD_RESUME_SUSPEND
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call the actual resume service to resume the thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Determine if the thread's preemption-threshold needs to be restored. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, restore the previous highest-priority thread's preemption-threshold. This
+ can only happen if this routine is called from initialization. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
+ }
+
+#ifdef TX_MISRA_ENABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Setup successful return status. */
+ status = TX_SUCCESS;
+#else
+
+ /* Return successful completion. */
+ return(TX_SUCCESS);
+#endif
+
+
+#else
+
+ /* In-line thread resumption processing follows, which is effectively just taking the
+ logic in tx_thread_system_resume.c and placing it here! */
+
+ /* Resume the thread! */
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#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
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time we have
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+ /* Make this thread ready. */
+
+ /* Change the state to ready. */
+ thread_ptr -> tx_thread_state = TX_READY;
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)
+
+#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
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ head_ptr = _tx_thread_priority_list[priority];
+ if (head_ptr == TX_NULL)
+ {
+
+ /* First thread at this priority ready. Add to the front of the list. */
+ _tx_thread_priority_list[priority] = thread_ptr;
+ thread_ptr -> tx_thread_ready_next = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = thread_ptr;
+
+#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
+
+ /* Or in the thread's priority bit. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit;
+
+ /* Determine if this newly ready thread is the highest priority. */
+ if (priority < _tx_thread_highest_priority)
+ {
+
+ /* A new highest priority thread is present. */
+
+ /* Update the highest priority variable. */
+ _tx_thread_highest_priority = priority;
+
+ /* Pickup the execute pointer. Since it is going to be referenced multiple
+ times, it is placed in a local variable. */
+ execute_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if no thread is currently executing. */
+ if (execute_ptr == TX_NULL)
+ {
+
+ /* Simply setup the execute pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+ }
+ else
+ {
+
+ /* Another thread has been scheduled for execution. */
+
+ /* Check to see if this is a higher priority thread and determine if preemption is allowed. */
+ if (priority < execute_ptr -> tx_thread_preempt_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
+
+ /* 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
+
+ /* 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)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
+ }
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if the caller is an interrupt or from a thread. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
+ {
+
+ /* Caller is a thread, so this is a solicited preemption. */
+ _tx_thread_performance_solicited_preemption_count++;
+
+ /* Increment the thread's solicited preemption counter. */
+ execute_ptr -> tx_thread_performance_solicited_preemption_count++;
+ }
+ else
+ {
+
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Caller is an interrupt, so this is an interrupt preemption. */
+ _tx_thread_performance_interrupt_preemption_count++;
+
+ /* Increment the thread's interrupt preemption counter. */
+ execute_ptr -> tx_thread_performance_interrupt_preemption_count++;
+ }
+ }
+
+ /* Remember the thread that preempted this thread. */
+ execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr;
+#endif
+
+ /* Yes, modify the execute thread pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+#ifndef TX_MISRA_ENABLE
+
+ /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */
+
+ /* Determine if the thread's preemption-threshold needs to be restored. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, restore the previous highest-priority thread's preemption-threshold. This
+ can only happen if this routine is called from initialization. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return in-line when MISRA is not enabled. */
+ return(TX_SUCCESS);
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* No, there are other threads at this priority already ready. */
+
+ /* Just add this thread to the priority list. */
+ tail_ptr = head_ptr -> tx_thread_ready_previous;
+ tail_ptr -> tx_thread_ready_next = thread_ptr;
+ head_ptr -> tx_thread_ready_previous = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = tail_ptr;
+ thread_ptr -> tx_thread_ready_next = head_ptr;
+ }
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if we should log the execute pointer. */
+
+ /* Is the execute pointer different? */
+ if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Determine if the thread's preemption-threshold needs to be restored. */
+ if (saved_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, restore the previous highest-priority thread's preemption-threshold. This
+ can only happen if this routine is called from initialization. */
+ saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
+ }
+
+ /* Setup successful return status. */
+ status = TX_SUCCESS;
+#endif
+ }
+ else if (thread_ptr -> tx_thread_delayed_suspend == TX_TRUE)
+ {
+
+ /* Clear the delayed suspension. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_FALSE;
+
+ /* Setup delayed suspend lifted return status. */
+ status = TX_SUSPEND_LIFTED;
+ }
+ else
+ {
+
+ /* Setup invalid resume return status. */
+ status = TX_RESUME_ERROR;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_shell_entry.c b/common/src/tx_thread_shell_entry.c
new file mode 100644
index 00000000..67d61a40
--- /dev/null
+++ b/common/src/tx_thread_shell_entry.c
@@ -0,0 +1,201 @@
+/**************************************************************************/
+/* */
+/* 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_shell_entry PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calls the specified entry function of the thread. It */
+/* also provides a place for the thread's entry function to return. */
+/* If the thread returns, this function places the thread in a */
+/* "COMPLETED" state. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* thread_entry Thread's entry function */
+/* _tx_thread_system_suspend Thread suspension routine */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_shell_entry(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type);
+#endif
+
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_STARTED_EXTENSION(thread_ptr)
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has been entered! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
+ }
+#endif
+
+ /* Call current thread's entry function. */
+ (thread_ptr -> tx_thread_entry) (thread_ptr -> tx_thread_entry_parameter);
+
+ /* Suspend thread with a "completed" state. */
+
+ /* Determine if the application is using mutexes. */
+ if (_tx_thread_mutex_release != TX_NULL)
+ {
+
+ /* Yes, call the mutex release function via a function pointer that
+ is setup during mutex initialization. */
+ (_tx_thread_mutex_release)(thread_ptr);
+ }
+
+ /* Lockout interrupts while the thread state is setup. */
+ TX_DISABLE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine again. */
+ entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify;
+#endif
+
+ /* Set the status to suspending, in order to indicate the suspension
+ is in progress. */
+ thread_ptr -> tx_thread_state = TX_COMPLETED;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_COMPLETED)
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup for no timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
+
diff --git a/common/src/tx_thread_sleep.c b/common/src/tx_thread_sleep.c
new file mode 100644
index 00000000..2f24c438
--- /dev/null
+++ b/common/src/tx_thread_sleep.c
@@ -0,0 +1,198 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_sleep PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles application thread sleep requests. If the */
+/* sleep request was called from a non-thread, an error is returned. */
+/* */
+/* INPUT */
+/* */
+/* timer_ticks Number of timer ticks to sleep*/
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Actual thread suspension */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_sleep(ULONG timer_ticks)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+TX_THREAD *thread_ptr;
+
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Determine if this is a legal request. */
+
+ /* Is there a current thread? */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Illegal caller of this service. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Is the caller an ISR or Initialization? */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Illegal caller of this service. */
+ status = TX_CALLER_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Is the caller the system timer thread? */
+ else if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Illegal caller of this service. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Determine if the requested number of ticks is zero. */
+ else if (timer_ticks == ((ULONG) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Just return with a successful status. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SLEEP, TX_ULONG_TO_POINTER_CONVERT(timer_ticks), thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_SLEEP_INSERT
+
+ /* Suspend the current thread. */
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SLEEP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, timer_ticks);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Initialize the status to successful. */
+ thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
+
+ /* Setup the timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = timer_ticks;
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+ /* Return status to the caller. */
+ status = thread_ptr -> tx_thread_suspend_status;
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
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
+}
+
diff --git a/common/src/tx_thread_stack_error_handler.c b/common/src/tx_thread_stack_error_handler.c
new file mode 100644
index 00000000..46235137
--- /dev/null
+++ b/common/src/tx_thread_stack_error_handler.c
@@ -0,0 +1,105 @@
+/**************************************************************************/
+/* */
+/* 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_error_handler PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes stack errors detected during run-time. The */
+/* processing currently consists of a spin loop. */
+/* */
+/* 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_error_handler(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if the application has registered an error handler. */
+ if (_tx_thread_application_stack_error_handler != TX_NULL)
+ {
+
+ /* Yes, an error handler is present, simply call the application error handler. */
+ (_tx_thread_application_stack_error_handler)(thread_ptr);
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#else
+
+ /* Access input argument just for the sake of lint, MISRA, etc. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+#endif
+}
+
diff --git a/common/src/tx_thread_stack_error_notify.c b/common/src/tx_thread_stack_error_notify.c
new file mode 100644
index 00000000..abd456d2
--- /dev/null
+++ b/common/src/tx_thread_stack_error_notify.c
@@ -0,0 +1,125 @@
+/**************************************************************************/
+/* */
+/* 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"
+#ifdef TX_ENABLE_STACK_CHECKING
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_error_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application stack error handler. If */
+/* ThreadX detects a stack error, this application handler is called. */
+/* */
+/* Note: stack checking must be enabled for this routine to serve any */
+/* purpose via the TX_ENABLE_STACK_CHECKING define. */
+/* */
+/* INPUT */
+/* */
+/* stack_error_handler Pointer to stack error */
+/* handler, TX_NULL to disable */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_stack_error_notify(VOID (*stack_error_handler)(TX_THREAD *thread_ptr))
+{
+
+#ifndef TX_ENABLE_STACK_CHECKING
+
+UINT status;
+
+
+ /* Access input argument just for the sake of lint, MISRA, etc. */
+ if (stack_error_handler != TX_NULL)
+ {
+
+ /* Stack checking is not enabled, just return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Stack checking is not enabled, just return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Make entry in event log. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_STACK_ERROR_NOTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Make entry in event log. */
+ TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT
+
+ /* Setup global thread stack error handler. */
+ _tx_thread_application_stack_error_handler = stack_error_handler;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success to caller. */
+ return(TX_SUCCESS);
+#endif
+}
+
diff --git a/common/src/tx_thread_suspend.c b/common/src/tx_thread_suspend.c
new file mode 100644
index 00000000..20c83415
--- /dev/null
+++ b/common/src/tx_thread_suspend.c
@@ -0,0 +1,843 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
+#ifndef TX_NO_TIMER
+#include "tx_timer.h"
+#endif
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_suspend PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles application suspend requests. If the suspend */
+/* requires actual processing, this function calls the actual suspend */
+/* thread routine. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_suspend Actual thread suspension */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_suspend(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *current_thread;
+UINT status;
+
+
+#ifndef TX_INLINE_THREAD_RESUME_SUSPEND
+
+ /* Lockout interrupts while the thread is being suspended. */
+ TX_DISABLE
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_SUSPEND_INSERT
+
+ /* Check the specified thread's current status. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Initialize status to success. */
+ status = TX_SUCCESS;
+
+ /* Determine if we are in a thread context. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == 0)
+ {
+
+ /* Yes, we are in a thread context. */
+
+ /* Determine if the current thread is also the suspending thread. */
+ if (current_thread == thread_ptr)
+ {
+
+ /* Now determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Current thread cannot suspend when the preempt disable flag is non-zero,
+ return an error. */
+ status = TX_SUSPEND_ERROR;
+ }
+ }
+ }
+
+ /* Determine if the status is still successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup for no timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+
+ /* Temporarily disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifdef TX_MISRA_ENABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Return success. */
+ status = TX_SUCCESS;
+#else
+
+ /* If MISRA is not enabled, return directly. */
+ return(TX_SUCCESS);
+#endif
+ }
+ }
+ else if (thread_ptr -> tx_thread_state == TX_TERMINATED)
+ {
+
+ /* Thread is terminated. */
+ status = TX_SUSPEND_ERROR;
+ }
+ else if (thread_ptr -> tx_thread_state == TX_COMPLETED)
+ {
+
+ /* Thread is completed. */
+ status = TX_SUSPEND_ERROR;
+ }
+ else if (thread_ptr -> tx_thread_state == TX_SUSPENDED)
+ {
+
+ /* Already suspended, just set status to success. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Just set the delayed suspension flag. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_TRUE;
+
+ /* Set status to success. */
+ status = TX_SUCCESS;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Always return success, since this function does not perform error
+ checking. */
+ return(status);
+
+#else
+
+ /* In-line thread suspension processing follows, which is effectively just taking the
+ logic in tx_thread_system_suspend.c and placing it here! */
+
+UINT priority;
+UINT base_priority;
+ULONG priority_map;
+ULONG priority_bit;
+ULONG combined_flags;
+TX_THREAD *ready_next;
+TX_THREAD *ready_previous;
+
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *entry_ptr;
+ULONG time_stamp = ((ULONG) 0);
+#endif
+
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+ /* Lockout interrupts while the thread is being suspended. */
+ TX_DISABLE
+
+#ifndef TX_NO_TIMER
+
+ /* Determine if this is the current thread. */
+ if (thread_ptr == current_thread)
+ {
+
+ /* Yes, current thread is suspending - reset time slice for current thread. */
+ _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice;
+ }
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_SUSPEND_INSERT
+
+ /* Check the specified thread's current status. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Initialize status to success. */
+ status = TX_SUCCESS;
+
+ /* Determine if we are in a thread context. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == 0)
+ {
+
+ /* Yes, we are in a thread context. */
+
+ /* Determine if the current thread is also the suspending thread. */
+ if (current_thread == thread_ptr)
+ {
+
+ /* Now determine if the preempt disable flag is non-zero. */
+ if (_tx_thread_preempt_disable != ((UINT) 0))
+ {
+
+ /* Current thread cannot suspend when the preempt disable flag is non-zero,
+ return an error. */
+ status = TX_SUSPEND_ERROR;
+ }
+ }
+ }
+
+ /* Determine if the status is still successful. */
+ if (status == TX_SUCCESS)
+ {
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the thread's suspend count. */
+ thread_ptr -> tx_thread_performance_suspend_count++;
+
+ /* Increment the total number of thread suspensions. */
+ _tx_thread_performance_suspend_count++;
+#endif
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_SUSPENDED)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state)
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#endif
+
+ /* Log the thread status change. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, ((ULONG) thread_ptr -> tx_thread_state), TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS)
+
+#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
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Pickup the previous and next ready thread pointers. */
+ ready_next = thread_ptr -> tx_thread_ready_next;
+ ready_previous = thread_ptr -> tx_thread_ready_previous;
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ if (ready_next != thread_ptr)
+ {
+
+ /* Yes, there are other threads at this priority ready. */
+
+ /* Just remove this thread from the priority list. */
+ ready_next -> tx_thread_ready_previous = ready_previous;
+ ready_previous -> tx_thread_ready_next = ready_next;
+
+ /* Determine if this is the head of the priority list. */
+ if (_tx_thread_priority_list[priority] == thread_ptr)
+ {
+
+ /* Update the head pointer of this priority list. */
+ _tx_thread_priority_list[priority] = ready_next;
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Check for a thread preempted that had preemption threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+ }
+ }
+ else
+ {
+
+ /* This is the only thread at this priority ready to run. Set the head
+ pointer to NULL. */
+ _tx_thread_priority_list[priority] = TX_NULL;
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Clear this priority bit in the ready priority bit map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this priority map. */
+ if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this priority map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit));
+ }
+#endif
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Check for a thread preempted that had preemption-threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempted map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_priority_map_active;
+
+ /* Determine if there is anything. */
+ if (priority_map != ((ULONG) 0))
+ {
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+ }
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup working variable for the priority map. */
+ priority_map = _tx_thread_priority_maps[MAP_INDEX];
+
+ /* Make a quick check for no other threads ready for execution. */
+ if (priority_map == ((ULONG) 0))
+ {
+
+ /* Nothing else is ready. Set highest priority and execute thread
+ accordingly. */
+ _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES);
+ _tx_thread_execute_ptr = TX_NULL;
+
+#ifndef TX_MISRA_ENABLE
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0;
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* 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
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return(TX_SUCCESS);
+#endif
+ }
+ else
+ {
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the next highest priority variable. */
+ _tx_thread_highest_priority = base_priority + priority_bit;
+ }
+ }
+
+ /* Determine if this thread is the thread designated to execute. */
+ if (thread_ptr == _tx_thread_execute_ptr)
+ {
+
+ /* Pickup the highest priority thread to execute. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Determine if a previous thread with preemption-threshold was preempted. */
+#if TX_MAX_PRIORITIES > 32
+ if (_tx_thread_preempted_map_active != ((ULONG) 0))
+#else
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+#endif
+ {
+
+ /* Yes, there was a thread preempted when it was using preemption-threshold. */
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Interrupts are enabled briefly here to keep the interrupt
+ lockout time deterministic. */
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Decrement the preemption disable variable. */
+ _tx_thread_preempt_disable--;
+#endif
+
+ /* Calculate the thread with preemption threshold set that
+ was interrupted by a thread above the preemption level. */
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_preempted_map_active;
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup temporary preempted map. */
+ priority_map = _tx_thread_preempted_maps[MAP_INDEX];
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the highest priority preempted thread. */
+ priority = base_priority + priority_bit;
+
+ /* Determine if the next highest priority thread is above the highest priority threshold value. */
+ if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold))
+ {
+
+ /* Thread not allowed to execute until earlier preempted thread finishes or lowers its
+ preemption-threshold. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[priority];
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+ }
+#endif
+
+#ifndef TX_MISRA_ENABLE
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0;
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* 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
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return(TX_SUCCESS);
+#endif
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* Determine if an idle system return is present. */
+ if (_tx_thread_execute_ptr == TX_NULL)
+ {
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+ }
+ else
+ {
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+ }
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Return success. */
+ status = TX_SUCCESS;
+ }
+ }
+ else if (thread_ptr -> tx_thread_state == TX_TERMINATED)
+ {
+
+ /* Thread is terminated. */
+ status = TX_SUSPEND_ERROR;
+ }
+ else if (thread_ptr -> tx_thread_state == TX_COMPLETED)
+ {
+
+ /* Thread is completed. */
+ status = TX_SUSPEND_ERROR;
+ }
+ else if (thread_ptr -> tx_thread_state == TX_SUSPENDED)
+ {
+
+ /* Already suspended, just set status to success. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+ /* Just set the delayed suspension flag. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_TRUE;
+
+ /* Set status to success. */
+ status = TX_SUCCESS;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_thread_system_preempt_check.c b/common/src/tx_thread_system_preempt_check.c
new file mode 100644
index 00000000..0b92bb8b
--- /dev/null
+++ b/common/src/tx_thread_system_preempt_check.c
@@ -0,0 +1,127 @@
+/**************************************************************************/
+/* */
+/* 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_system_preempt_check PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for preemption that could have occurred as a */
+/* result scheduling activities occurring while the preempt disable */
+/* flag was set. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_return Return to the system */
+/* */
+/* CALLED BY */
+/* */
+/* Other ThreadX Components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_system_preempt_check(VOID)
+{
+
+ULONG combined_flags;
+TX_THREAD *current_thread;
+TX_THREAD *thread_ptr;
+
+
+ /* Combine the system state and preempt disable flags into one for comparison. */
+ TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags)
+
+ /* Determine if we are in a system state (ISR or Initialization) or internal preemption is disabled. */
+ if (combined_flags == ((ULONG) 0))
+ {
+
+ /* No, at thread execution level so continue checking for preemption. */
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Pickup the next execute pointer. */
+ thread_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if preemption should take place. */
+ if (current_thread != thread_ptr)
+ {
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if an idle system return is present. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+ }
+ else
+ {
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+ }
+#endif
+
+ /* Return to the system so the higher priority thread can be scheduled. */
+ _tx_thread_system_return();
+ }
+ }
+}
+
diff --git a/common/src/tx_thread_system_resume.c b/common/src/tx_thread_system_resume.c
new file mode 100644
index 00000000..b81b5d70
--- /dev/null
+++ b/common/src/tx_thread_system_resume.c
@@ -0,0 +1,1002 @@
+/**************************************************************************/
+/* */
+/* 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"
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+#include "tx_initialize.h"
+#endif
+#include "tx_trace.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_resume PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the specified thread on the list of ready */
+/* threads at the thread's specific priority. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to resume */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_return Return to the system */
+/* _tx_thread_system_ni_resume Noninterruptable thread resume*/
+/* _tx_timer_system_deactivate Timer deactivate */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Thread create function */
+/* _tx_thread_priority_change Thread priority change */
+/* _tx_thread_resume Application resume service */
+/* _tx_thread_timeout Thread timeout */
+/* _tx_thread_wait_abort Thread wait abort */
+/* Other ThreadX Components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_system_resume(TX_THREAD *thread_ptr)
+#ifndef TX_NOT_INTERRUPTABLE
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+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
+
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+#ifndef TX_NO_TIMER
+
+ /* Deactivate the timeout timer if necessary. */
+ if (thread_ptr -> tx_thread_timer.tx_timer_internal_list_head != TX_NULL)
+ {
+
+ /* Deactivate the thread's timeout timer. */
+ _tx_timer_system_deactivate(&(thread_ptr -> tx_thread_timer));
+ }
+ else
+ {
+
+ /* Clear the remaining time to ensure timer doesn't get activated. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+ }
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#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
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time we have
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+ /* Decrease the preempt disabled count. */
+ _tx_thread_preempt_disable--;
+
+ /* Determine if the thread is in the process of suspending. If so, the thread
+ control block is already on the linked list so nothing needs to be done. */
+ if (thread_ptr -> tx_thread_suspending == TX_FALSE)
+ {
+
+ /* Thread is not in the process of suspending. Now check to make sure the thread
+ has not already been resumed. */
+ if (thread_ptr -> tx_thread_state != TX_READY)
+ {
+
+ /* No, now check to see if the delayed suspension flag is set. */
+ if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE)
+ {
+
+ /* Resume the thread! */
+
+ /* Make this thread ready. */
+
+ /* Change the state to ready. */
+ thread_ptr -> tx_thread_state = TX_READY;
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)
+
+#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
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ head_ptr = _tx_thread_priority_list[priority];
+ if (head_ptr == TX_NULL)
+ {
+
+ /* First thread at this priority ready. Add to the front of the list. */
+ _tx_thread_priority_list[priority] = thread_ptr;
+ thread_ptr -> tx_thread_ready_next = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = thread_ptr;
+
+#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
+
+ /* Or in the thread's priority bit. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit;
+
+ /* Determine if this newly ready thread is the highest priority. */
+ if (priority < _tx_thread_highest_priority)
+ {
+
+ /* A new highest priority thread is present. */
+
+ /* Update the highest priority variable. */
+ _tx_thread_highest_priority = priority;
+
+ /* Pickup the execute pointer. Since it is going to be referenced multiple
+ times, it is placed in a local variable. */
+ execute_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if no thread is currently executing. */
+ if (execute_ptr == TX_NULL)
+ {
+
+ /* Simply setup the execute pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+ }
+ else
+ {
+
+ /* Another thread has been scheduled for execution. */
+
+ /* Check to see if this is a higher priority thread and determine if preemption is allowed. */
+ if (priority < execute_ptr -> tx_thread_preempt_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
+
+ /* 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
+
+ /* 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)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
+ }
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if the caller is an interrupt or from a thread. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
+ {
+
+ /* Caller is a thread, so this is a solicited preemption. */
+ _tx_thread_performance_solicited_preemption_count++;
+
+ /* Increment the thread's solicited preemption counter. */
+ execute_ptr -> tx_thread_performance_solicited_preemption_count++;
+ }
+ else
+ {
+
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Caller is an interrupt, so this is an interrupt preemption. */
+ _tx_thread_performance_interrupt_preemption_count++;
+
+ /* Increment the thread's interrupt preemption counter. */
+ execute_ptr -> tx_thread_performance_interrupt_preemption_count++;
+ }
+ }
+
+ /* Remember the thread that preempted this thread. */
+ execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr;
+
+#endif
+
+ /* Yes, modify the execute thread pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+#ifndef TX_MISRA_ENABLE
+
+ /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return in-line when MISRA is not enabled. */
+ return;
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* No, there are other threads at this priority already ready. */
+
+ /* Just add this thread to the priority list. */
+ tail_ptr = head_ptr -> tx_thread_ready_previous;
+ tail_ptr -> tx_thread_ready_next = thread_ptr;
+ head_ptr -> tx_thread_ready_previous = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = tail_ptr;
+ thread_ptr -> tx_thread_ready_next = head_ptr;
+ }
+ }
+
+ /* Else, delayed suspend flag was set. */
+ else
+ {
+
+ /* Clear the delayed suspend flag and change the state. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_FALSE;
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+ }
+ }
+ }
+ else
+ {
+
+ /* A resumption occurred in the middle of a previous thread suspension. */
+
+ /* Make sure the type of suspension under way is not a terminate or
+ thread completion. In either of these cases, do not void the
+ interrupted suspension processing. */
+ if (thread_ptr -> tx_thread_state != TX_COMPLETED)
+ {
+
+ /* Make sure the thread isn't terminated. */
+ if (thread_ptr -> tx_thread_state != TX_TERMINATED)
+ {
+
+ /* No, now check to see if the delayed suspension flag is set. */
+ if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE)
+ {
+
+ /* Clear the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_FALSE;
+
+ /* Restore the state to ready. */
+ thread_ptr -> tx_thread_state = TX_READY;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)
+ }
+ else
+ {
+
+ /* Clear the delayed suspend flag and change the state. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_FALSE;
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+ }
+
+#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
+ }
+ }
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+}
+#else
+{
+
+TX_INTERRUPT_SAVE_AREA
+#ifdef TX_ENABLE_EVENT_TRACE
+UINT temp_state;
+#endif
+UINT state;
+
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+ /* Decrease the preempt disabled count. */
+ _tx_thread_preempt_disable--;
+
+ /* Determine if the thread is in the process of suspending. If so, the thread
+ control block is already on the linked list so nothing needs to be done. */
+ if (thread_ptr -> tx_thread_suspending == TX_FALSE)
+ {
+
+ /* Call the non-interruptable thread system resume function. */
+ _tx_thread_system_ni_resume(thread_ptr);
+ }
+ else
+ {
+
+ /* A resumption occurred in the middle of a previous thread suspension. */
+
+ /* Pickup the current thread state. */
+ state = thread_ptr -> tx_thread_state;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Move the state into a different variable for MISRA compliance. */
+ temp_state = state;
+#endif
+
+ /* Log the thread status change. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, ((ULONG) state), TX_POINTER_TO_ULONG_CONVERT(&temp_state), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS)
+
+ /* Make sure the type of suspension under way is not a terminate or
+ thread completion. In either of these cases, do not void the
+ interrupted suspension processing. */
+ if (state != TX_COMPLETED)
+ {
+
+ /* Check for terminated thread. */
+ if (state != TX_TERMINATED)
+ {
+
+ /* Clear the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_FALSE;
+
+ /* Restore the state to ready. */
+ thread_ptr -> tx_thread_state = TX_READY;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)
+
+#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
+ }
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+
+/* Define the non-interruptable version of thread resume. It is assumed at this point that
+ all interrupts are disabled and will remain so during this function. */
+
+VOID _tx_thread_system_ni_resume(TX_THREAD *thread_ptr)
+{
+
+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
+
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#endif
+
+ /* Log the thread status change. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, ((ULONG) 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
+
+ /* Save the time stamp for later comparison to verify that
+ the event hasn't been overwritten by the time we have
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+
+#ifndef TX_NO_TIMER
+
+ /* Deactivate the timeout timer if necessary. */
+ if (thread_ptr -> tx_thread_timer.tx_timer_internal_list_head != TX_NULL)
+ {
+
+ /* Deactivate the thread's timeout timer. */
+ _tx_timer_system_deactivate(&(thread_ptr -> tx_thread_timer));
+ }
+#endif
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+ /* Thread is not in the process of suspending. Now check to make sure the thread
+ has not already been resumed. */
+ if (thread_ptr -> tx_thread_state != TX_READY)
+ {
+
+ /* No, now check to see if the delayed suspension flag is set. */
+ if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE)
+ {
+
+ /* Resume the thread! */
+
+ /* Make this thread ready. */
+
+ /* Change the state to ready. */
+ thread_ptr -> tx_thread_state = TX_READY;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY)
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+#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
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ head_ptr = _tx_thread_priority_list[priority];
+ if (head_ptr == TX_NULL)
+ {
+
+ /* First thread at this priority ready. Add to the front of the list. */
+ _tx_thread_priority_list[priority] = thread_ptr;
+ thread_ptr -> tx_thread_ready_next = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = thread_ptr;
+
+#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
+
+ /* Or in the thread's priority bit. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit;
+
+ /* Determine if this newly ready thread is the highest priority. */
+ if (priority < _tx_thread_highest_priority)
+ {
+
+ /* A new highest priority thread is present. */
+
+ /* Update the highest priority variable. */
+ _tx_thread_highest_priority = priority;
+
+ /* Pickup the execute pointer. Since it is going to be referenced multiple
+ times, it is placed in a local variable. */
+ execute_ptr = _tx_thread_execute_ptr;
+
+ /* Determine if no thread is currently executing. */
+ if (execute_ptr == TX_NULL)
+ {
+
+ /* Simply setup the execute pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+ }
+ else
+ {
+
+ /* Check to see if this is a higher priority thread and determine if preemption is allowed. */
+ if (priority < execute_ptr -> tx_thread_preempt_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
+
+ /* 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
+
+ /* 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)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
+ }
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if the caller is an interrupt or from a thread. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
+ {
+
+ /* Caller is a thread, so this is a solicited preemption. */
+ _tx_thread_performance_solicited_preemption_count++;
+
+ /* Increment the thread's solicited preemption counter. */
+ execute_ptr -> tx_thread_performance_solicited_preemption_count++;
+ }
+ else
+ {
+
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Caller is an interrupt, so this is an interrupt preemption. */
+ _tx_thread_performance_interrupt_preemption_count++;
+
+ /* Increment the thread's interrupt preemption counter. */
+ execute_ptr -> tx_thread_performance_interrupt_preemption_count++;
+ }
+ }
+
+ /* Remember the thread that preempted this thread. */
+ execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr;
+#endif
+
+ /* Yes, modify the execute thread pointer. */
+ _tx_thread_execute_ptr = thread_ptr;
+
+#ifndef TX_MISRA_ENABLE
+
+ /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+ }
+ }
+#endif
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return in-line when MISRA is not enabled. */
+ return;
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* No, there are other threads at this priority already ready. */
+
+ /* Just add this thread to the priority list. */
+ tail_ptr = head_ptr -> tx_thread_ready_previous;
+ tail_ptr -> tx_thread_ready_next = thread_ptr;
+ head_ptr -> tx_thread_ready_previous = thread_ptr;
+ thread_ptr -> tx_thread_ready_previous = tail_ptr;
+ thread_ptr -> tx_thread_ready_next = head_ptr;
+ }
+ }
+
+ /* Else, delayed suspend flag was set. */
+ else
+ {
+
+ /* Clear the delayed suspend flag and change the state. */
+ thread_ptr -> tx_thread_delayed_suspend = TX_FALSE;
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+ }
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ resume event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Does the timestamp match? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* 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
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* There is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+}
+#endif
diff --git a/common/src/tx_thread_system_suspend.c b/common/src/tx_thread_system_suspend.c
new file mode 100644
index 00000000..f3880e24
--- /dev/null
+++ b/common/src/tx_thread_system_suspend.c
@@ -0,0 +1,1218 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_suspend PORTABLE C */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function suspends the specified thread and changes the thread */
+/* state to the value specified. Note: delayed suspension processing */
+/* is handled outside of this routine. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_return Return to system */
+/* _tx_thread_system_preempt_check System preemption check */
+/* _tx_timer_system_activate Activate timer for timeout */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_priority_change Thread priority change */
+/* _tx_thread_shell_entry Thread shell function */
+/* _tx_thread_sleep Thread sleep */
+/* _tx_thread_suspend Application thread suspend */
+/* _tx_thread_terminate Thread terminate */
+/* Other ThreadX Components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr)
+#ifndef TX_NOT_INTERRUPTABLE
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT priority;
+UINT base_priority;
+ULONG priority_map;
+ULONG priority_bit;
+ULONG combined_flags;
+TX_THREAD *ready_next;
+TX_THREAD *ready_previous;
+TX_THREAD *current_thread;
+
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+
+#ifndef TX_NO_TIMER
+ULONG timeout;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *entry_ptr;
+ULONG time_stamp = ((ULONG) 0);
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+ /* Lockout interrupts while the thread is being suspended. */
+ TX_DISABLE
+
+#ifndef TX_NO_TIMER
+
+ /* Is the current thread suspending? */
+ if (thread_ptr == current_thread)
+ {
+
+ /* Pickup the wait option. */
+ timeout = thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks;
+
+ /* Determine if an activation is needed. */
+ if (timeout != TX_NO_WAIT)
+ {
+
+ /* Make sure the suspension is not a wait-forever. */
+ if (timeout != TX_WAIT_FOREVER)
+ {
+
+ /* Activate the thread timer with the timeout value setup in the caller. */
+ _tx_timer_system_activate(&(thread_ptr -> tx_thread_timer));
+ }
+ }
+
+ /* Yes, reset time slice for current thread. */
+ _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice;
+ }
+#endif
+
+ /* Decrease the preempt disabled count. */
+ _tx_thread_preempt_disable--;
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the thread's suspend count. */
+ thread_ptr -> tx_thread_performance_suspend_count++;
+
+ /* Increment the total number of thread suspensions. */
+ _tx_thread_performance_suspend_count++;
+#endif
+
+ /* Check to make sure the thread suspending flag is still set. If not, it
+ has already been resumed. */
+ if (thread_ptr -> tx_thread_suspending == TX_TRUE)
+ {
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, thread_ptr -> tx_thread_state)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state)
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#endif
+
+ /* Log the thread status change. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS)
+
+#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
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+ /* Actually suspend this thread. But first, clear the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_FALSE;
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Pickup the next ready thread pointer. */
+ ready_next = thread_ptr -> tx_thread_ready_next;
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ if (ready_next != thread_ptr)
+ {
+
+ /* Yes, there are other threads at this priority ready. */
+
+ /* Pickup the previous ready thread pointer. */
+ ready_previous = thread_ptr -> tx_thread_ready_previous;
+
+ /* Just remove this thread from the priority list. */
+ ready_next -> tx_thread_ready_previous = ready_previous;
+ ready_previous -> tx_thread_ready_next = ready_next;
+
+ /* Determine if this is the head of the priority list. */
+ if (_tx_thread_priority_list[priority] == thread_ptr)
+ {
+
+ /* Update the head pointer of this priority list. */
+ _tx_thread_priority_list[priority] = ready_next;
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Check for a thread preempted that had preemption threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+ }
+ }
+ else
+ {
+
+ /* This is the only thread at this priority ready to run. Set the head
+ pointer to NULL. */
+ _tx_thread_priority_list[priority] = TX_NULL;
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Clear this priority bit in the ready priority bit map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this priority map. */
+ if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this priority map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit));
+ }
+#endif
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Check for a thread preempted that had preemption-threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempted map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_priority_map_active;
+
+ /* Determine if there is anything. */
+ if (priority_map != ((ULONG) 0))
+ {
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+ }
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup working variable for the priority map. */
+ priority_map = _tx_thread_priority_maps[MAP_INDEX];
+
+ /* Make a quick check for no other threads ready for execution. */
+ if (priority_map == ((ULONG) 0))
+ {
+
+ /* Nothing else is ready. Set highest priority and execute thread
+ accordingly. */
+ _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES);
+ _tx_thread_execute_ptr = TX_NULL;
+
+#ifndef TX_MISRA_ENABLE
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0;
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* 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
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return;
+#endif
+ }
+ else
+ {
+
+ /* Other threads at different priority levels are ready to run. */
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the next highest priority variable. */
+ _tx_thread_highest_priority = base_priority + ((UINT) priority_bit);
+ }
+ }
+
+ /* Determine if the suspending thread is the thread designated to execute. */
+ if (thread_ptr == _tx_thread_execute_ptr)
+ {
+
+ /* Pickup the highest priority thread to execute. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Determine if a previous thread with preemption-threshold was preempted. */
+#if TX_MAX_PRIORITIES > 32
+ if (_tx_thread_preempted_map_active != ((ULONG) 0))
+#else
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+#endif
+ {
+
+ /* Yes, there was a thread preempted when it was using preemption-threshold. */
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Interrupts are enabled briefly here to keep the interrupt
+ lockout time deterministic. */
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Decrement the preemption disable variable. */
+ _tx_thread_preempt_disable--;
+
+ /* Calculate the thread with preemption threshold set that
+ was interrupted by a thread above the preemption level. */
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_preempted_map_active;
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup temporary preempted map. */
+ priority_map = _tx_thread_preempted_maps[MAP_INDEX];
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the highest priority preempted thread. */
+ priority = base_priority + ((UINT) priority_bit);
+
+ /* Determine if the next highest priority thread is above the highest priority threshold value. */
+ if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold))
+ {
+
+ /* Thread not allowed to execute until earlier preempted thread finishes or lowers its
+ preemption-threshold. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[priority];
+
+ /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+ }
+#endif
+
+#ifndef TX_MISRA_ENABLE
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+ }
+ }
+#endif
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* 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
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return;
+#endif
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* Determine if an idle system return is present. */
+ if (_tx_thread_execute_ptr == TX_NULL)
+ {
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+ }
+ else
+ {
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+ }
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+
+ /* Return to caller. */
+ return;
+}
+#else
+/* Define the entry function for modules assuming the interruptable version of system suspend. */
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG wait_option;
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if the thread is still suspending. */
+ if (thread_ptr -> tx_thread_suspending == TX_TRUE)
+ {
+
+ /* Yes, prepare to call the non-interruptable system suspend function. */
+
+ /* Clear the thread suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_FALSE;
+
+ /* Pickup the wait option. */
+ wait_option = thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks;
+
+ /* Decrement the preempt disable count. */
+ _tx_thread_preempt_disable--;
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+}
+
+/* Define the system suspend function that is not interruptable, i.e., it is assumed that
+ interrupts are disabled upon calling this function. */
+
+VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option)
+{
+
+UINT priority;
+UINT base_priority;
+ULONG priority_map;
+ULONG priority_bit;
+ULONG combined_flags;
+TX_THREAD *ready_next;
+TX_THREAD *ready_previous;
+TX_THREAD *current_thread;
+
+#if TX_MAX_PRIORITIES > 32
+UINT map_index;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *entry_ptr;
+ULONG time_stamp = ((ULONG) 0);
+#endif
+
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+#ifndef TX_NO_TIMER
+
+
+ /* Determine if a timeout needs to be activated. */
+ if (thread_ptr == current_thread)
+ {
+
+ /* Is there a wait option? */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Make sure it is not a wait-forever option. */
+ if (wait_option != TX_WAIT_FOREVER)
+ {
+
+ /* Setup the wait option. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
+
+ /* Activate the thread timer with the timeout value setup in the caller. */
+ _tx_timer_system_activate(&(thread_ptr -> tx_thread_timer));
+ }
+ }
+
+ /* Reset time slice for current thread. */
+ _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice;
+ }
+#endif
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+#endif
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the thread's suspend count. */
+ thread_ptr -> tx_thread_performance_suspend_count++;
+
+ /* Increment the total number of thread suspensions. */
+ _tx_thread_performance_suspend_count++;
+#endif
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, thread_ptr -> tx_thread_state)
+
+ /* Log the thread status change. */
+ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state)
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, save the current event pointer. */
+ entry_ptr = _tx_trace_buffer_current_ptr;
+#endif
+
+ /* Log the thread status change. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS)
+
+#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
+ computed the next thread to execute. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Save time stamp. */
+ time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
+ }
+#endif
+
+ /* Pickup priority of thread. */
+ priority = thread_ptr -> tx_thread_priority;
+
+ /* Pickup the next ready thread pointer. */
+ ready_next = thread_ptr -> tx_thread_ready_next;
+
+ /* Determine if there are other threads at this priority that are
+ ready. */
+ if (ready_next != thread_ptr)
+ {
+
+ /* Yes, there are other threads at this priority ready. */
+
+ /* Pickup the previous ready thread pointer. */
+ ready_previous = thread_ptr -> tx_thread_ready_previous;
+
+ /* Just remove this thread from the priority list. */
+ ready_next -> tx_thread_ready_previous = ready_previous;
+ ready_previous -> tx_thread_ready_next = ready_next;
+
+ /* Determine if this is the head of the priority list. */
+ if (_tx_thread_priority_list[priority] == thread_ptr)
+ {
+
+ /* Update the head pointer of this priority list. */
+ _tx_thread_priority_list[priority] = ready_next;
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Check for a thread preempted that had preemption threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+ }
+ }
+ else
+ {
+
+ /* This is the only thread at this priority ready to run. Set the head
+ pointer to NULL. */
+ _tx_thread_priority_list[priority] = TX_NULL;
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index into the bit map array. */
+ map_index = priority/((UINT) 32);
+#endif
+
+ /* Clear this priority bit in the ready priority bit map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this priority map. */
+ if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this priority map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit));
+ }
+#endif
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Check for a thread preempted that had preemption-threshold set. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+ {
+
+ /* Ensure that this thread's priority is clear in the preempt map. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempted map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+#endif
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_priority_map_active;
+
+ /* Determine if there is anything. */
+ if (priority_map != ((ULONG) 0))
+ {
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+ }
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup working variable for the priority map. */
+ priority_map = _tx_thread_priority_maps[MAP_INDEX];
+
+ /* Make a quick check for no other threads ready for execution. */
+ if (priority_map == ((ULONG) 0))
+ {
+
+ /* Nothing else is ready. Set highest priority and execute thread
+ accordingly. */
+ _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES);
+ _tx_thread_execute_ptr = TX_NULL;
+
+#ifndef TX_MISRA_ENABLE
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0;
+ }
+ }
+#endif
+
+ /* 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
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return;
+#endif
+ }
+ else
+ {
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the next highest priority variable. */
+ _tx_thread_highest_priority = base_priority + ((UINT) priority_bit);
+ }
+ }
+
+ /* Determine if the suspending thread is the thread designated to execute. */
+ if (thread_ptr == _tx_thread_execute_ptr)
+ {
+
+ /* Pickup the highest priority thread to execute. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
+
+ /* Determine if a previous thread with preemption-threshold was preempted. */
+#if TX_MAX_PRIORITIES > 32
+ if (_tx_thread_preempted_map_active != ((ULONG) 0))
+#else
+ if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0))
+#endif
+ {
+
+ /* Yes, there was a thread preempted when it was using preemption-threshold. */
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Decrement the preemption disable variable. */
+ _tx_thread_preempt_disable--;
+
+ /* Calculate the thread with preemption threshold set that
+ was interrupted by a thread above the preemption level. */
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Calculate the index to find the next highest priority thread ready for execution. */
+ priority_map = _tx_thread_preempted_map_active;
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index)
+
+ /* Calculate the base priority as well. */
+ base_priority = map_index * ((UINT) 32);
+#else
+
+ /* Setup the base priority to zero. */
+ base_priority = ((UINT) 0);
+#endif
+
+ /* Setup temporary preempted map. */
+ priority_map = _tx_thread_preempted_maps[MAP_INDEX];
+
+ /* Calculate the lowest bit set in the priority map. */
+ TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit)
+
+ /* Setup the highest priority preempted thread. */
+ priority = base_priority + ((UINT) priority_bit);
+
+ /* Determine if the next highest priority thread is above the highest priority threshold value. */
+ if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold))
+ {
+
+ /* Thread not allowed to execute until earlier preempted thread finishes or lowers its
+ preemption-threshold. */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[priority];
+
+ /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */
+ TX_MOD32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
+
+#if TX_MAX_PRIORITIES > 32
+
+ /* Determine if there are any other bits set in this preempt map. */
+ if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
+ {
+
+ /* No, clear the active bit to signify this preempt map has nothing set. */
+ TX_DIV32_BIT_SET(priority, priority_bit)
+ _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
+ }
+#endif
+ }
+ }
+#endif
+
+#ifndef TX_MISRA_ENABLE
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+ }
+ }
+#endif
+
+ /* 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
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+
+ /* Return to caller. */
+ return;
+#endif
+ }
+
+#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)
+ {
+
+ /* Move to next entry. */
+ _tx_thread_performance__execute_log_index++;
+
+ /* Check for wrap condition. */
+ if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
+ {
+
+ /* Set the index to the beginning. */
+ _tx_thread_performance__execute_log_index = ((UINT) 0);
+ }
+
+ /* Log the new execute pointer. */
+ _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
+ }
+#endif
+
+#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
+ suspend event. In that case, do nothing here. */
+ if (entry_ptr != TX_NULL)
+ {
+
+ /* Is the timestamp the same? */
+ if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
+ {
+
+ /* Timestamp is the same, set the "next thread pointer" to the new value of the
+ next thread to execute. This can be used by the trace analysis tool to keep
+ track of next thread execution. */
+#ifdef TX_MISRA_ENABLE
+ entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#else
+ entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr);
+#endif
+ }
+ }
+#endif
+
+ /* Determine if a preemption condition is present. */
+ if (current_thread != _tx_thread_execute_ptr)
+ {
+
+#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
+
+ /* 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
+
+ /* Determine if an idle system return is present. */
+ if (_tx_thread_execute_ptr == TX_NULL)
+ {
+
+ /* Yes, increment the return to idle return count. */
+ _tx_thread_performance_idle_return_count++;
+ }
+ else
+ {
+
+ /* No, there is another thread ready to run and will be scheduled upon return. */
+ _tx_thread_performance_non_idle_return_count++;
+ }
+#endif
+
+ /* Preemption is needed - return to the system! */
+ _tx_thread_system_return();
+ }
+ }
+
+ /* Return to caller. */
+ return;
+}
+#endif
+
diff --git a/common/src/tx_thread_terminate.c b/common/src/tx_thread_terminate.c
new file mode 100644
index 00000000..012d128e
--- /dev/null
+++ b/common/src/tx_thread_terminate.c
@@ -0,0 +1,310 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_terminate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles application thread terminate requests. Once */
+/* a thread is terminated, it cannot be executed again unless it is */
+/* deleted and recreated. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_system_deactivate Timer deactivate function */
+/* _tx_thread_system_suspend Actual thread suspension */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend */
+/* thread */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* Suspend Cleanup Routine Suspension cleanup function */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_terminate(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence);
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id);
+#endif
+UINT status;
+ULONG suspension_sequence;
+
+
+ /* Default to successful completion. */
+ status = TX_SUCCESS;
+
+ /* Lockout interrupts while the thread is being terminated. */
+ TX_DISABLE
+
+ /* Deactivate thread timer, if active. */
+ _tx_timer_system_deactivate(&thread_ptr -> tx_thread_timer);
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TERMINATE, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&suspend_cleanup), 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_TERMINATE_INSERT
+
+ /* Is the thread already terminated? */
+ if (thread_ptr -> tx_thread_state == TX_TERMINATED)
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return success since thread is already terminated. */
+ status = TX_SUCCESS;
+ }
+
+ /* Check the specified thread's current status. */
+ else if (thread_ptr -> tx_thread_state != TX_COMPLETED)
+ {
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify;
+#endif
+
+ /* Check to see if the thread is currently ready. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Set the state to terminated. */
+ thread_ptr -> tx_thread_state = TX_TERMINATED;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED)
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Setup for no timeout period. */
+ thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
+
+ /* Disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Since the thread is currently ready, we don't need to
+ worry about calling the suspend cleanup routine! */
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+ else
+ {
+
+ /* Change the state to terminated. */
+ thread_ptr -> tx_thread_state = TX_TERMINATED;
+
+ /* Thread state change. */
+ TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED)
+
+ /* Set the suspending flag. This prevents the thread from being
+ resumed before the cleanup routine is executed. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Pickup the cleanup routine address. */
+ suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Pickup the suspension sequence number that is used later to verify that the
+ cleanup is still necessary. */
+ suspension_sequence = thread_ptr -> tx_thread_suspension_sequence;
+#else
+
+ /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */
+ suspension_sequence = ((ULONG) 0);
+#endif
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Call any cleanup routines. */
+ if (suspend_cleanup != TX_NULL)
+ {
+
+ /* Yes, there is a function to call. */
+ (suspend_cleanup)(thread_ptr, suspension_sequence);
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+
+ /* Clear the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_FALSE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Perform any additional activities for tool or user purpose. */
+ TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Determine if the application is using mutexes. */
+ if (_tx_thread_mutex_release != TX_NULL)
+ {
+
+ /* Yes, call the mutex release function via a function pointer that
+ is setup during initialization. */
+ (_tx_thread_mutex_release)(thread_ptr);
+ }
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Disable interrupts. */
+ TX_DISABLE
+#endif
+
+ /* Enable preemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_thread_time_slice.c b/common/src/tx_thread_time_slice.c
new file mode 100644
index 00000000..d629ab9a
--- /dev/null
+++ b/common/src/tx_thread_time_slice.c
@@ -0,0 +1,184 @@
+/**************************************************************************/
+/* */
+/* 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_timer.h"
+#include "tx_thread.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_time_slice PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function moves the currently executing thread to the end of */
+/* the threads ready at the same priority level as a result of a */
+/* time-slice interrupt. If no other thread of the same priority is */
+/* ready, this function simply returns. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_timer_interrupt Timer interrupt handling */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_time_slice(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+#ifdef TX_ENABLE_STACK_CHECKING
+TX_THREAD *next_thread_ptr;
+#endif
+#ifdef TX_ENABLE_EVENT_TRACE
+ULONG system_state;
+UINT preempt_disable;
+#endif
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Check this thread's stack. */
+ TX_THREAD_STACK_CHECK(thread_ptr)
+
+ /* Set the next thread pointer to NULL. */
+ next_thread_ptr = TX_NULL;
+#endif
+
+ /* Lockout interrupts while the time-slice is evaluated. */
+ TX_DISABLE
+
+ /* Clear the expired time-slice flag. */
+ _tx_timer_expired_time_slice = TX_FALSE;
+
+ /* Make sure the thread pointer is valid. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Make sure the thread is still active, i.e. not suspended. */
+ if (thread_ptr -> tx_thread_state == TX_READY)
+ {
+
+ /* Setup a fresh time-slice for the thread. */
+ thread_ptr -> tx_thread_time_slice = thread_ptr -> tx_thread_new_time_slice;
+
+ /* Reset the actual time-slice variable. */
+ _tx_timer_time_slice = thread_ptr -> tx_thread_time_slice;
+
+ /* Determine if there is another thread at the same priority and preemption-threshold
+ is not set. Preemption-threshold overrides time-slicing. */
+ if (thread_ptr -> tx_thread_ready_next != thread_ptr)
+ {
+
+ /* Check to see if preemption-threshold is not being used. */
+ if (thread_ptr -> tx_thread_priority == thread_ptr -> tx_thread_preempt_threshold)
+ {
+
+ /* Preemption-threshold is not being used by this thread. */
+
+ /* There is another thread at this priority, make it the highest at
+ this priority level. */
+ _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr -> tx_thread_ready_next;
+
+ /* Designate the highest priority thread as the one to execute. Don't use this
+ thread's priority as an index just in case a higher priority thread is now
+ ready! */
+ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the thread's time-slice counter. */
+ thread_ptr -> tx_thread_performance_time_slice_count++;
+
+ /* Increment the total number of thread time-slice operations. */
+ _tx_thread_performance_time_slice_count++;
+#endif
+
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Pickup the next execute pointer. */
+ next_thread_ptr = _tx_thread_execute_ptr;
+#endif
+ }
+ }
+ }
+ }
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Pickup the volatile information. */
+ system_state = TX_THREAD_GET_SYSTEM_STATE();
+ preempt_disable = _tx_thread_preempt_disable;
+
+ /* Insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SLICE, _tx_thread_execute_ptr, system_state, preempt_disable, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_INTERNAL_EVENTS)
+#endif
+
+ /* Restore previous interrupt posture. */
+ TX_RESTORE
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+ /* Determine if there is a next thread pointer to perform stack checking on. */
+ if (next_thread_ptr != TX_NULL)
+ {
+
+ /* Yes, check this thread's stack. */
+ TX_THREAD_STACK_CHECK(next_thread_ptr)
+ }
+#endif
+}
+
diff --git a/common/src/tx_thread_time_slice_change.c b/common/src/tx_thread_time_slice_change.c
new file mode 100644
index 00000000..19ca83fc
--- /dev/null
+++ b/common/src/tx_thread_time_slice_change.c
@@ -0,0 +1,117 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_time_slice_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes thread time slice change requests. The */
+/* previous time slice is returned to the caller. If the new request */
+/* is made for an executing thread, it is also placed in the actual */
+/* time-slice countdown variable. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* new_time_slice New time slice */
+/* old_time_slice Old time slice */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *current_thread;
+
+
+ /* Lockout interrupts while the thread is being resumed. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TIME_SLICE_CHANGE, thread_ptr, new_time_slice, thread_ptr -> tx_thread_new_time_slice, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT
+
+ /* Return the old time slice. */
+ *old_time_slice = thread_ptr -> tx_thread_new_time_slice;
+
+ /* Setup the new time-slice. */
+ thread_ptr -> tx_thread_time_slice = new_time_slice;
+ thread_ptr -> tx_thread_new_time_slice = new_time_slice;
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Determine if this thread is the currently executing thread. */
+ if (thread_ptr == current_thread)
+ {
+
+ /* Yes, update the time-slice countdown variable. */
+ _tx_timer_time_slice = new_time_slice;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_thread_timeout.c b/common/src/tx_thread_timeout.c
new file mode 100644
index 00000000..0ac5c022
--- /dev/null
+++ b/common/src/tx_thread_timeout.c
@@ -0,0 +1,164 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_timeout PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles thread timeout processing. Timeouts occur in */
+/* two flavors, namely the thread sleep timeout and all other service */
+/* call timeouts. Thread sleep timeouts are processed locally, while */
+/* the others are processed by the appropriate suspension clean-up */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* timeout_input Contains the thread pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* Suspension Cleanup Functions */
+/* _tx_thread_system_resume Resume thread */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_timer_expiration_process Timer expiration function */
+/* _tx_timer_thread_entry Timer thread function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_timeout(ULONG timeout_input)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence);
+ULONG suspension_sequence;
+
+
+ /* Pickup the thread pointer. */
+ TX_THREAD_TIMEOUT_POINTER_SETUP(thread_ptr)
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine how the thread is currently suspended. */
+ if (thread_ptr -> tx_thread_state == TX_SLEEP)
+ {
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Increment the disable preemption flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Lift the suspension on the sleeping thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+ }
+ else
+ {
+
+ /* Process all other suspension timeouts. */
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total number of thread timeouts. */
+ _tx_thread_performance_timeout_count++;
+
+ /* Increment the number of timeouts for this thread. */
+ thread_ptr -> tx_thread_performance_timeout_count++;
+#endif
+
+ /* Pickup the cleanup routine address. */
+ suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Pickup the suspension sequence number that is used later to verify that the
+ cleanup is still necessary. */
+ suspension_sequence = thread_ptr -> tx_thread_suspension_sequence;
+#else
+
+ /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */
+ suspension_sequence = ((ULONG) 0);
+#endif
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Call any cleanup routines. */
+ if (suspend_cleanup != TX_NULL)
+ {
+ /* Yes, there is a function to call. */
+ (suspend_cleanup)(thread_ptr, suspension_sequence);
+ }
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+ }
+}
+
diff --git a/common/src/tx_thread_wait_abort.c b/common/src/tx_thread_wait_abort.c
new file mode 100644
index 00000000..c590e17a
--- /dev/null
+++ b/common/src/tx_thread_wait_abort.c
@@ -0,0 +1,235 @@
+/**************************************************************************/
+/* */
+/* 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_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_wait_abort PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function aborts the wait condition that the specified thread */
+/* is in - regardless of what object the thread is waiting on - and */
+/* returns a TX_WAIT_ABORTED status to the specified thread. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread to abort the wait on */
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* Suspension Cleanup Functions */
+/* _tx_thread_system_resume */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_wait_abort(TX_THREAD *thread_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence);
+UINT status;
+ULONG suspension_sequence;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_WAIT_ABORT, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_THREAD_WAIT_ABORT_INSERT
+
+ /* Determine if the thread is currently suspended. */
+ if (thread_ptr -> tx_thread_state < TX_SLEEP)
+ {
+
+ /* Thread is either ready, completed, terminated, or in a pure
+ suspension condition. */
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Just return with an error message to indicate that
+ nothing was done. */
+ status = TX_WAIT_ABORT_ERROR;
+ }
+ else
+ {
+
+ /* Check for a sleep condition. */
+ if (thread_ptr -> tx_thread_state == TX_SLEEP)
+ {
+
+ /* Set the state to terminated. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Set the TX_WAIT_ABORTED status in the thread that is
+ sleeping. */
+ thread_ptr -> tx_thread_suspend_status = TX_WAIT_ABORTED;
+
+ /* Make sure there isn't a suspend cleanup routine. */
+ thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the disable preemption flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+ }
+ else
+ {
+
+ /* Process all other suspension timeouts. */
+
+ /* Set the state to suspended. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+ /* Pickup the cleanup routine address. */
+ suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Pickup the suspension sequence number that is used later to verify that the
+ cleanup is still necessary. */
+ suspension_sequence = thread_ptr -> tx_thread_suspension_sequence;
+#else
+
+ /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */
+ suspension_sequence = ((ULONG) 0);
+#endif
+
+ /* Set the TX_WAIT_ABORTED status in the thread that was
+ suspended. */
+ thread_ptr -> tx_thread_suspend_status = TX_WAIT_ABORTED;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+ /* Increment the disable preemption flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Call any cleanup routines. */
+ if (suspend_cleanup != TX_NULL)
+ {
+
+ /* Yes, there is a function to call. */
+ (suspend_cleanup)(thread_ptr, suspension_sequence);
+ }
+ }
+
+ /* If the abort of the thread wait was successful, if so resume the thread. */
+ if (thread_ptr -> tx_thread_suspend_status == TX_WAIT_ABORTED)
+ {
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total number of thread wait aborts. */
+ _tx_thread_performance_wait_abort_count++;
+
+ /* Increment this thread's wait abort count. */
+ thread_ptr -> tx_thread_performance_wait_abort_count++;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(thread_ptr);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Lift the suspension on the previously waiting thread. */
+ _tx_thread_system_resume(thread_ptr);
+#endif
+
+ /* Return a successful status. */
+ status = TX_SUCCESS;
+ }
+ else
+ {
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+#else
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the disable preemption flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+
+ /* Return with an error message to indicate that
+ nothing was done. */
+ status = TX_WAIT_ABORT_ERROR;
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_time_get.c b/common/src/tx_time_get.c
new file mode 100644
index 00000000..2bc69bc0
--- /dev/null
+++ b/common/src/tx_time_get.c
@@ -0,0 +1,100 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_time_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves the internal, free-running, system clock */
+/* and returns it to the caller. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* _tx_timer_system_clock Returns the system clock value */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+ULONG _tx_time_get(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifdef TX_ENABLE_EVENT_TRACE
+ULONG another_temp_time = ((ULONG) 0);
+#endif
+ULONG temp_time;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Pickup the system clock time. */
+ temp_time = _tx_timer_system_clock;
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_GET, TX_ULONG_TO_POINTER_CONVERT(temp_time), TX_POINTER_TO_ULONG_CONVERT(&another_temp_time), 0, 0, TX_TRACE_TIME_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIME_GET_INSERT
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return the time. */
+ return(temp_time);
+}
+
diff --git a/common/src/tx_time_set.c b/common/src/tx_time_set.c
new file mode 100644
index 00000000..83522f7d
--- /dev/null
+++ b/common/src/tx_time_set.c
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_time_set PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function modifies the internal, free-running, system clock */
+/* as specified by the caller. */
+/* */
+/* INPUT */
+/* */
+/* new_time New time value */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_time_set(ULONG new_time)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SET, TX_ULONG_TO_POINTER_CONVERT(new_time), 0, 0, 0, TX_TRACE_TIME_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIME_SET_INSERT
+
+ /* Set the system clock time. */
+ _tx_timer_system_clock = new_time;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+
diff --git a/common/src/tx_timer_activate.c b/common/src/tx_timer_activate.c
new file mode 100644
index 00000000..69580545
--- /dev/null
+++ b/common/src/tx_timer_activate.c
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_activate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function activates the specified application timer. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Always returns success */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_system_activate Actual timer activation function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_activate(TX_TIMER *timer_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+
+
+ /* Disable interrupts to put the timer on the created list. */
+ TX_DISABLE
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_ACTIVATE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS)
+#endif
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_ACTIVATE_INSERT
+#endif
+
+ /* Check for an already active timer. */
+ if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL)
+ {
+
+ /* Timer is already active, return an error. */
+ status = TX_ACTIVATE_ERROR;
+ }
+
+ /* Check for a timer with a zero expiration. */
+ else if (timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks == ((ULONG) 0))
+ {
+
+ /* Timer is being activated with a zero expiration. */
+ status = TX_ACTIVATE_ERROR;
+ }
+ else
+ {
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total activations counter. */
+ _tx_timer_performance_activate_count++;
+
+ /* Increment the number of activations on this timer. */
+ timer_ptr -> tx_timer_performance_activate_count++;
+#endif
+
+ /* Call actual activation function. */
+ _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal));
+
+ /* Return a successful status. */
+ status = TX_SUCCESS;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_timer_change.c b/common/src/tx_timer_change.c
new file mode 100644
index 00000000..ca796a3f
--- /dev/null
+++ b/common/src/tx_timer_change.c
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function modifies an application timer as specified by the */
+/* input. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* initial_ticks Initial expiration ticks */
+/* reschedule_ticks Reschedule ticks */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts to put the timer on the created list. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CHANGE, timer_ptr, initial_ticks, reschedule_ticks, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_CHANGE_INSERT
+
+ /* Determine if the timer is active. */
+ if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head == TX_NULL)
+ {
+
+ /* Setup the new expiration fields. */
+ timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks = initial_ticks;
+ timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks = reschedule_ticks;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_timer_create.c b/common/src/tx_timer_create.c
new file mode 100644
index 00000000..a394fcf2
--- /dev/null
+++ b/common/src/tx_timer_create.c
@@ -0,0 +1,167 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates an application timer from the specified */
+/* input. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* name_ptr Pointer to timer name */
+/* expiration_function Application expiration function */
+/* initial_ticks Initial expiration ticks */
+/* reschedule_ticks Reschedule ticks */
+/* auto_activate Automatic activation flag */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_system_activate Timer activation function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
+ VOID (*expiration_function)(ULONG id), ULONG expiration_input,
+ ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER *next_timer;
+TX_TIMER *previous_timer;
+
+
+ /* Initialize timer control block to all zeros. */
+ TX_MEMSET(timer_ptr, 0, (sizeof(TX_TIMER)));
+
+ /* Setup the basic timer fields. */
+ timer_ptr -> tx_timer_name = name_ptr;
+ timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks = initial_ticks;
+ timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks = reschedule_ticks;
+ timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_function = expiration_function;
+ timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_param = expiration_input;
+
+ /* Disable interrupts to put the timer on the created list. */
+ TX_DISABLE
+
+ /* Setup the timer ID to make it valid. */
+ timer_ptr -> tx_timer_id = TX_TIMER_ID;
+
+ /* Place the timer on the list of created application timers. First,
+ check for an empty list. */
+ if (_tx_timer_created_count == TX_EMPTY)
+ {
+
+ /* The created timer list is empty. Add timer to empty list. */
+ _tx_timer_created_ptr = timer_ptr;
+ timer_ptr -> tx_timer_created_next = timer_ptr;
+ timer_ptr -> tx_timer_created_previous = timer_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_timer = _tx_timer_created_ptr;
+ previous_timer = next_timer -> tx_timer_created_previous;
+
+ /* Place the new timer in the list. */
+ next_timer -> tx_timer_created_previous = timer_ptr;
+ previous_timer -> tx_timer_created_next = timer_ptr;
+
+ /* Setup this timer's created links. */
+ timer_ptr -> tx_timer_created_previous = previous_timer;
+ timer_ptr -> tx_timer_created_next = next_timer;
+ }
+
+ /* Increment the number of created timers. */
+ _tx_timer_created_count++;
+
+ /* Optional timer create extended processing. */
+ TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+ /* If trace is enabled, register this object. */
+ TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, name_ptr, initial_ticks, reschedule_ticks)
+
+ /* If trace is enabled, insert this call in the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CREATE, timer_ptr, initial_ticks, reschedule_ticks, auto_activate, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_CREATE_INSERT
+
+ /* Determine if this timer needs to be activated. */
+ if (auto_activate == TX_AUTO_ACTIVATE)
+ {
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total activations counter. */
+ _tx_timer_performance_activate_count++;
+
+ /* Increment the number of activations on this timer. */
+ timer_ptr -> tx_timer_performance_activate_count++;
+#endif
+
+ /* Call actual activation function. */
+ _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal));
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_timer_deactivate.c b/common/src/tx_timer_deactivate.c
new file mode 100644
index 00000000..b93c2785
--- /dev/null
+++ b/common/src/tx_timer_deactivate.c
@@ -0,0 +1,250 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_deactivate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deactivates the specified application timer. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Always returns success */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_deactivate(TX_TIMER *timer_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER_INTERNAL *internal_ptr;
+TX_TIMER_INTERNAL **list_head;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *previous_timer;
+ULONG ticks_left;
+UINT active_timer_list;
+
+
+ /* Setup internal timer pointer. */
+ internal_ptr = &(timer_ptr -> tx_timer_internal);
+
+ /* Disable interrupts while the remaining time before expiration is
+ calculated. */
+ TX_DISABLE
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total deactivations counter. */
+ _tx_timer_performance_deactivate_count++;
+
+ /* Increment the number of deactivations on this timer. */
+ timer_ptr -> tx_timer_performance_deactivate_count++;
+#endif
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DEACTIVATE, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_DEACTIVATE_INSERT
+
+ /* Pickup the list head. */
+ list_head = internal_ptr -> tx_timer_internal_list_head;
+
+ /* Is the timer active? */
+ if (list_head != TX_NULL)
+ {
+
+ /* Default the active timer list flag to false. */
+ active_timer_list = TX_FALSE;
+
+ /* Determine if the head pointer is within the timer expiration list. */
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_start))
+ {
+
+ /* Now check to make sure the list head is before the end of the list. */
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) < TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end))
+ {
+
+ /* Set the active timer list flag to true. */
+ active_timer_list = TX_TRUE;
+ }
+ }
+
+ /* Determine if the timer is on active timer list. */
+ if (active_timer_list == TX_TRUE)
+ {
+
+ /* This timer is active and has not yet expired. */
+
+ /* Calculate the amount of time that has elapsed since the timer
+ was activated. */
+
+ /* Is this timer's entry after the current timer pointer? */
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_current_ptr))
+ {
+
+ /* Calculate ticks left to expiration - just the difference between this
+ timer's entry and the current timer pointer. */
+ ticks_left = (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_current_ptr)) + ((ULONG) 1);
+ }
+ else
+ {
+
+ /* Calculate the ticks left with a wrapped list condition. */
+ ticks_left = (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_list_start));
+
+ ticks_left = ticks_left + (ULONG) ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1));
+ }
+
+ /* Adjust the remaining ticks accordingly. */
+ if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Subtract off the last full pass through the timer list and add the
+ time left. */
+ internal_ptr -> tx_timer_internal_remaining_ticks =
+ (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left;
+ }
+ else
+ {
+
+ /* Just put the ticks left into the timer's remaining ticks. */
+ internal_ptr -> tx_timer_internal_remaining_ticks = ticks_left;
+ }
+ }
+ else
+ {
+
+ /* Determine if this is timer has just expired. */
+ if (_tx_timer_expired_timer_ptr != internal_ptr)
+ {
+
+ /* No, it hasn't expired. Now check for remaining time greater than the list
+ size. */
+ if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Adjust the remaining ticks. */
+ internal_ptr -> tx_timer_internal_remaining_ticks =
+ internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
+ }
+ else
+ {
+
+ /* Set the remaining time to the reactivation time. */
+ internal_ptr -> tx_timer_internal_remaining_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks;
+ }
+ }
+ else
+ {
+
+ /* Set the remaining time to the reactivation time. */
+ internal_ptr -> tx_timer_internal_remaining_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks;
+ }
+ }
+
+ /* Pickup the next timer. */
+ next_timer = internal_ptr -> tx_timer_internal_active_next;
+
+ /* See if this is the only timer in the list. */
+ if (internal_ptr == next_timer)
+ {
+
+ /* Yes, the only timer on the list. */
+
+ /* Determine if the head pointer needs to be updated. */
+ if (*(list_head) == internal_ptr)
+ {
+
+ /* Update the head pointer. */
+ *(list_head) = TX_NULL;
+ }
+ }
+ else
+ {
+
+ /* At least one more timer is on the same expiration list. */
+
+ /* Update the links of the adjacent timers. */
+ previous_timer = internal_ptr -> tx_timer_internal_active_previous;
+ next_timer -> tx_timer_internal_active_previous = previous_timer;
+ previous_timer -> tx_timer_internal_active_next = next_timer;
+
+ /* Determine if the head pointer needs to be updated. */
+ if (*(list_head) == internal_ptr)
+ {
+
+ /* Update the next timer in the list with the list head
+ pointer. */
+ next_timer -> tx_timer_internal_list_head = list_head;
+
+ /* Update the head pointer. */
+ *(list_head) = next_timer;
+ }
+ }
+
+ /* Clear the timer's list head pointer. */
+ internal_ptr -> tx_timer_internal_list_head = TX_NULL;
+ }
+
+ /* Restore interrupts to previous posture. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_timer_delete.c b/common/src/tx_timer_delete.c
new file mode 100644
index 00000000..c5f444b0
--- /dev/null
+++ b/common/src/tx_timer_delete.c
@@ -0,0 +1,142 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the specified application timer. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Successful completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_system_deactivate Timer deactivation function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_delete(TX_TIMER *timer_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER *next_timer;
+TX_TIMER *previous_timer;
+
+
+ /* Disable interrupts to remove the timer from the created list. */
+ TX_DISABLE
+
+ /* Determine if the timer needs to be deactivated. */
+ if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL)
+ {
+
+ /* Yes, deactivate the timer before it is deleted. */
+ _tx_timer_system_deactivate(&(timer_ptr -> tx_timer_internal));
+ }
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DELETE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Optional timer delete extended processing. */
+ TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+ /* If trace is enabled, unregister this object. */
+ TX_TRACE_OBJECT_UNREGISTER(timer_ptr)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_DELETE_INSERT
+
+ /* Clear the timer ID to make it invalid. */
+ timer_ptr -> tx_timer_id = TX_CLEAR_ID;
+
+ /* Decrement the number of created timers. */
+ _tx_timer_created_count--;
+
+ /* See if the timer is the only one on the list. */
+ if (_tx_timer_created_count == TX_EMPTY)
+ {
+
+ /* Only created timer, just set the created list to NULL. */
+ _tx_timer_created_ptr = TX_NULL;
+ }
+ else
+ {
+
+ /* Link-up the neighbors. */
+ next_timer = timer_ptr -> tx_timer_created_next;
+ previous_timer = timer_ptr -> tx_timer_created_previous;
+ next_timer -> tx_timer_created_previous = previous_timer;
+ previous_timer -> tx_timer_created_next = next_timer;
+
+ /* See if we have to update the created list head pointer. */
+ if (_tx_timer_created_ptr == timer_ptr)
+ {
+
+ /* Yes, move the head pointer to the next link. */
+ _tx_timer_created_ptr = next_timer;
+ }
+ }
+
+ /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
+ TX_TIMER_DELETE_PORT_COMPLETION(timer_ptr)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return TX_SUCCESS. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_timer_expiration_process.c b/common/src/tx_timer_expiration_process.c
new file mode 100644
index 00000000..ffe9ba81
--- /dev/null
+++ b/common/src/tx_timer_expiration_process.c
@@ -0,0 +1,477 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_expiration_process PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes thread and application timer expirations. */
+/* It is called from the _tx_timer_interrupt handler and either */
+/* processes the timer expiration in the ISR or defers to the system */
+/* timer thread. The actual processing is determined during */
+/* compilation. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_resume Thread resume processing */
+/* _tx_thread_system_ni_resume Non-interruptable resume thread */
+/* _tx_timer_system_activate Timer reactivate processing */
+/* Timer Expiration Function */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_timer_interrupt Timer interrupt handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_timer_expiration_process(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+#ifdef TX_TIMER_PROCESS_IN_ISR
+
+TX_TIMER_INTERNAL *expired_timers;
+TX_TIMER_INTERNAL *reactivate_timer;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *previous_timer;
+#ifdef TX_REACTIVATE_INLINE
+TX_TIMER_INTERNAL **timer_list; /* Timer list pointer */
+UINT expiration_time; /* Value used for pointer offset*/
+ULONG delta;
+#endif
+TX_TIMER_INTERNAL *current_timer;
+VOID (*timeout_function)(ULONG id);
+ULONG timeout_param = ((ULONG) 0);
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+TX_TIMER *timer_ptr;
+#endif
+#endif
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Don't process in the ISR, wakeup the system timer thread to process the
+ timer expiration. */
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Resume the thread! */
+ _tx_thread_system_ni_resume(&_tx_timer_thread);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call the system resume function to activate the timer thread. */
+ _tx_thread_system_resume(&_tx_timer_thread);
+#endif
+
+#else
+
+ /* Process the timer expiration directly in the ISR. This increases the interrupt
+ processing, however, it eliminates the need for a system timer thread and associated
+ resources. */
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if the timer processing is already active. This needs to be checked outside
+ of the processing loop because it remains set throughout nested timer interrupt conditions. */
+ if (_tx_timer_processing_active == TX_FALSE)
+ {
+
+ /* Timer processing is not nested. */
+
+ /* Determine if the timer expiration has already been cleared. */
+ if (_tx_timer_expired != ((UINT) 0))
+ {
+
+ /* Proceed with timer processing. */
+
+ /* Set the timer interrupt processing active flag. */
+ _tx_timer_processing_active = TX_TRUE;
+
+ /* Now go into an infinite loop to process timer expirations. */
+ do
+ {
+
+ /* First, move the current list pointer and clear the timer
+ expired value. This allows the interrupt handling portion
+ to continue looking for timer expirations. */
+
+ /* Save the current timer expiration list pointer. */
+ expired_timers = *_tx_timer_current_ptr;
+
+ /* Modify the head pointer in the first timer in the list, if there
+ is one! */
+ if (expired_timers != TX_NULL)
+ {
+
+ expired_timers -> tx_timer_internal_list_head = &expired_timers;
+ }
+
+ /* Set the current list pointer to NULL. */
+ *_tx_timer_current_ptr = TX_NULL;
+
+ /* Move the current pointer up one timer entry wrap if we get to
+ the end of the list. */
+ _tx_timer_current_ptr = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1);
+ if (_tx_timer_current_ptr == _tx_timer_list_end)
+ {
+
+ _tx_timer_current_ptr = _tx_timer_list_start;
+ }
+
+ /* Clear the expired flag. */
+ _tx_timer_expired = TX_FALSE;
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Next, process the expiration of the associated timers at this
+ time slot. */
+ while (expired_timers != TX_NULL)
+ {
+
+ /* Something is on the list. Remove it and process the expiration. */
+ current_timer = expired_timers;
+
+ /* Pickup the next timer. */
+ next_timer = expired_timers -> tx_timer_internal_active_next;
+
+ /* Set the reactivate timer to NULL. */
+ reactivate_timer = TX_NULL;
+
+ /* Determine if this is the only timer. */
+ if (current_timer == next_timer)
+ {
+
+ /* Yes, this is the only timer in the list. */
+
+ /* Set the head pointer to NULL. */
+ expired_timers = TX_NULL;
+ }
+ else
+ {
+
+ /* No, not the only expired timer. */
+
+ /* Remove this timer from the expired list. */
+ previous_timer = current_timer -> tx_timer_internal_active_previous;
+ next_timer -> tx_timer_internal_active_previous = previous_timer;
+ previous_timer -> tx_timer_internal_active_next = next_timer;
+
+ /* Modify the next timer's list head to point at the current list head. */
+ next_timer -> tx_timer_internal_list_head = &expired_timers;
+
+ /* Set the list head pointer. */
+ expired_timers = next_timer;
+ }
+
+ /* In any case, the timer is now off of the expired list. */
+
+ /* Determine if the timer has expired or if it is just a really
+ big timer that needs to be placed in the list again. */
+ if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Timer is bigger than the timer entries and must be
+ rescheduled. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total expiration adjustments counter. */
+ _tx_timer_performance__expiration_adjust_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expiration adjustments on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance__expiration_adjust_count++;
+ }
+ }
+#endif
+
+ /* Decrement the remaining ticks of the timer. */
+ current_timer -> tx_timer_internal_remaining_ticks =
+ current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
+
+ /* Set the timeout function to NULL in order to bypass the
+ expiration. */
+ timeout_function = TX_NULL;
+
+ /* Make the timer appear that it is still active while interrupts
+ are enabled. This will permit proper processing of a timer
+ deactivate from an ISR. */
+ current_timer -> tx_timer_internal_list_head = &reactivate_timer;
+ current_timer -> tx_timer_internal_active_next = current_timer;
+
+ /* Setup the temporary timer list head pointer. */
+ reactivate_timer = current_timer;
+ }
+ else
+ {
+
+ /* Timer did expire. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total expirations counter. */
+ _tx_timer_performance_expiration_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expirations on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance_expiration_count++;
+ }
+ }
+#endif
+
+ /* Copy the calling function and ID into local variables before interrupts
+ are re-enabled. */
+ timeout_function = current_timer -> tx_timer_internal_timeout_function;
+ timeout_param = current_timer -> tx_timer_internal_timeout_param;
+
+ /* Copy the reinitialize ticks into the remaining ticks. */
+ current_timer -> tx_timer_internal_remaining_ticks = current_timer -> tx_timer_internal_re_initialize_ticks;
+
+ /* Determine if the timer should be reactivated. */
+ if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0))
+ {
+
+ /* Make the timer appear that it is still active while processing
+ the expiration routine and with interrupts enabled. This will
+ permit proper processing of a timer deactivate from both the
+ expiration routine and an ISR. */
+ current_timer -> tx_timer_internal_list_head = &reactivate_timer;
+ current_timer -> tx_timer_internal_active_next = current_timer;
+
+ /* Setup the temporary timer list head pointer. */
+ reactivate_timer = current_timer;
+ }
+ else
+ {
+
+ /* Set the list pointer of this timer to NULL. This is used to indicate
+ the timer is no longer active. */
+ current_timer -> tx_timer_internal_list_head = TX_NULL;
+ }
+ }
+
+ /* Set pointer to indicate the expired timer that is currently being processed. */
+ _tx_timer_expired_timer_ptr = current_timer;
+
+ /* Restore interrupts for timer expiration call. */
+ TX_RESTORE
+
+ /* Call the timer-expiration function, if non-NULL. */
+ if (timeout_function != TX_NULL)
+ {
+
+ (timeout_function) (timeout_param);
+ }
+
+ /* Lockout interrupts again. */
+ TX_DISABLE
+
+ /* Clear expired timer pointer. */
+ _tx_timer_expired_timer_ptr = TX_NULL;
+
+ /* Determine if the timer needs to be reactivated. */
+ if (reactivate_timer == current_timer)
+ {
+
+ /* Reactivate the timer. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if this timer expired. */
+ if (timeout_function != TX_NULL)
+ {
+
+ /* Increment the total reactivations counter. */
+ _tx_timer_performance_reactivate_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expirations on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance_reactivate_count++;
+ }
+ }
+ }
+#endif
+
+
+#ifdef TX_REACTIVATE_INLINE
+
+ /* Calculate the amount of time remaining for the timer. */
+ if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Set expiration time to the maximum number of entries. */
+ expiration_time = TX_TIMER_ENTRIES - ((UINT) 1);
+ }
+ else
+ {
+
+ /* Timer value fits in the timer entries. */
+
+ /* Set the expiration time. */
+ expiration_time = ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1);
+ }
+
+ /* At this point, we are ready to put the timer back on one of
+ the timer lists. */
+
+ /* Calculate the proper place for the timer. */
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time);
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end))
+ {
+
+ /* Wrap from the beginning of the list. */
+ delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end);
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta);
+ }
+
+ /* Now put the timer on this list. */
+ if ((*timer_list) == TX_NULL)
+ {
+
+ /* This list is NULL, just put the new timer on it. */
+
+ /* Setup the links in this timer. */
+ current_timer -> tx_timer_internal_active_next = current_timer;
+ current_timer -> tx_timer_internal_active_previous = current_timer;
+
+ /* Setup the list head pointer. */
+ *timer_list = current_timer;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current timer to the end. */
+ next_timer = *timer_list;
+ previous_timer = next_timer -> tx_timer_internal_active_previous;
+ previous_timer -> tx_timer_internal_active_next = current_timer;
+ next_timer -> tx_timer_internal_active_previous = current_timer;
+ current_timer -> tx_timer_internal_active_next = next_timer;
+ current_timer -> tx_timer_internal_active_previous = previous_timer;
+ }
+
+ /* Setup list head pointer. */
+ current_timer -> tx_timer_internal_list_head = timer_list;
+#else
+
+ /* Reactivate through the timer activate function. */
+
+ /* Clear the list head for the timer activate call. */
+ current_timer -> tx_timer_internal_list_head = TX_NULL;
+
+ /* Activate the current timer. */
+ _tx_timer_system_activate(current_timer);
+#endif
+ }
+ }
+ } while (_tx_timer_expired != TX_FALSE);
+
+ /* Clear the timer interrupt processing active flag. */
+ _tx_timer_processing_active = TX_FALSE;
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#endif
+}
+
diff --git a/common/src/tx_timer_info_get.c b/common/src/tx_timer_info_get.c
new file mode 100644
index 00000000..d422910b
--- /dev/null
+++ b/common/src/tx_timer_info_get.c
@@ -0,0 +1,248 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves information from the specified timer. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* name Destination for the timer name */
+/* active Destination for active flag */
+/* remaining_ticks Destination for remaining ticks */
+/* before expiration */
+/* reschedule_ticks Destination for reschedule ticks */
+/* next_timer Destination for next timer on the */
+/* created list */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
+ ULONG *reschedule_ticks, TX_TIMER **next_timer)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER_INTERNAL *internal_ptr;
+TX_TIMER_INTERNAL **list_head;
+ULONG ticks_left;
+UINT timer_active;
+UINT active_timer_list;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_INFO_GET, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_INFO_GET_INSERT
+
+ /* Retrieve the name of the timer. */
+ if (name != TX_NULL)
+ {
+
+ *name = timer_ptr -> tx_timer_name;
+ }
+
+ /* Pickup address of internal timer structure. */
+ internal_ptr = &(timer_ptr -> tx_timer_internal);
+
+ /* Retrieve all the pertinent information and return it in the supplied
+ destinations. */
+
+ /* Default active to false. */
+ timer_active = TX_FALSE;
+
+ /* Default the ticks left to the remaining ticks. */
+ ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks;
+
+ /* Determine if the timer is still active. */
+ if (internal_ptr -> tx_timer_internal_list_head != TX_NULL)
+ {
+
+ /* Indicate this timer is active. */
+ timer_active = TX_TRUE;
+
+ /* Default the active timer list flag to false. */
+ active_timer_list = TX_FALSE;
+
+ /* Determine if the timer is still active. */
+ if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_list_start)
+ {
+
+ /* Determine if the list head is before the end of the list. */
+ if (internal_ptr -> tx_timer_internal_list_head < _tx_timer_list_end)
+ {
+
+ /* This timer is active and has not yet expired. */
+ active_timer_list = TX_TRUE;
+ }
+ }
+
+ /* Determine if the timer is on the active timer list. */
+ if (active_timer_list == TX_TRUE)
+ {
+
+ /* Calculate the amount of time that has elapsed since the timer
+ was activated. */
+
+ /* Setup the list head pointer. */
+ list_head = internal_ptr -> tx_timer_internal_list_head;
+
+ /* Is this timer's entry after the current timer pointer? */
+ if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_current_ptr)
+ {
+
+ /* Calculate ticks left to expiration - just the difference between this
+ timer's entry and the current timer pointer. */
+ ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_current_ptr)) + ((ULONG) 1));
+ }
+ else
+ {
+
+ /* Calculate the ticks left with a wrapped list condition. */
+ ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_list_start)));
+
+ ticks_left = ticks_left + ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1));
+ }
+
+ /* Adjust the remaining ticks accordingly. */
+ if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Subtract off the last full pass through the timer list and add the
+ time left. */
+ ticks_left = (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left;
+ }
+
+ }
+ else
+ {
+
+ /* The timer is not on the actual timer list so it must either be being processed
+ or on a temporary list to be processed. */
+
+ /* Check to see if this timer is the timer currently being processed. */
+ if (_tx_timer_expired_timer_ptr == internal_ptr)
+ {
+
+ /* Timer dispatch routine is executing, waiting to execute, or just finishing. No more remaining ticks for this expiration. */
+ ticks_left = ((ULONG) 0);
+ }
+ else
+ {
+
+ /* Timer is not the one being processed, which means it must be on the temporary expiration list
+ waiting to be processed. */
+
+ /* Calculate the remaining ticks for a timer in the process of expiring. */
+ if (ticks_left > TX_TIMER_ENTRIES)
+ {
+
+ /* Calculate the number of ticks remaining. */
+ ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
+ }
+ else
+ {
+
+ /* Timer dispatch routine is waiting to execute, no more remaining ticks for this expiration. */
+ ticks_left = ((ULONG) 0);
+ }
+ }
+ }
+ }
+
+ /* Setup return values for an inactive timer. */
+ if (active != TX_NULL)
+ {
+
+ /* Setup the timer active indication. */
+ *active = timer_active;
+ }
+ if (remaining_ticks != TX_NULL)
+ {
+
+ /* Setup the default remaining ticks value. */
+ *remaining_ticks = ticks_left;
+ }
+
+ /* Pickup the reschedule ticks value. */
+ if (reschedule_ticks != TX_NULL)
+ {
+
+ *reschedule_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks;
+ }
+
+ /* Pickup the next created application timer. */
+ if (next_timer != TX_NULL)
+ {
+
+ *next_timer = timer_ptr -> tx_timer_created_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+}
+
diff --git a/common/src/tx_timer_initialize.c b/common/src/tx_timer_initialize.c
new file mode 100644
index 00000000..f86498f4
--- /dev/null
+++ b/common/src/tx_timer_initialize.c
@@ -0,0 +1,304 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/* Check for the TX_NO_TIMER option. When defined, do not define all of the
+ timer component global variables. */
+
+#ifndef TX_NO_TIMER
+
+
+/* Define the system clock value that is continually incremented by the
+ periodic timer interrupt processing. */
+
+volatile ULONG _tx_timer_system_clock;
+
+
+/* Define the time-slice expiration flag. This is used to indicate that a time-slice
+ has happened. */
+
+UINT _tx_timer_expired_time_slice;
+
+
+/* Define the thread and application timer entry list. This list provides a direct access
+ method for insertion of times less than TX_TIMER_ENTRIES. */
+
+TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES];
+
+
+/* Define the boundary pointers to the list. These are setup to easily manage
+ wrapping the list. */
+
+TX_TIMER_INTERNAL **_tx_timer_list_start;
+TX_TIMER_INTERNAL **_tx_timer_list_end;
+
+
+/* Define the current timer pointer in the list. This pointer is moved sequentially
+ through the timer list by the timer interrupt handler. */
+
+TX_TIMER_INTERNAL **_tx_timer_current_ptr;
+
+
+/* Define the timer expiration flag. This is used to indicate that a timer
+ has expired. */
+
+UINT _tx_timer_expired;
+
+
+/* Define the created timer list head pointer. */
+
+TX_TIMER *_tx_timer_created_ptr;
+
+
+/* Define the created timer count. */
+
+ULONG _tx_timer_created_count;
+
+
+/* Define the pointer to the timer that has expired and is being processed. */
+
+TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr;
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+/* Define the timer thread's control block. */
+
+TX_THREAD _tx_timer_thread;
+
+
+/* Define the variable that holds the timer thread's starting stack address. */
+
+VOID *_tx_timer_stack_start;
+
+
+/* Define the variable that holds the timer thread's stack size. */
+
+ULONG _tx_timer_stack_size;
+
+
+/* Define the variable that holds the timer thread's priority. */
+
+UINT _tx_timer_priority;
+
+/* Define the system timer thread's stack. The default size is defined
+ in tx_port.h. */
+
+ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))];
+
+#else
+
+
+/* Define the busy flag that will prevent nested timer ISR processing. */
+
+UINT _tx_timer_processing_active;
+
+#endif
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of timer activations. */
+
+ULONG _tx_timer_performance_activate_count;
+
+
+/* Define the total number of timer reactivations. */
+
+ULONG _tx_timer_performance_reactivate_count;
+
+
+/* Define the total number of timer deactivations. */
+
+ULONG _tx_timer_performance_deactivate_count;
+
+
+/* Define the total number of timer expirations. */
+
+ULONG _tx_timer_performance_expiration_count;
+
+
+/* Define the total number of timer expiration adjustments. These are required
+ if the expiration time is greater than the size of the timer list. In such
+ cases, the timer is placed at the end of the list and then reactivated
+ as many times as necessary to finally achieve the resulting timeout. */
+
+ULONG _tx_timer_performance__expiration_adjust_count;
+
+#endif
+#endif
+
+
+/* Define the current time slice value. If non-zero, a time-slice is active.
+ Otherwise, the time_slice is not active. */
+
+ULONG _tx_timer_time_slice;
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the clock control component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_create Create the system timer thread */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_timer_initialize(VOID)
+{
+#ifndef TX_NO_TIMER
+#ifndef TX_TIMER_PROCESS_IN_ISR
+UINT status;
+#endif
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the system clock to 0. */
+ _tx_timer_system_clock = ((ULONG) 0);
+
+ /* Initialize the time-slice value to 0 to make sure it is disabled. */
+ _tx_timer_time_slice = ((ULONG) 0);
+
+ /* Clear the expired flags. */
+ _tx_timer_expired_time_slice = TX_FALSE;
+ _tx_timer_expired = TX_FALSE;
+
+ /* Set the currently expired timer being processed pointer to NULL. */
+ _tx_timer_expired_timer_ptr = TX_NULL;
+
+ /* Initialize the thread and application timer management control structures. */
+
+ /* First, initialize the timer list. */
+ TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list)));
+#endif
+
+ /* Initialize all of the list pointers. */
+ _tx_timer_list_start = &_tx_timer_list[0];
+ _tx_timer_current_ptr = &_tx_timer_list[0];
+
+ /* Set the timer list end pointer to one past the actual timer list. This is done
+ to make the timer interrupt handling in assembly language a little easier. */
+ _tx_timer_list_end = &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)];
+ _tx_timer_list_end = TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1));
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Setup the variables associated with the system timer thread's stack and
+ priority. */
+ _tx_timer_stack_start = (VOID *) &_tx_timer_thread_stack_area[0];
+ _tx_timer_stack_size = ((ULONG) TX_TIMER_THREAD_STACK_SIZE);
+ _tx_timer_priority = ((UINT) TX_TIMER_THREAD_PRIORITY);
+
+ /* Create the system timer thread. This thread processes all of the timer
+ expirations and reschedules. Its stack and priority are defined in the
+ low-level initialization component. */
+ do
+ {
+
+ /* Create the system timer thread. */
+ status = _tx_thread_create(&_tx_timer_thread,
+ TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("System Timer Thread"),
+ _tx_timer_thread_entry,
+ ((ULONG) TX_TIMER_ID),
+ _tx_timer_stack_start, _tx_timer_stack_size,
+ _tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START);
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* Check return from thread create - if an error is detected throw an exception. */
+ if (status != TX_SUCCESS)
+ {
+
+ /* Raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, status);
+ }
+#endif
+
+ /* Define timer initialize extension. */
+ TX_TIMER_INITIALIZE_EXTENSION(status)
+
+ } while (status != TX_SUCCESS);
+
+#else
+
+ /* Clear the timer interrupt processing active flag. */
+ _tx_timer_processing_active = TX_FALSE;
+#endif
+
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize the head pointer of the created application timer list. */
+ _tx_timer_created_ptr = TX_NULL;
+
+ /* Set the created count to zero. */
+ _tx_timer_created_count = TX_EMPTY;
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Initialize timer performance counters. */
+ _tx_timer_performance_activate_count = ((ULONG) 0);
+ _tx_timer_performance_reactivate_count = ((ULONG) 0);
+ _tx_timer_performance_deactivate_count = ((ULONG) 0);
+ _tx_timer_performance_expiration_count = ((ULONG) 0);
+ _tx_timer_performance__expiration_adjust_count = ((ULONG) 0);
+#endif
+#endif
+#endif
+}
+
diff --git a/common/src/tx_timer_performance_info_get.c b/common/src/tx_timer_performance_info_get.c
new file mode 100644
index 00000000..e765abc9
--- /dev/null
+++ b/common/src/tx_timer_performance_info_get.c
@@ -0,0 +1,214 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_performance_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves performance information from the specified */
+/* timer. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* activates Destination for the number of */
+/* activations of this timer */
+/* reactivates Destination for the number of */
+/* reactivations of this timer */
+/* deactivates Destination for the number of */
+/* deactivations of this timer */
+/* expirations Destination for the number of */
+/* expirations of this timer */
+/* expiration_adjusts Destination for the number of */
+/* expiration adjustments of this */
+/* timer */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_performance_info_get(TX_TIMER *timer_ptr, ULONG *activates, ULONG *reactivates,
+ ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts)
+{
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+
+
+ /* Determine if this is a legal request. */
+ if (timer_ptr == TX_NULL)
+ {
+
+ /* Timer pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the timer ID is invalid. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+
+ /* Timer pointer is illegal, return error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_PERFORMANCE_INFO_GET, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT
+
+ /* Retrieve the number of activations of this timer. */
+ if (activates != TX_NULL)
+ {
+
+ *activates = timer_ptr -> tx_timer_performance_activate_count;
+ }
+
+ /* Retrieve the number of reactivations of this timer. */
+ if (reactivates != TX_NULL)
+ {
+
+ *reactivates = timer_ptr -> tx_timer_performance_reactivate_count;
+ }
+
+ /* Retrieve the number of deactivations of this timer. */
+ if (deactivates != TX_NULL)
+ {
+
+ *deactivates = timer_ptr -> tx_timer_performance_deactivate_count;
+ }
+
+ /* Retrieve the number of expirations of this timer. */
+ if (expirations != TX_NULL)
+ {
+
+ *expirations = timer_ptr -> tx_timer_performance_expiration_count;
+ }
+
+ /* Retrieve the number of expiration adjustments of this timer. */
+ if (expiration_adjusts != TX_NULL)
+ {
+
+ *expiration_adjusts = timer_ptr -> tx_timer_performance__expiration_adjust_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+#else
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (timer_ptr != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (activates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (reactivates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (deactivates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (expirations != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (expiration_adjusts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+#endif
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/tx_timer_performance_system_info_get.c b/common/src/tx_timer_performance_system_info_get.c
new file mode 100644
index 00000000..5439864d
--- /dev/null
+++ b/common/src/tx_timer_performance_system_info_get.c
@@ -0,0 +1,187 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+#include "tx_trace.h"
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_performance_system_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function retrieves timer performance information. */
+/* */
+/* INPUT */
+/* */
+/* activates Destination for total number of */
+/* activations */
+/* reactivates Destination for total number of */
+/* reactivations */
+/* deactivates Destination for total number of */
+/* deactivations */
+/* expirations Destination for total number of */
+/* expirations */
+/* expiration_adjusts Destination for total number of */
+/* expiration adjustments */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_timer_performance_system_info_get(ULONG *activates, ULONG *reactivates,
+ ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts)
+{
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* If trace is enabled, insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_TIMER_EVENTS)
+
+ /* Log this kernel call. */
+ TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+ /* Retrieve the total number of timer activations. */
+ if (activates != TX_NULL)
+ {
+
+ *activates = _tx_timer_performance_activate_count;
+ }
+
+ /* Retrieve the total number of timer reactivations. */
+ if (reactivates != TX_NULL)
+ {
+
+ *reactivates = _tx_timer_performance_reactivate_count;
+ }
+
+ /* Retrieve the total number of timer deactivations. */
+ if (deactivates != TX_NULL)
+ {
+
+ *deactivates = _tx_timer_performance_deactivate_count;
+ }
+
+ /* Retrieve the total number of timer expirations. */
+ if (expirations != TX_NULL)
+ {
+
+ *expirations = _tx_timer_performance_expiration_count;
+ }
+
+ /* Retrieve the total number of timer expiration adjustments. */
+ if (expiration_adjusts != TX_NULL)
+ {
+
+ *expiration_adjusts = _tx_timer_performance__expiration_adjust_count;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (activates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (reactivates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (deactivates != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (expirations != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (expiration_adjusts != TX_NULL)
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Not enabled, return error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_timer_system_activate.c b/common/src/tx_timer_system_activate.c
new file mode 100644
index 00000000..a4b844d3
--- /dev/null
+++ b/common/src/tx_timer_system_activate.c
@@ -0,0 +1,164 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_system_activate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function places the specified internal timer in the proper */
+/* place in the timer expiration list. If the timer is already active */
+/* this function does nothing. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Always returns success */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_system_suspend Thread suspend function */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* _tx_timer_thread_entry Timer thread processing */
+/* _tx_timer_activate Application timer activate */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr)
+{
+
+TX_TIMER_INTERNAL **timer_list;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *previous_timer;
+ULONG delta;
+ULONG remaining_ticks;
+ULONG expiration_time;
+
+
+ /* Pickup the remaining ticks. */
+ remaining_ticks = timer_ptr -> tx_timer_internal_remaining_ticks;
+
+ /* Determine if there is a timer to activate. */
+ if (remaining_ticks != ((ULONG) 0))
+ {
+
+ /* Determine if the timer is set to wait forever. */
+ if (remaining_ticks != TX_WAIT_FOREVER)
+ {
+
+ /* Valid timer activate request. */
+
+ /* Determine if the timer still needs activation. */
+ if (timer_ptr -> tx_timer_internal_list_head == TX_NULL)
+ {
+
+ /* Activate the timer. */
+
+ /* Calculate the amount of time remaining for the timer. */
+ if (remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Set expiration time to the maximum number of entries. */
+ expiration_time = TX_TIMER_ENTRIES - ((ULONG) 1);
+ }
+ else
+ {
+
+ /* Timer value fits in the timer entries. */
+
+ /* Set the expiration time. */
+ expiration_time = (remaining_ticks - ((ULONG) 1));
+ }
+
+ /* At this point, we are ready to put the timer on one of
+ the timer lists. */
+
+ /* Calculate the proper place for the timer. */
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time);
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end))
+ {
+
+ /* Wrap from the beginning of the list. */
+ delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end);
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta);
+ }
+
+ /* Now put the timer on this list. */
+ if ((*timer_list) == TX_NULL)
+ {
+
+ /* This list is NULL, just put the new timer on it. */
+
+ /* Setup the links in this timer. */
+ timer_ptr -> tx_timer_internal_active_next = timer_ptr;
+ timer_ptr -> tx_timer_internal_active_previous = timer_ptr;
+
+ /* Setup the list head pointer. */
+ *timer_list = timer_ptr;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current timer to the end. */
+ next_timer = *timer_list;
+ previous_timer = next_timer -> tx_timer_internal_active_previous;
+ previous_timer -> tx_timer_internal_active_next = timer_ptr;
+ next_timer -> tx_timer_internal_active_previous = timer_ptr;
+ timer_ptr -> tx_timer_internal_active_next = next_timer;
+ timer_ptr -> tx_timer_internal_active_previous = previous_timer;
+ }
+
+ /* Setup list head pointer. */
+ timer_ptr -> tx_timer_internal_list_head = timer_list;
+ }
+ }
+ }
+}
+
diff --git a/common/src/tx_timer_system_deactivate.c b/common/src/tx_timer_system_deactivate.c
new file mode 100644
index 00000000..b951791f
--- /dev/null
+++ b/common/src/tx_timer_system_deactivate.c
@@ -0,0 +1,132 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_system_deactivate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deactivates, or removes the timer from the active */
+/* timer expiration list. If the timer is already deactivated, this */
+/* function just returns. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Always returns success */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_system_resume Thread resume function */
+/* _tx_timer_thread_entry Timer thread processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr)
+{
+
+TX_TIMER_INTERNAL **list_head;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *previous_timer;
+
+
+ /* Pickup the list head pointer. */
+ list_head = timer_ptr -> tx_timer_internal_list_head;
+
+ /* Determine if the timer still needs deactivation. */
+ if (list_head != TX_NULL)
+ {
+
+ /* Deactivate the timer. */
+
+ /* Pickup the next active timer. */
+ next_timer = timer_ptr -> tx_timer_internal_active_next;
+
+ /* See if this is the only timer in the list. */
+ if (timer_ptr == next_timer)
+ {
+
+ /* Yes, the only timer on the list. */
+
+ /* Determine if the head pointer needs to be updated. */
+ if (*(list_head) == timer_ptr)
+ {
+
+ /* Update the head pointer. */
+ *(list_head) = TX_NULL;
+ }
+ }
+ else
+ {
+
+ /* At least one more timer is on the same expiration list. */
+
+ /* Update the links of the adjacent timers. */
+ previous_timer = timer_ptr -> tx_timer_internal_active_previous;
+ next_timer -> tx_timer_internal_active_previous = previous_timer;
+ previous_timer -> tx_timer_internal_active_next = next_timer;
+
+ /* Determine if the head pointer needs to be updated. */
+ if (*(list_head) == timer_ptr)
+ {
+
+ /* Update the next timer in the list with the list head pointer. */
+ next_timer -> tx_timer_internal_list_head = list_head;
+
+ /* Update the head pointer. */
+ *(list_head) = next_timer;
+ }
+ }
+
+ /* Clear the timer's list head pointer. */
+ timer_ptr -> tx_timer_internal_list_head = TX_NULL;
+ }
+}
+
diff --git a/common/src/tx_timer_thread_entry.c b/common/src/tx_timer_thread_entry.c
new file mode 100644
index 00000000..cc8b036c
--- /dev/null
+++ b/common/src/tx_timer_thread_entry.c
@@ -0,0 +1,480 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_thread_entry PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function manages thread and application timer expirations. */
+/* Actually, from this thread's point of view, there is no difference. */
+/* */
+/* INPUT */
+/* */
+/* timer_thread_input Used just for verification */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* Timer Expiration Function */
+/* _tx_thread_system_suspend Thread suspension */
+/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
+/* _tx_timer_system_activate Timer reactivate processing */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Scheduler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+#ifndef TX_TIMER_PROCESS_IN_ISR
+VOID _tx_timer_thread_entry(ULONG timer_thread_input)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER_INTERNAL *expired_timers;
+TX_TIMER_INTERNAL *reactivate_timer;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *previous_timer;
+TX_TIMER_INTERNAL *current_timer;
+VOID (*timeout_function)(ULONG id);
+ULONG timeout_param = ((ULONG) 0);
+TX_THREAD *thread_ptr;
+#ifdef TX_REACTIVATE_INLINE
+TX_TIMER_INTERNAL **timer_list; /* Timer list pointer */
+UINT expiration_time; /* Value used for pointer offset*/
+ULONG delta;
+#endif
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+TX_TIMER *timer_ptr;
+#endif
+
+
+ /* Make sure the timer input is correct. This also gets rid of the
+ silly compiler warnings. */
+ if (timer_thread_input == TX_TIMER_ID)
+ {
+
+ /* Yes, valid thread entry, proceed... */
+
+ /* Now go into an infinite loop to process timer expirations. */
+ while (TX_LOOP_FOREVER)
+ {
+
+ /* First, move the current list pointer and clear the timer
+ expired value. This allows the interrupt handling portion
+ to continue looking for timer expirations. */
+ TX_DISABLE
+
+ /* Save the current timer expiration list pointer. */
+ expired_timers = *_tx_timer_current_ptr;
+
+ /* Modify the head pointer in the first timer in the list, if there
+ is one! */
+ if (expired_timers != TX_NULL)
+ {
+
+ expired_timers -> tx_timer_internal_list_head = &expired_timers;
+ }
+
+ /* Set the current list pointer to NULL. */
+ *_tx_timer_current_ptr = TX_NULL;
+
+ /* Move the current pointer up one timer entry wrap if we get to
+ the end of the list. */
+ _tx_timer_current_ptr = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1);
+ if (_tx_timer_current_ptr == _tx_timer_list_end)
+ {
+
+ _tx_timer_current_ptr = _tx_timer_list_start;
+ }
+
+ /* Clear the expired flag. */
+ _tx_timer_expired = TX_FALSE;
+
+ /* Restore interrupts temporarily. */
+ TX_RESTORE
+
+ /* Disable interrupts again. */
+ TX_DISABLE
+
+ /* Next, process the expiration of the associated timers at this
+ time slot. */
+ while (expired_timers != TX_NULL)
+ {
+
+ /* Something is on the list. Remove it and process the expiration. */
+ current_timer = expired_timers;
+
+ /* Pickup the next timer. */
+ next_timer = expired_timers -> tx_timer_internal_active_next;
+
+ /* Set the reactivate_timer to NULL. */
+ reactivate_timer = TX_NULL;
+
+ /* Determine if this is the only timer. */
+ if (current_timer == next_timer)
+ {
+
+ /* Yes, this is the only timer in the list. */
+
+ /* Set the head pointer to NULL. */
+ expired_timers = TX_NULL;
+ }
+ else
+ {
+
+ /* No, not the only expired timer. */
+
+ /* Remove this timer from the expired list. */
+ previous_timer = current_timer -> tx_timer_internal_active_previous;
+ next_timer -> tx_timer_internal_active_previous = previous_timer;
+ previous_timer -> tx_timer_internal_active_next = next_timer;
+
+ /* Modify the next timer's list head to point at the current list head. */
+ next_timer -> tx_timer_internal_list_head = &expired_timers;
+
+ /* Set the list head pointer. */
+ expired_timers = next_timer;
+ }
+
+ /* In any case, the timer is now off of the expired list. */
+
+ /* Determine if the timer has expired or if it is just a really
+ big timer that needs to be placed in the list again. */
+ if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Timer is bigger than the timer entries and must be
+ rescheduled. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total expiration adjustments counter. */
+ _tx_timer_performance__expiration_adjust_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expiration adjustments on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance__expiration_adjust_count++;
+ }
+ }
+#endif
+
+ /* Decrement the remaining ticks of the timer. */
+ current_timer -> tx_timer_internal_remaining_ticks =
+ current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
+
+ /* Set the timeout function to NULL in order to bypass the
+ expiration. */
+ timeout_function = TX_NULL;
+
+ /* Make the timer appear that it is still active while interrupts
+ are enabled. This will permit proper processing of a timer
+ deactivate from an ISR. */
+ current_timer -> tx_timer_internal_list_head = &reactivate_timer;
+ current_timer -> tx_timer_internal_active_next = current_timer;
+
+ /* Setup the temporary timer list head pointer. */
+ reactivate_timer = current_timer;
+ }
+ else
+ {
+
+ /* Timer did expire. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Increment the total expirations counter. */
+ _tx_timer_performance_expiration_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expirations on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance_expiration_count++;
+ }
+ }
+#endif
+
+ /* Copy the calling function and ID into local variables before interrupts
+ are re-enabled. */
+ timeout_function = current_timer -> tx_timer_internal_timeout_function;
+ timeout_param = current_timer -> tx_timer_internal_timeout_param;
+
+ /* Copy the reinitialize ticks into the remaining ticks. */
+ current_timer -> tx_timer_internal_remaining_ticks = current_timer -> tx_timer_internal_re_initialize_ticks;
+
+ /* Determine if the timer should be reactivated. */
+ if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0))
+ {
+
+ /* Make the timer appear that it is still active while processing
+ the expiration routine and with interrupts enabled. This will
+ permit proper processing of a timer deactivate from both the
+ expiration routine and an ISR. */
+ current_timer -> tx_timer_internal_list_head = &reactivate_timer;
+ current_timer -> tx_timer_internal_active_next = current_timer;
+
+ /* Setup the temporary timer list head pointer. */
+ reactivate_timer = current_timer;
+ }
+ else
+ {
+
+ /* Set the list pointer of this timer to NULL. This is used to indicate
+ the timer is no longer active. */
+ current_timer -> tx_timer_internal_list_head = TX_NULL;
+ }
+ }
+
+ /* Set pointer to indicate the expired timer that is currently being processed. */
+ _tx_timer_expired_timer_ptr = current_timer;
+
+ /* Restore interrupts for timer expiration call. */
+ TX_RESTORE
+
+ /* Call the timer-expiration function, if non-NULL. */
+ if (timeout_function != TX_NULL)
+ {
+
+ (timeout_function) (timeout_param);
+ }
+
+ /* Lockout interrupts again. */
+ TX_DISABLE
+
+ /* Clear expired timer pointer. */
+ _tx_timer_expired_timer_ptr = TX_NULL;
+
+ /* Determine if the timer needs to be reactivated. */
+ if (reactivate_timer == current_timer)
+ {
+
+ /* Reactivate the timer. */
+
+#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
+
+ /* Determine if this timer expired. */
+ if (timeout_function != TX_NULL)
+ {
+
+ /* Increment the total reactivations counter. */
+ _tx_timer_performance_reactivate_count++;
+
+ /* Determine if this is an application timer. */
+ if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout)
+ {
+
+ /* Derive the application timer pointer. */
+
+ /* Pickup the application timer pointer. */
+ TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr)
+
+ /* Increment the number of expirations on this timer. */
+ if (timer_ptr -> tx_timer_id == TX_TIMER_ID)
+ {
+
+ timer_ptr -> tx_timer_performance_reactivate_count++;
+ }
+ }
+ }
+#endif
+
+#ifdef TX_REACTIVATE_INLINE
+
+ /* Calculate the amount of time remaining for the timer. */
+ if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Set expiration time to the maximum number of entries. */
+ expiration_time = TX_TIMER_ENTRIES - ((UINT) 1);
+ }
+ else
+ {
+
+ /* Timer value fits in the timer entries. */
+
+ /* Set the expiration time. */
+ expiration_time = ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1);
+ }
+
+ /* At this point, we are ready to put the timer back on one of
+ the timer lists. */
+
+ /* Calculate the proper place for the timer. */
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time);
+ if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end))
+ {
+
+ /* Wrap from the beginning of the list. */
+ delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end);
+ timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta);
+ }
+
+ /* Now put the timer on this list. */
+ if ((*timer_list) == TX_NULL)
+ {
+
+ /* This list is NULL, just put the new timer on it. */
+
+ /* Setup the links in this timer. */
+ current_timer -> tx_timer_internal_active_next = current_timer;
+ current_timer -> tx_timer_internal_active_previous = current_timer;
+
+ /* Setup the list head pointer. */
+ *timer_list = current_timer;
+ }
+ else
+ {
+
+ /* This list is not NULL, add current timer to the end. */
+ next_timer = *timer_list;
+ previous_timer = next_timer -> tx_timer_internal_active_previous;
+ previous_timer -> tx_timer_internal_active_next = current_timer;
+ next_timer -> tx_timer_internal_active_previous = current_timer;
+ current_timer -> tx_timer_internal_active_next = next_timer;
+ current_timer -> tx_timer_internal_active_previous = previous_timer;
+ }
+
+ /* Setup list head pointer. */
+ current_timer -> tx_timer_internal_list_head = timer_list;
+#else
+
+ /* Reactivate through the timer activate function. */
+
+ /* Clear the list head for the timer activate call. */
+ current_timer -> tx_timer_internal_list_head = TX_NULL;
+
+ /* Activate the current timer. */
+ _tx_timer_system_activate(current_timer);
+#endif
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Lockout interrupts again. */
+ TX_DISABLE
+ }
+
+ /* Finally, suspend this thread and wait for the next expiration. */
+
+ /* Determine if another expiration took place while we were in this
+ thread. If so, process another expiration. */
+ if (_tx_timer_expired == TX_FALSE)
+ {
+
+ /* Otherwise, no timer expiration, so suspend the thread. */
+
+ /* Build pointer to the timer thread. */
+ thread_ptr = &_tx_timer_thread;
+
+ /* Set the status to suspending, in order to indicate the
+ suspension is in progress. */
+ thread_ptr -> tx_thread_state = TX_SUSPENDED;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+ /* Call actual non-interruptable thread suspension routine. */
+ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Set the suspending flag. */
+ thread_ptr -> tx_thread_suspending = TX_TRUE;
+
+ /* Increment the preempt disable count prior to suspending. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Call actual thread suspension routine. */
+ _tx_thread_system_suspend(thread_ptr);
+#endif
+ }
+ else
+ {
+
+ /* Restore interrupts. */
+ TX_RESTORE
+ }
+ }
+ }
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+
+}
+#endif
+
diff --git a/common/src/tx_trace_buffer_full_notify.c b/common/src/tx_trace_buffer_full_notify.c
new file mode 100644
index 00000000..e8723870
--- /dev/null
+++ b/common/src/tx_trace_buffer_full_notify.c
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_buffer_full_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets up the application callback function that is */
+/* called whenever the trace buffer becomes full. The application */
+/* can then swap to a new trace buffer in order not to lose any */
+/* events. */
+/* */
+/* INPUT */
+/* */
+/* full_buffer_callback Full trace buffer processing */
+/* function */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_buffer_full_notify(VOID (*full_buffer_callback)(VOID *buffer))
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Setup the callback function pointer. */
+ _tx_trace_full_notify_function = full_buffer_callback;
+
+ /* Return success. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (full_buffer_callback != TX_NULL)
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_trace_disable.c b/common/src/tx_trace_disable.c
new file mode 100644
index 00000000..61881ce2
--- /dev/null
+++ b/common/src/tx_trace_disable.c
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_disable PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function disables trace inside of ThreadX. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_disable(VOID)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+UINT status;
+
+
+ /* Determine if trace is already disabled. */
+ if (_tx_trace_buffer_current_ptr == TX_NULL)
+ {
+
+ /* Yes, trace is already disabled. */
+ status = TX_NOT_DONE;
+ }
+ else
+ {
+
+ /* Otherwise, simply clear the current pointer and registery start pointer to disable the trace. */
+ _tx_trace_buffer_current_ptr = TX_NULL;
+ _tx_trace_registry_start_ptr = TX_NULL;
+
+ /* Successful completion. */
+ status = TX_SUCCESS;
+ }
+
+ /* Return completion status. */
+ return(status);
+
+#else
+
+ /* Trace not enabled, return an error. */
+ return(TX_FEATURE_NOT_ENABLED);
+#endif
+}
+
diff --git a/common/src/tx_trace_enable.c b/common/src/tx_trace_enable.c
new file mode 100644
index 00000000..079500fd
--- /dev/null
+++ b/common/src/tx_trace_enable.c
@@ -0,0 +1,442 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_event_flags.h"
+#include "tx_queue.h"
+#include "tx_semaphore.h"
+#include "tx_mutex.h"
+#include "tx_block_pool.h"
+#include "tx_byte_pool.h"
+#endif
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_enable PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the ThreadX trace buffer and the */
+/* associated control variables, enabling it for operation. */
+/* */
+/* INPUT */
+/* */
+/* trace_buffer_start Start of trace buffer */
+/* trace_buffer_size Size (bytes) of trace buffer */
+/* registry_entries Number of object registry */
+/* entries. */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_trace_object_register Register existing objects */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_enable(VOID *trace_buffer_start, ULONG trace_buffer_size, ULONG registry_entries)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_TIMER *timer_ptr;
+TX_EVENT_FLAGS_GROUP *event_flags_ptr;
+TX_QUEUE *queue_ptr;
+TX_SEMAPHORE *semaphore_ptr;
+TX_MUTEX *mutex_ptr;
+TX_BLOCK_POOL *block_pool_ptr;
+TX_BYTE_POOL *byte_pool_ptr;
+UCHAR *work_ptr;
+UCHAR *event_start_ptr;
+TX_TRACE_OBJECT_ENTRY *entry_ptr;
+TX_TRACE_BUFFER_ENTRY *event_ptr;
+ULONG i;
+UINT status;
+
+
+ /* First, see if there is enough room for the control header, the registry entries, and at least one event in
+ memory supplied to this call. */
+ if (trace_buffer_size < ((sizeof(TX_TRACE_HEADER)) + ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) + (sizeof(TX_TRACE_BUFFER_ENTRY))))
+ {
+
+ /* No, the memory isn't big enough to hold one trace buffer entry. Return an error. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Determine if trace is already enabled. */
+ else if (_tx_trace_buffer_current_ptr != TX_NULL)
+ {
+
+ /* Yes, trace is already enabled. */
+ status = TX_NOT_DONE;
+ }
+ else
+ {
+
+ /* Set the enable bits for all events enabled. */
+ _tx_trace_event_enable_bits = 0xFFFFFFFFUL;
+
+ /* Setup working pointer to the supplied memory. */
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(trace_buffer_start);
+
+ /* Setup pointer to the trace control area. */
+ _tx_trace_header_ptr = TX_UCHAR_TO_HEADER_POINTER_CONVERT(work_ptr);
+
+ /* Move the working pointer past the control area. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_HEADER)));
+
+ /* Save the start of the trace object registry. */
+ _tx_trace_registry_start_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Setup the end of the trace object registry. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*registry_entries);
+ _tx_trace_registry_end_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Loop to make all trace object registry entries empty and valid. */
+ for (i = ((ULONG) 0); i < registry_entries; i++)
+ {
+
+ /* Setup the work pointer. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*i);
+
+ /* Convert to a registry entry pointer. */
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Initialize object registry entry. */
+ entry_ptr -> tx_trace_object_entry_available = (UCHAR) TX_TRUE;
+ entry_ptr -> tx_trace_object_entry_type = (UCHAR) TX_TRACE_OBJECT_TYPE_NOT_VALID;
+ entry_ptr -> tx_trace_object_entry_reserved1 = (UCHAR) 0;
+ entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) 0;
+ entry_ptr -> tx_trace_object_entry_thread_pointer = (ULONG) 0;
+ }
+
+ /* Setup the total number of registry entries. */
+ _tx_trace_total_registry_entries = registry_entries;
+
+ /* Setup the object registry available count to the total number of registry entries. */
+ _tx_trace_available_registry_entries = registry_entries;
+
+ /* Setup the search starting index to the first entry. */
+ _tx_trace_registry_search_start = ((ULONG) 0);
+
+ /* Setup the work pointer to after the trace object registry. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_end_ptr);
+
+ /* Adjust the remaining trace buffer size. */
+ trace_buffer_size = trace_buffer_size - ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) - (sizeof(TX_TRACE_HEADER));
+
+ /* Setup pointer to the start of the actual event trace log. */
+ _tx_trace_buffer_start_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Save the event trace log start address. */
+ event_start_ptr = work_ptr;
+
+ /* Calculate the end of the trace buffer. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY)))*(sizeof(TX_TRACE_BUFFER_ENTRY))));
+ _tx_trace_buffer_end_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Loop to mark all entries in the trace buffer as invalid. */
+ for (i = ((ULONG) 0); i < (trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY))); i++)
+ {
+
+ /* Setup the work pointer. */
+ work_ptr = TX_UCHAR_POINTER_ADD(event_start_ptr, (sizeof(TX_TRACE_BUFFER_ENTRY))*i);
+
+ /* Convert to a trace event pointer. */
+ event_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Mark this trace event as invalid. */
+ event_ptr -> tx_trace_buffer_entry_thread_pointer = ((ULONG) 0);
+ }
+
+ /* Now, fill in the event trace control header. */
+ _tx_trace_header_ptr -> tx_trace_header_id = TX_TRACE_VALID;
+ _tx_trace_header_ptr -> tx_trace_header_timer_valid_mask = TX_TRACE_TIME_MASK;
+ _tx_trace_header_ptr -> tx_trace_header_trace_base_address = TX_POINTER_TO_ULONG_CONVERT(trace_buffer_start);
+ _tx_trace_header_ptr -> tx_trace_header_registry_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_reserved1 = ((USHORT) 0);
+ _tx_trace_header_ptr -> tx_trace_header_object_name_size = ((USHORT) TX_TRACE_OBJECT_REGISTRY_NAME);
+ _tx_trace_header_ptr -> tx_trace_header_registry_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_end_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_end_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_reserved2 = 0xAAAAAAAAUL;
+ _tx_trace_header_ptr -> tx_trace_header_reserved3 = 0xBBBBBBBBUL;
+ _tx_trace_header_ptr -> tx_trace_header_reserved4 = 0xCCCCCCCCUL;
+
+ /* Now, loop through all existing ThreadX objects and register them in the newly setup trace buffer. */
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* First, disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Pickup the first thread and the number of created threads. */
+ thread_ptr = _tx_thread_created_ptr;
+ i = _tx_thread_created_count;
+
+ /* Loop to register all threads. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this thread. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, thread_ptr -> tx_thread_name,
+ TX_POINTER_TO_ULONG_CONVERT(thread_ptr -> tx_thread_stack_start), (ULONG) thread_ptr -> tx_thread_stack_size);
+
+ /* Move to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_created_next;
+ }
+
+ /* Pickup the first timer and the number of created timers. */
+ timer_ptr = _tx_timer_created_ptr;
+ i = _tx_timer_created_count;
+
+ /* Loop to register all timers. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this timer. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, timer_ptr -> tx_timer_name,
+ ((ULONG) 0), timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks);
+
+ /* Move to the next timer. */
+ timer_ptr = timer_ptr -> tx_timer_created_next;
+ }
+
+
+ /* Pickup the first event flag group and the number of created groups. */
+ event_flags_ptr = _tx_event_flags_created_ptr;
+ i = _tx_event_flags_created_count;
+
+ /* Loop to register all event flags groups. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this event flags group. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, event_flags_ptr, event_flags_ptr -> tx_event_flags_group_name, ((ULONG) 0), ((ULONG) 0));
+
+ /* Move to the next event flags group. */
+ event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next;
+ }
+
+ /* Pickup the first queue and the number of created queues. */
+ queue_ptr = _tx_queue_created_ptr;
+ i = _tx_queue_created_count;
+
+ /* Loop to register all queues. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this queue. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, queue_ptr -> tx_queue_name,
+ (queue_ptr -> tx_queue_capacity * (sizeof(ULONG))), ((ULONG) 0));
+
+ /* Move to the next queue. */
+ queue_ptr = queue_ptr -> tx_queue_created_next;
+ }
+
+ /* Pickup the first semaphore and the number of created semaphores. */
+ semaphore_ptr = _tx_semaphore_created_ptr;
+ i = _tx_semaphore_created_count;
+
+ /* Loop to register all semaphores. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this semaphore. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, semaphore_ptr -> tx_semaphore_name, ((ULONG) 0), ((ULONG) 0));
+
+ /* Move to the next semaphore. */
+ semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
+ }
+
+ /* Pickup the first mutex and the number of created mutexes. */
+ mutex_ptr = _tx_mutex_created_ptr;
+ i = _tx_mutex_created_count;
+
+ /* Loop to register all mutexes. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this mutex. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, mutex_ptr -> tx_mutex_name,
+ (ULONG) mutex_ptr -> tx_mutex_inherit, ((ULONG) 0));
+
+ /* Move to the next mutex. */
+ mutex_ptr = mutex_ptr -> tx_mutex_created_next;
+ }
+
+ /* Pickup the first block pool and the number of created block pools. */
+ block_pool_ptr = _tx_block_pool_created_ptr;
+ i = _tx_block_pool_created_count;
+
+ /* Loop to register all block pools. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this block pool. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, block_pool_ptr, block_pool_ptr -> tx_block_pool_name,
+ block_pool_ptr -> tx_block_pool_size, ((ULONG) 0));
+
+ /* Move to the next block pool. */
+ block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
+ }
+
+ /* Pickup the first byte pool and the number of created byte pools. */
+ byte_pool_ptr = _tx_byte_pool_created_ptr;
+ i = _tx_byte_pool_created_count;
+
+ /* Loop to register all byte pools. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this byte pool. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BYTE_POOL, byte_pool_ptr, byte_pool_ptr -> tx_byte_pool_name,
+ byte_pool_ptr -> tx_byte_pool_size, ((ULONG) 0));
+
+ /* Move to the next byte pool. */
+ byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release the preeemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Finally, setup the current buffer pointer, which effectively enables the trace! */
+ _tx_trace_buffer_current_ptr = (TX_TRACE_BUFFER_ENTRY *) _tx_trace_buffer_start_ptr;
+
+ /* Insert two RUNNING events so the buffer is not empty. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS)
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+
+ /* Return completion status. */
+ return(status);
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (trace_buffer_start != TX_NULL)
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (trace_buffer_size == ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (registry_entries == ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
+
+
diff --git a/common/src/tx_trace_event_filter.c b/common/src/tx_trace_event_filter.c
new file mode 100644
index 00000000..82c23789
--- /dev/null
+++ b/common/src/tx_trace_event_filter.c
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_event_filter PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets up the event filter, which allows the */
+/* application to filter various trace events during run-time. */
+/* */
+/* INPUT */
+/* */
+/* event_filter_bits Trace filter event bit(s) */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_event_filter(ULONG event_filter_bits)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Apply the specified filter by clearing the enable bits. */
+ _tx_trace_event_enable_bits = _tx_trace_event_enable_bits & (~event_filter_bits);
+
+ /* Return success. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (event_filter_bits != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_trace_event_unfilter.c b/common/src/tx_trace_event_unfilter.c
new file mode 100644
index 00000000..6c2e8011
--- /dev/null
+++ b/common/src/tx_trace_event_unfilter.c
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_event_unfilter PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function removes the event filter, which allows the */
+/* application to un-filter various trace events during run-time. */
+/* */
+/* INPUT */
+/* */
+/* event_unfilter_bits Trace un-filter event bit(s) */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_event_unfilter(ULONG event_unfilter_bits)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ /* Make sure the specified bits are set in the event enable variable. */
+ _tx_trace_event_enable_bits = _tx_trace_event_enable_bits | event_unfilter_bits;
+
+ /* Return success. */
+ return(TX_SUCCESS);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (event_unfilter_bits != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/tx_trace_initialize.c b/common/src/tx_trace_initialize.c
new file mode 100644
index 00000000..1be5408c
--- /dev/null
+++ b/common/src/tx_trace_initialize.c
@@ -0,0 +1,152 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+
+
+/* Define the pointer to the start of the trace buffer control structure. */
+
+TX_TRACE_HEADER *_tx_trace_header_ptr;
+
+
+/* Define the pointer to the start of the trace object registry area in the trace buffer. */
+
+TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_start_ptr;
+
+
+/* Define the pointer to the end of the trace object registry area in the trace buffer. */
+
+TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_end_ptr;
+
+
+/* Define the pointer to the starting entry of the actual trace event area of the trace buffer. */
+
+TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr;
+
+
+/* Define the pointer to the ending entry of the actual trace event area of the trace buffer. */
+
+TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr;
+
+
+/* Define the pointer to the current entry of the actual trace event area of the trace buffer. */
+
+TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr;
+
+
+/* Define the trace event enable bits, where each bit represents a type of event that can be enabled
+ or disabled dynamically by the application. */
+
+ULONG _tx_trace_event_enable_bits;
+
+
+/* Define a counter that is used in environments that don't have a timer source. This counter
+ is incremented on each use giving each event a unique timestamp. */
+
+ULONG _tx_trace_simulated_time;
+
+
+/* Define the function pointer used to call the application when the trace buffer wraps. If NULL,
+ the application has not registered a callback function. */
+
+VOID (*_tx_trace_full_notify_function)(VOID *buffer);
+
+
+/* Define the total number of registry entries. */
+
+ULONG _tx_trace_total_registry_entries;
+
+
+/* Define a counter that is used to track the number of available registry entries. */
+
+ULONG _tx_trace_available_registry_entries;
+
+
+/* Define an index that represents the start of the registry search. */
+
+ULONG _tx_trace_registry_search_start;
+
+#endif
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_initialize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the various control data structures for */
+/* the trace component. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level High level initialization */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_trace_initialize(VOID)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+#ifndef TX_DISABLE_REDUNDANT_CLEARING
+
+ /* Initialize all the pointers to the trace buffer to NULL. */
+ _tx_trace_header_ptr = TX_NULL;
+ _tx_trace_registry_start_ptr = TX_NULL;
+ _tx_trace_registry_end_ptr = TX_NULL;
+ _tx_trace_buffer_start_ptr = TX_NULL;
+ _tx_trace_buffer_end_ptr = TX_NULL;
+ _tx_trace_buffer_current_ptr = TX_NULL;
+#endif
+#endif
+}
+
diff --git a/common/src/tx_trace_interrupt_control.c b/common/src/tx_trace_interrupt_control.c
new file mode 100644
index 00000000..3f8addc4
--- /dev/null
+++ b/common/src/tx_trace_interrupt_control.c
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_interrupt_control PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function provides a shell for the tx_interrupt_control */
+/* function so that a trace event can be logged for its use. */
+/* */
+/* INPUT */
+/* */
+/* new_posture New interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* Previous Interrupt Posture */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_interrupt_control Interrupt control service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_interrupt_control(UINT new_posture)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+TX_INTERRUPT_SAVE_AREA
+UINT saved_posture;
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Insert this event into the trace buffer. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_INTERRUPT_CONTROL, TX_ULONG_TO_POINTER_CONVERT(new_posture), TX_POINTER_TO_ULONG_CONVERT(&saved_posture), 0, 0, TX_TRACE_INTERRUPT_CONTROL_EVENT)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Perform the interrupt service. */
+ saved_posture = _tx_thread_interrupt_control(new_posture);
+
+ /* Return saved posture. */
+ return(saved_posture);
+#else
+
+UINT saved_posture;
+
+ /* Perform the interrupt service. */
+ saved_posture = _tx_thread_interrupt_control(new_posture);
+
+ /* Return saved posture. */
+ return(saved_posture);
+#endif
+}
+
diff --git a/common/src/tx_trace_isr_enter_insert.c b/common/src/tx_trace_isr_enter_insert.c
new file mode 100644
index 00000000..9ab427c2
--- /dev/null
+++ b/common/src/tx_trace_isr_enter_insert.c
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_thread.h"
+#endif
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_isr_enter_insert PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function provides inserts an ISR entry event into the trace */
+/* buffer. */
+/* */
+/* INPUT */
+/* */
+/* isr_id User defined ISR ID */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_trace_isr_enter_insert(ULONG isr_id)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+UINT stack_address;
+ULONG system_state;
+UINT preempt_disable;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Insert this event into the trace buffer. */
+ system_state = TX_THREAD_GET_SYSTEM_STATE();
+ preempt_disable = _tx_thread_preempt_disable;
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_ISR_ENTER, &stack_address, isr_id, system_state, preempt_disable, TX_TRACE_INTERNAL_EVENTS)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (isr_id != ((ULONG) 0))
+ {
+
+ /* NOP code. */
+ TX_DISABLE
+ TX_RESTORE
+ }
+#endif
+}
+
diff --git a/common/src/tx_trace_isr_exit_insert.c b/common/src/tx_trace_isr_exit_insert.c
new file mode 100644
index 00000000..ef484c3b
--- /dev/null
+++ b/common/src/tx_trace_isr_exit_insert.c
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_thread.h"
+#endif
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_isr_exit_insert PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function provides inserts an ISR exit event into the trace */
+/* buffer. */
+/* */
+/* INPUT */
+/* */
+/* isr_id User defined ISR ID */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_trace_isr_exit_insert(ULONG isr_id)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+UINT stack_address;
+ULONG system_state;
+UINT preempt_disable;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Insert this event into the trace buffer. */
+ system_state = TX_THREAD_GET_SYSTEM_STATE();
+ preempt_disable = _tx_thread_preempt_disable;
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_ISR_EXIT, &stack_address, isr_id, system_state, preempt_disable, TX_TRACE_INTERNAL_EVENTS)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+#else
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (isr_id != ((ULONG) 0))
+ {
+
+ /* NOP code. */
+ TX_DISABLE
+ TX_RESTORE
+ }
+#endif
+}
+
diff --git a/common/src/tx_trace_object_register.c b/common/src/tx_trace_object_register.c
new file mode 100644
index 00000000..f4cee525
--- /dev/null
+++ b/common/src/tx_trace_object_register.c
@@ -0,0 +1,291 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_object_register PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers a ThreadX system object in the trace */
+/* registry area. This provides a mapping between the object pointers */
+/* stored in each trace event to the actual ThreadX objects. */
+/* */
+/* INPUT */
+/* */
+/* object_type Type of system object */
+/* object_ptr Address of system object */
+/* object_name Name of system object */
+/* parameter_1 Supplemental parameter 1 */
+/* parameter_2 Supplemental parameter 2 */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+UINT i, entries;
+UINT found, loop_break;
+TX_THREAD *thread_ptr;
+UCHAR *work_ptr;
+TX_TRACE_OBJECT_ENTRY *entry_ptr;
+
+
+ /* Determine if the registry area is setup. */
+ if (_tx_trace_registry_start_ptr != TX_NULL)
+ {
+
+ /* Trace buffer is enabled, proceed. */
+
+ /* Pickup the total entries. */
+ entries = _tx_trace_total_registry_entries;
+
+ /* Determine if there are available entries in the registry. */
+ if (_tx_trace_available_registry_entries != ((ULONG) 0))
+ {
+
+ /* There are more available entries, proceed. */
+
+ /* Initialize found to the max entries... indicating no space was found. */
+ found = entries;
+ loop_break = TX_FALSE;
+
+ /* Loop to find available entry. */
+ i = _tx_trace_registry_search_start;
+ do
+ {
+
+ /* Setup the registry entry pointer. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*i));
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Determine if this is the first pass building the registry. A NULL object value indicates this part
+ of the registry has never been used. */
+ if (entry_ptr -> tx_trace_object_entry_thread_pointer == (ULONG) 0)
+ {
+
+ /* Set found to this index and break out of the loop. */
+ found = i;
+ loop_break = TX_TRUE;
+ }
+
+ /* Determine if this entry matches the object pointer... we must reuse old entries left in the
+ registry. */
+ if (entry_ptr -> tx_trace_object_entry_thread_pointer == TX_POINTER_TO_ULONG_CONVERT(object_ptr))
+ {
+
+ /* Set found to this index and break out of the loop. */
+ found = i;
+ loop_break = TX_TRUE;
+ }
+
+ /* Determine if we should break out of the loop. */
+ if (loop_break == TX_TRUE)
+ {
+
+ /* Yes, break out of the loop. */
+ break;
+ }
+
+ /* Is this entry available? */
+ if (entry_ptr -> tx_trace_object_entry_available == TX_TRUE)
+ {
+
+ /* Yes, determine if we have not already found an empty slot. */
+ if (found == entries)
+ {
+ found = i;
+ }
+ else
+ {
+
+ /* Setup a pointer to the found entry. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found));
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ if (entry_ptr -> tx_trace_object_entry_type != ((UCHAR) 0))
+ {
+ found = i;
+ }
+ }
+ }
+
+ /* Move to the next entry. */
+ i++;
+
+ /* Determine if we have wrapped the list. */
+ if (i >= entries)
+ {
+
+ /* Yes, wrap to the beginning of the list. */
+ i = ((ULONG) 0);
+ }
+
+ } while (i != _tx_trace_registry_search_start);
+
+ /* Now determine if an empty or reuse entry has been found. */
+ if (found < entries)
+ {
+
+ /* Decrement the number of available entries. */
+ _tx_trace_available_registry_entries--;
+
+ /* Adjust the search index to the next entry. */
+ if ((found + ((ULONG) 1)) < entries)
+ {
+
+ /* Start searching from the next index. */
+ _tx_trace_registry_search_start = found + ((ULONG) 1);
+ }
+ else
+ {
+
+ /* Reset the search to the beginning of the list. */
+ _tx_trace_registry_search_start = ((ULONG) 0);
+ }
+
+ /* Yes, an entry has been found... */
+
+ /* Build a pointer to the found entry. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found));
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Populate the found entry! */
+ entry_ptr -> tx_trace_object_entry_available = ((UCHAR) TX_FALSE);
+ entry_ptr -> tx_trace_object_entry_type = object_type;
+ entry_ptr -> tx_trace_object_entry_thread_pointer = TX_POINTER_TO_ULONG_CONVERT(object_ptr);
+ entry_ptr -> tx_trace_object_entry_param_1 = parameter_1;
+ entry_ptr -> tx_trace_object_entry_param_2 = parameter_2;
+
+ /* Loop to copy the object name string... */
+ for (i = ((ULONG) 0); i < (((ULONG) TX_TRACE_OBJECT_REGISTRY_NAME)-((ULONG) 1)); i++)
+ {
+
+ /* Setup work pointer to the object name character. */
+ work_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, i);
+
+ /* Copy a character of the name. */
+ entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *work_ptr;
+
+ /* Determine if we are at the end. */
+ if (*work_ptr == ((UCHAR) 0))
+ {
+ break;
+ }
+ }
+
+ /* Null terminate the object string. */
+ entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) 0;
+
+ /* Determine if a thread object type is present. */
+ if (object_type == TX_TRACE_OBJECT_TYPE_THREAD)
+ {
+
+ /* Yes, a thread object is present. */
+
+ /* Setup a pointer to the thread. */
+ thread_ptr = TX_VOID_TO_THREAD_POINTER_CONVERT(object_ptr);
+
+ /* Store the thread's priority in the reserved bits. */
+ entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0x80) | ((UCHAR) (thread_ptr -> tx_thread_priority >> ((UCHAR) 8)));
+ entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) (thread_ptr -> tx_thread_priority & ((UCHAR) 0xFF));
+ }
+ else
+ {
+
+ /* For all other objects, set the reserved bytes to 0. */
+ entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0);
+ entry_ptr -> tx_trace_object_entry_reserved2 = ((UCHAR) 0);
+ }
+ }
+ }
+ }
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (object_type != ((UCHAR) 0))
+ {
+
+ if (object_ptr != TX_NULL)
+ {
+
+ if (object_name != TX_NULL)
+ {
+
+ if (parameter_1 != ((ULONG) 0))
+ {
+
+ if (parameter_2 != ((ULONG) 0))
+ {
+
+ /* NOP code. */
+ TX_DISABLE
+ TX_RESTORE
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
diff --git a/common/src/tx_trace_object_unregister.c b/common/src/tx_trace_object_unregister.c
new file mode 100644
index 00000000..abdc4bc1
--- /dev/null
+++ b/common/src/tx_trace_object_unregister.c
@@ -0,0 +1,131 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_object_unregister PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function unregisters a ThreadX system object from the trace */
+/* registry area. */
+/* */
+/* INPUT */
+/* */
+/* object_pointer Address of system object */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_trace_object_unregister(VOID *object_ptr)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+UINT i, entries;
+UCHAR *work_ptr;
+TX_TRACE_OBJECT_ENTRY *entry_ptr;
+
+
+ /* Determine if the registry area is setup. */
+ if (_tx_trace_registry_start_ptr != TX_NULL)
+ {
+
+ /* Registry is setup, proceed. */
+
+ /* Pickup the total entries. */
+ entries = _tx_trace_total_registry_entries;
+
+ /* Loop to find available entry. */
+ for (i = ((ULONG) 0); i < entries; i++)
+ {
+
+ /* Setup the registry entry pointer. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*i));
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Determine if this entry matches the object pointer... */
+ if (entry_ptr -> tx_trace_object_entry_thread_pointer == TX_POINTER_TO_ULONG_CONVERT(object_ptr))
+ {
+
+ /* Mark this entry as available, but leave the other information so that old trace entries can
+ still find it - if necessary! */
+ entry_ptr -> tx_trace_object_entry_available = ((UCHAR) TX_TRUE);
+
+ /* Increment the number of available registry entries. */
+ _tx_trace_available_registry_entries++;
+
+ /* Adjust the search index to this position. */
+ _tx_trace_registry_search_start = i;
+
+ break;
+ }
+ }
+ }
+#else
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (object_ptr != TX_NULL)
+ {
+
+ /* NOP code. */
+ TX_DISABLE
+ TX_RESTORE
+ }
+#endif
+}
+
diff --git a/common/src/tx_trace_user_event_insert.c b/common/src/tx_trace_user_event_insert.c
new file mode 100644
index 00000000..5e21ff64
--- /dev/null
+++ b/common/src/tx_trace_user_event_insert.c
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_user_event_insert PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts a user-defined event into the trace buffer. */
+/* */
+/* INPUT */
+/* */
+/* event_id User Event ID */
+/* info_field_1 First information field */
+/* info_field_2 First information field */
+/* info_field_3 First information field */
+/* info_field_4 First information field */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_user_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Determine if trace is disabled. */
+ if (_tx_trace_buffer_current_ptr == TX_NULL)
+ {
+
+ /* Yes, trace is already disabled. */
+ status = TX_NOT_DONE;
+ }
+ else
+ {
+
+ /* Insert this event into the trace buffer. */
+#ifdef TX_MISRA_ENABLE
+ TX_TRACE_IN_LINE_INSERT(event_id, TX_ULONG_TO_POINTER_CONVERT(info_field_1), info_field_2, info_field_3, info_field_4, ((ULONG) TX_TRACE_USER_EVENTS))
+#else
+ TX_TRACE_IN_LINE_INSERT(event_id, info_field_1, info_field_2, info_field_3, info_field_4, TX_TRACE_USER_EVENTS)
+#endif
+
+ /* Return successful status. */
+ status = TX_SUCCESS;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return completion status. */
+ return(status);
+
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (event_id != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (info_field_1 != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (info_field_2 != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (info_field_3 != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (info_field_4 != ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
diff --git a/common/src/txe_block_allocate.c b/common/src/txe_block_allocate.c
new file mode 100644
index 00000000..e100758f
--- /dev/null
+++ b/common/src/txe_block_allocate.c
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_block_allocate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the allocate block memory */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* block_ptr Pointer to place allocated block */
+/* pointer */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid pool pointer */
+/* TX_PTR_ERROR Invalid destination pointer */
+/* TX_WAIT_ERROR Invalid wait option */
+/* status Actual Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_allocate Actual block allocate function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+TX_THREAD *current_thread;
+#endif
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for an invalid pool pointer. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for an invalid destination for return pointer. */
+ else if (block_ptr == TX_NULL)
+ {
+
+ /* Null destination pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual block allocate function. */
+ status = _tx_block_allocate(pool_ptr, block_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_block_pool_create.c b/common/src/txe_block_pool_create.c
new file mode 100644
index 00000000..7aba85ac
--- /dev/null
+++ b/common/src/txe_block_pool_create.c
@@ -0,0 +1,227 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_block_pool_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the create block memory pool */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* name_ptr Pointer to block pool name */
+/* block_size Number of bytes in each block */
+/* pool_start Address of beginning of pool area */
+/* pool_size Number of bytes in the block pool */
+/* pool_control_block_size Size of block pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid pool pointer */
+/* TX_PTR_ERROR Invalid starting address */
+/* TX_SIZE_ERROR Invalid pool size */
+/* TX_CALLER_ERROR Invalid caller of pool */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_pool_create Actual block pool create function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
+ VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_BLOCK_POOL *next_pool;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for invalid control block size. */
+ else if (pool_control_block_size != (sizeof(TX_BLOCK_POOL)))
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_pool = _tx_block_pool_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_block_pool_created_count; i++)
+ {
+
+ /* Determine if this block pool matches the pool in the list. */
+ if (pool_ptr == next_pool)
+ {
+
+ break;
+ }
+ else
+ {
+ /* Move to the next pool. */
+ next_pool = next_pool -> tx_block_pool_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate pool. */
+ if (pool_ptr == next_pool)
+ {
+
+ /* Pool is already created, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for an invalid starting address. */
+ else if (pool_start == TX_NULL)
+ {
+
+ /* Null starting address pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for invalid pool size. */
+ if ((((block_size/(sizeof(void *)))*(sizeof(void *))) + (sizeof(void *))) >
+ ((pool_size/(sizeof(void *)))*(sizeof(void *))))
+ {
+
+ /* Not enough memory for one block, return appropriate error. */
+ status = TX_SIZE_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual block pool create function. */
+ status = _tx_block_pool_create(pool_ptr, name_ptr, block_size, pool_start, pool_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_block_pool_delete.c b/common/src/txe_block_pool_delete.c
new file mode 100644
index 00000000..dc18a69a
--- /dev/null
+++ b/common/src/txe_block_pool_delete.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_block_pool_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the delete block pool memory */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid memory block pool pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual delete function status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_pool_delete Actual block pool delete function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+#endif
+
+ /* Check for an invalid pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check the pool ID. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the call from an ISR or initialization? */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the call from the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+#endif
+
+ /* Call actual block pool delete function. */
+ status = _tx_block_pool_delete(pool_ptr);
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ }
+#endif
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_block_pool_info_get.c b/common/src/txe_block_pool_info_get.c
new file mode 100644
index 00000000..631a5529
--- /dev/null
+++ b/common/src/txe_block_pool_info_get.c
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_block_pool_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the block pool information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to block pool control blk */
+/* name Destination for the pool name */
+/* available_blocks Number of free blocks in pool */
+/* total_blocks Total number of blocks in pool */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on block pool */
+/* suspended_count Destination for suspended count */
+/* next_pool Destination for pointer to next */
+/* block pool on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid block pool pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_pool_info_get Actual block pool info get service*/
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
+ ULONG *total_blocks, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BLOCK_POOL **next_pool)
+{
+
+
+UINT status;
+
+
+ /* Check for an invalid block pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Block pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check the pool ID. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Block pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual block pool information get service. */
+ status = _tx_block_pool_info_get(pool_ptr, name, available_blocks,
+ total_blocks, first_suspended, suspended_count, next_pool);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_block_pool_prioritize.c b/common/src/txe_block_pool_prioritize.c
new file mode 100644
index 00000000..da32a9e8
--- /dev/null
+++ b/common/src/txe_block_pool_prioritize.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_block_pool_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the block pool prioritize call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_pool_prioritize Actual block pool prioritize */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid block memory pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Block memory pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check for invalid pool ID. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Block memory pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Call actual block pool prioritize function. */
+ status = _tx_block_pool_prioritize(pool_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_block_release.c b/common/src/txe_block_release.c
new file mode 100644
index 00000000..54914be0
--- /dev/null
+++ b/common/src/txe_block_release.c
@@ -0,0 +1,123 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Block Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_block_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_block_release PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the block release function call. */
+/* */
+/* INPUT */
+/* */
+/* block_ptr Pointer to memory block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_PTR_ERROR Invalid memory block pointer */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_block_release Actual block release function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_block_release(VOID *block_ptr)
+{
+
+UINT status;
+TX_BLOCK_POOL *pool_ptr;
+UCHAR **indirect_ptr;
+UCHAR *work_ptr;
+
+
+ /* First check the supplied pointer. */
+ if (block_ptr == TX_NULL)
+ {
+
+ /* The block pointer is invalid, return appropriate status. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Pickup the pool pointer which is just previous to the starting
+ address of block that the caller sees. */
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
+ work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *)));
+ indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
+ work_ptr = *indirect_ptr;
+ pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT(work_ptr);
+
+ /* Check for an invalid pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Now check for invalid pool ID. */
+ else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
+ {
+
+ /* Pool pointer is invalid, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Call actual block release function. */
+ status = _tx_block_release(block_ptr);
+ }
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_allocate.c b/common/src/txe_byte_allocate.c
new file mode 100644
index 00000000..5f374024
--- /dev/null
+++ b/common/src/txe_byte_allocate.c
@@ -0,0 +1,199 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_byte_allocate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in allocate bytes function call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* memory_ptr Pointer to place allocated bytes */
+/* pointer */
+/* memory_size Number of bytes to allocate */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid memory pool pointer */
+/* TX_PTR_ERROR Invalid destination pointer */
+/* TX_WAIT_ERROR Invalid wait option */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* TX_SIZE_ERROR Invalid size of memory request */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_allocate Actual byte allocate function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr,
+ ULONG memory_size, ULONG wait_option)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid byte pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check for invalid pool ID. */
+ else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for an invalid destination for return pointer. */
+ else if (memory_ptr == TX_NULL)
+ {
+
+ /* Null destination pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for an invalid memory size. */
+ else if (memory_size == ((ULONG) 0))
+ {
+
+ /* Error in size, return appropriate error. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Determine if the size is greater than the pool size. */
+ else if (memory_size > pool_ptr -> tx_byte_pool_size)
+ {
+
+ /* Error in size, return appropriate error. */
+ status = TX_SIZE_ERROR;
+ }
+
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is call from ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+ }
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Check for timer execution. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+#endif
+
+ /* Is everything still okay? */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual byte memory allocate function. */
+ status = _tx_byte_allocate(pool_ptr, memory_ptr, memory_size, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_pool_create.c b/common/src/txe_byte_pool_create.c
new file mode 100644
index 00000000..9a45d76b
--- /dev/null
+++ b/common/src/txe_byte_pool_create.c
@@ -0,0 +1,222 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_byte_pool_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the create byte pool memory */
+/* function. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* name_ptr Pointer to byte pool name */
+/* pool_start Address of beginning of pool area */
+/* pool_size Number of bytes in the byte pool */
+/* pool_control_block_size Size of byte pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid byte pool pointer */
+/* TX_PTR_ERROR Invalid pool starting address */
+/* TX_SIZE_ERROR Invalid pool size */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_pool_create Actual byte pool create function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_BYTE_POOL *next_pool;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid byte pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now see if the pool control block size is valid. */
+ else if (pool_control_block_size != (sizeof(TX_BYTE_POOL)))
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_pool = _tx_byte_pool_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_byte_pool_created_count; i++)
+ {
+
+ /* Determine if this byte pool matches the pool in the list. */
+ if (pool_ptr == next_pool)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to the next pool. */
+ next_pool = next_pool -> tx_byte_pool_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate pool. */
+ if (pool_ptr == next_pool)
+ {
+
+ /* Pool is already created, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for an invalid starting address. */
+ else if (pool_start == TX_NULL)
+ {
+
+ /* Null starting address pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for invalid pool size. */
+ else if (pool_size < TX_BYTE_POOL_MIN)
+ {
+
+ /* Pool not big enough, return appropriate error. */
+ status = TX_SIZE_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual byte pool create function. */
+ status = _tx_byte_pool_create(pool_ptr, name_ptr, pool_start, pool_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_pool_delete.c b/common/src/txe_byte_pool_delete.c
new file mode 100644
index 00000000..b3d8a505
--- /dev/null
+++ b/common/src/txe_byte_pool_delete.c
@@ -0,0 +1,144 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Pool */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_byte_pool_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the delete byte pool function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid pool pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_pool_delete Actual byte pool delete function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_pool_delete(TX_BYTE_POOL *pool_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+#endif
+
+ /* Check for an invalid byte pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check the pool ID. */
+ else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Check for interrupt or initialization. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+#endif
+
+ /* Call actual byte pool delete function. */
+ status = _tx_byte_pool_delete(pool_ptr);
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ }
+#endif
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_pool_info_get.c b/common/src/txe_byte_pool_info_get.c
new file mode 100644
index 00000000..cd735df8
--- /dev/null
+++ b/common/src/txe_byte_pool_info_get.c
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_byte_pool_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the byte pool information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to byte pool control block*/
+/* name Destination for the pool name */
+/* available_bytes Number of free bytes in byte pool */
+/* fragments Number of fragments in byte pool */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on byte pool */
+/* suspended_count Destination for suspended count */
+/* next_pool Destination for pointer to next */
+/* byte pool on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_POOL_ERROR Invalid byte pool pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_pool_info_get Actual byte pool info get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
+ ULONG *fragments, TX_THREAD **first_suspended,
+ ULONG *suspended_count, TX_BYTE_POOL **next_pool)
+{
+
+UINT status;
+
+
+ /* Check for an invalid byte pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Block pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check for invalid pool ID. */
+ else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Block pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual byte pool information get service. */
+ status = _tx_byte_pool_info_get(pool_ptr, name, available_bytes,
+ fragments, first_suspended, suspended_count, next_pool);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_pool_prioritize.c b/common/src/txe_byte_pool_prioritize.c
new file mode 100644
index 00000000..18e7e4b4
--- /dev/null
+++ b/common/src/txe_byte_pool_prioritize.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_byte_pool_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the byte pool prioritize call. */
+/* */
+/* INPUT */
+/* */
+/* pool_ptr Pointer to pool control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_pool_prioritize Actual byte pool prioritize */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid byte memory pool pointer. */
+ if (pool_ptr == TX_NULL)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+
+ /* Now check for invalid pool ID. */
+ else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
+ {
+
+ /* Byte pool pointer is invalid, return appropriate error code. */
+ status = TX_POOL_ERROR;
+ }
+ else
+ {
+
+ /* Call actual byte pool prioritize function. */
+ status = _tx_byte_pool_prioritize(pool_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_byte_release.c b/common/src/txe_byte_release.c
new file mode 100644
index 00000000..c7a11714
--- /dev/null
+++ b/common/src/txe_byte_release.c
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Byte Memory */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_byte_pool.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_byte_release PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the release byte function call. */
+/* */
+/* INPUT */
+/* */
+/* memory_ptr Pointer to allocated memory */
+/* */
+/* OUTPUT */
+/* */
+/* TX_PTR_ERROR Invalid memory pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_release Actual byte release function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_byte_release(VOID *memory_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* First check the supplied memory pointer. */
+ if (memory_ptr == TX_NULL)
+ {
+
+ /* The byte memory pointer is invalid, return appropriate status. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual byte release function. */
+ status = _tx_byte_release(memory_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_create.c b/common/src/txe_event_flags_create.c
new file mode 100644
index 00000000..ed2038ee
--- /dev/null
+++ b/common/src/txe_event_flags_create.c
@@ -0,0 +1,203 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the event flag creation function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to event flags group */
+/* control block */
+/* name_ptr Pointer to event flags name */
+/* event_control_block_size Size of event flags control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_GROUP_ERROR Invalid event flag group pointer */
+/* TX_CALLER_ERROR Invalid calling function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_create Actual create function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_EVENT_FLAGS_GROUP *next_group;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid event flags group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for proper control block size. */
+ else if (event_control_block_size != (sizeof(TX_EVENT_FLAGS_GROUP)))
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_group = _tx_event_flags_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_event_flags_created_count; i++)
+ {
+
+ /* Determine if this group matches the event flags group in the list. */
+ if (group_ptr == next_group)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to the next group. */
+ next_group = next_group -> tx_event_flags_group_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate event flag group. */
+ if (group_ptr == next_group)
+ {
+
+ /* Group is already created, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual event flags create function. */
+ status = _tx_event_flags_create(group_ptr, name_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_delete.c b/common/src/txe_event_flags_delete.c
new file mode 100644
index 00000000..ebe73938
--- /dev/null
+++ b/common/src/txe_event_flags_delete.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the delete event flags group */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_GROUP_ERROR Invalid event flag group pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_delete Actual delete event flags function*/
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+#endif
+
+ /* Check for an invalid event flag group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for invalid event flag group ID. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the caller an ISR or Initialization? */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the caller the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+#endif
+
+ /* Call actual event flag group delete function. */
+ status = _tx_event_flags_delete(group_ptr);
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ }
+#endif
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_get.c b/common/src/txe_event_flags_get.c
new file mode 100644
index 00000000..3ded965f
--- /dev/null
+++ b/common/src/txe_event_flags_get.c
@@ -0,0 +1,177 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the event flags get function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* requested_event_flags Event flags requested */
+/* get_option Specifies and/or and clear options*/
+/* actual_flags_ptr Pointer to place the actual flags */
+/* the service retrieved */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_GROUP_ERROR Invalid event flags group pointer */
+/* TX_PTR_ERROR Invalid actual flags pointer */
+/* TX_WAIT_ERROR Invalid wait option */
+/* TX_OPTION_ERROR Invalid get option */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_get Actual event flags get function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
+ UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid event flag group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for invalid event group ID. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Check for an invalid destination for actual flags. */
+ else if (actual_flags_ptr == TX_NULL)
+ {
+
+ /* Null destination pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Is everything still okay? */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Check for invalid get option. */
+ if (get_option > TX_AND_CLEAR)
+ {
+
+ /* Invalid get events option, return appropriate error. */
+ status = TX_OPTION_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual event flags get function. */
+ status = _tx_event_flags_get(group_ptr, requested_flags, get_option, actual_flags_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_info_get.c b/common/src/txe_event_flags_info_get.c
new file mode 100644
index 00000000..6abfeb79
--- /dev/null
+++ b/common/src/txe_event_flags_info_get.c
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the event flag information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to event flag group */
+/* name Destination for the event flags */
+/* group name */
+/* current_flags Current event flags */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on event flags */
+/* suspended_count Destination for suspended count */
+/* next_group Destination for pointer to next */
+/* event flag group on the created */
+/* list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_GROUP_ERROR Invalid event flag group pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_info_get Actual event flags group info */
+/* get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_EVENT_FLAGS_GROUP **next_group)
+{
+
+UINT status;
+
+
+ /* Check for an invalid event flag group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for invalid event flag group ID. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual event flags group information get service. */
+ status = _tx_event_flags_info_get(group_ptr, name, current_flags, first_suspended,
+ suspended_count, next_group);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_set.c b/common/src/txe_event_flags_set.c
new file mode 100644
index 00000000..a0e97bb8
--- /dev/null
+++ b/common/src/txe_event_flags_set.c
@@ -0,0 +1,126 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_set PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the set event flags function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block */
+/* flags_to_set Event flags to set */
+/* set_option Specified either AND or OR */
+/* operation on the event flags */
+/* */
+/* OUTPUT */
+/* */
+/* TX_GROUP_ERROR Invalid event flags group pointer */
+/* TX_OPTION_ERROR Invalid set option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_set Actual set event flags function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option)
+{
+
+UINT status;
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid event flag group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for invalid event flag group ID. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+ else
+ {
+
+ /* Check for invalid set option. */
+ if (set_option != TX_AND)
+ {
+
+ if (set_option != TX_OR)
+ {
+
+ /* Invalid set events option, return appropriate error. */
+ status = TX_OPTION_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual event flags set function. */
+ status = _tx_event_flags_set(group_ptr, flags_to_set, set_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_event_flags_set_notify.c b/common/src/txe_event_flags_set_notify.c
new file mode 100644
index 00000000..621848be
--- /dev/null
+++ b/common/src/txe_event_flags_set_notify.c
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Event Flags */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_event_flags.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_event_flags_set_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the event flags set notify */
+/* callback function call. */
+/* */
+/* INPUT */
+/* */
+/* group_ptr Pointer to group control block*/
+/* group_put_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_event_flags_set_notify Actual event flags set notify */
+/* call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr))
+{
+
+UINT status;
+
+
+ /* Check for an invalid group pointer. */
+ if (group_ptr == TX_NULL)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+
+ /* Now check for invalid event group ID. */
+ else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
+ {
+
+ /* Event flags group pointer is invalid, return appropriate error code. */
+ status = TX_GROUP_ERROR;
+ }
+ else
+ {
+
+ /* Call actual event flags set notify function. */
+ status = _tx_event_flags_set_notify(group_ptr, events_set_notify);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_create.c b/common/src/txe_mutex_create.c
new file mode 100644
index 00000000..76f9a215
--- /dev/null
+++ b/common/src/txe_mutex_create.c
@@ -0,0 +1,221 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_mutex_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the create mutex function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* name_ptr Pointer to mutex name */
+/* inherit Initial mutex count */
+/* mutex_control_block_size Size of mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_MUTEX_ERROR Invalid mutex pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* TX_INHERIT_ERROR Invalid inherit option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_create Actual create mutex function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_MUTEX *next_mutex;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check to make sure the control block is the correct size. */
+ else if (mutex_control_block_size != (sizeof(TX_MUTEX)))
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_mutex = _tx_mutex_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_mutex_created_count; i++)
+ {
+
+ /* Determine if this mutex matches the mutex in the list. */
+ if (mutex_ptr == next_mutex)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to the next mutex. */
+ next_mutex = next_mutex -> tx_mutex_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate mutex. */
+ if (mutex_ptr == next_mutex)
+ {
+
+ /* Mutex is already created, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Check for a valid inherit option. */
+ if (inherit != TX_INHERIT)
+ {
+
+ if (inherit != TX_NO_INHERIT)
+ {
+
+ /* Inherit option is illegal. */
+ status = TX_INHERIT_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual mutex create function. */
+ status = _tx_mutex_create(mutex_ptr, name_ptr, inherit);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_delete.c b/common/src/txe_mutex_delete.c
new file mode 100644
index 00000000..de5ff718
--- /dev/null
+++ b/common/src/txe_mutex_delete.c
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_mutex_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the mutex delete function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_MUTEX_ERROR Invalid mutex pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_delete Actual delete mutex function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_delete(TX_MUTEX *mutex_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+#endif
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check for a valid mutex ID. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the caller an ISR or Initialization? */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the caller the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+#endif
+
+ /* Call actual mutex delete function. */
+ status = _tx_mutex_delete(mutex_ptr);
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ }
+#endif
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_get.c b/common/src/txe_mutex_get.c
new file mode 100644
index 00000000..c1a81601
--- /dev/null
+++ b/common/src/txe_mutex_get.c
@@ -0,0 +1,168 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#ifndef TX_TIMER_PROCESS_IN_ISR
+#include "tx_timer.h"
+#endif
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_mutex_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the mutex get function call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_MUTEX_ERROR Invalid mutex pointer */
+/* TX_WAIT_ERROR Invalid wait option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_get Actual get mutex function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check for a valid mutex ID. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Yes, invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual get mutex function. */
+ status = _tx_mutex_get(mutex_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_info_get.c b/common/src/txe_mutex_info_get.c
new file mode 100644
index 00000000..853c7470
--- /dev/null
+++ b/common/src/txe_mutex_info_get.c
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_mutex_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the mutex information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* name Destination for the mutex name */
+/* count Destination for the owner count */
+/* owner Destination for the owner's */
+/* thread control block pointer */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on the mutex */
+/* suspended_count Destination for suspended count */
+/* next_mutex Destination for pointer to next */
+/* mutex on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_MUTEX_ERROR Invalid mutex pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_info_get Actual mutex info get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_MUTEX **next_mutex)
+{
+
+UINT status;
+
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check for invalid mutex ID. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual mutex information get service. */
+ status = _tx_mutex_info_get(mutex_ptr, name, count, owner, first_suspended,
+ suspended_count, next_mutex);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_prioritize.c b/common/src/txe_mutex_prioritize.c
new file mode 100644
index 00000000..9df7065a
--- /dev/null
+++ b/common/src/txe_mutex_prioritize.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_mutex_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the mutex prioritize call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_prioritize Actual mutex prioritize */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_prioritize(TX_MUTEX *mutex_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check for invalid mutex ID. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Call actual mutex prioritize function. */
+ status = _tx_mutex_prioritize(mutex_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_mutex_put.c b/common/src/txe_mutex_put.c
new file mode 100644
index 00000000..16de56e1
--- /dev/null
+++ b/common/src/txe_mutex_put.c
@@ -0,0 +1,124 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Mutex */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_mutex_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the mutex put function call. */
+/* */
+/* INPUT */
+/* */
+/* mutex_ptr Pointer to mutex control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_MUTEX_ERROR Invalid mutex pointer */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_put Actual put mutex function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_mutex_put(TX_MUTEX *mutex_ptr)
+{
+
+UINT status;
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid mutex pointer. */
+ if (mutex_ptr == TX_NULL)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+
+ /* Now check for invalid mutex ID. */
+ else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Mutex pointer is invalid, return appropriate error code. */
+ status = TX_MUTEX_ERROR;
+ }
+ else
+ {
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual put mutex function. */
+ status = _tx_mutex_put(mutex_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_create.c b/common/src/txe_queue_create.c
new file mode 100644
index 00000000..006386f3
--- /dev/null
+++ b/common/src/txe_queue_create.c
@@ -0,0 +1,237 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue create function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* name_ptr Pointer to queue name */
+/* message_size Size of each queue message */
+/* queue_start Starting address of the queue area*/
+/* queue_size Number of bytes in the queue */
+/* queue_control_block_size Size of queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_PTR_ERROR Invalid starting address of queue */
+/* TX_SIZE_ERROR Invalid message queue size */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_create Actual queue create function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+ VOID *queue_start, ULONG queue_size, UINT queue_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_QUEUE *next_queue;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for a valid control block size. */
+ else if (queue_control_block_size != (sizeof(TX_QUEUE)))
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_queue = _tx_queue_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_queue_created_count; i++)
+ {
+
+ /* Determine if this queue matches the queue in the list. */
+ if (queue_ptr == next_queue)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to the next queue. */
+ next_queue = next_queue -> tx_queue_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate queue. */
+ if (queue_ptr == next_queue)
+ {
+
+ /* Queue is already created, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Check the starting address of the queue. */
+ else if (queue_start == TX_NULL)
+ {
+
+ /* Invalid starting address of queue. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for an invalid message size - less than 1. */
+ else if (message_size < TX_1_ULONG)
+ {
+
+ /* Invalid message size specified. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check for an invalid message size - greater than 16. */
+ else if (message_size > TX_16_ULONG)
+ {
+
+ /* Invalid message size specified. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check on the queue size. */
+ else if ((queue_size/(sizeof(ULONG))) < message_size)
+ {
+
+ /* Invalid queue size specified. */
+ status = TX_SIZE_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual queue create function. */
+ status = _tx_queue_create(queue_ptr, name_ptr, message_size, queue_start, queue_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
diff --git a/common/src/txe_queue_delete.c b/common/src/txe_queue_delete.c
new file mode 100644
index 00000000..75a63778
--- /dev/null
+++ b/common/src/txe_queue_delete.c
@@ -0,0 +1,142 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue delete function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_delete Actual queue delete function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_delete(TX_QUEUE *queue_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for a valid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the caller an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the caller the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+#endif
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual queue delete function. */
+ status = _tx_queue_delete(queue_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_flush.c b/common/src/txe_queue_flush.c
new file mode 100644
index 00000000..09a658f4
--- /dev/null
+++ b/common/src/txe_queue_flush.c
@@ -0,0 +1,102 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_flush PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue flush function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_flush Actual queue flush function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_flush(TX_QUEUE *queue_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for invalid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual queue flush function. */
+ status = _tx_queue_flush(queue_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_front_send.c b/common/src/txe_queue_front_send.c
new file mode 100644
index 00000000..91c1eee0
--- /dev/null
+++ b/common/src/txe_queue_front_send.c
@@ -0,0 +1,158 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_front_send PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue send function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* source_ptr Pointer to message source */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_PTR_ERROR Invalid source pointer - NULL */
+/* TX_WAIT_ERROR Invalid wait option - non thread */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_front_send Actual queue send function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for invalid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Check for an invalid source for message. */
+ else if (source_ptr == TX_NULL)
+ {
+
+ /* Null source pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual queue front send function. */
+ status = _tx_queue_front_send(queue_ptr, source_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_info_get.c b/common/src/txe_queue_info_get.c
new file mode 100644
index 00000000..0e05cf5a
--- /dev/null
+++ b/common/src/txe_queue_info_get.c
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* name Destination for the queue name */
+/* enqueued Destination for enqueued count */
+/* available_storage Destination for available storage */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on this queue */
+/* suspended_count Destination for suspended count */
+/* next_queue Destination for pointer to next */
+/* queue on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_info_get Actual information get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
+ TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue)
+{
+
+UINT status;
+
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for a valid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual queue information get service. */
+ status = _tx_queue_info_get(queue_ptr, name, enqueued, available_storage, first_suspended,
+ suspended_count, next_queue);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_prioritize.c b/common/src/txe_queue_prioritize.c
new file mode 100644
index 00000000..2a40fe36
--- /dev/null
+++ b/common/src/txe_queue_prioritize.c
@@ -0,0 +1,98 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue prioritize call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_prioritize Actual queue prioritize function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_prioritize(TX_QUEUE *queue_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for invalid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual queue prioritize function. */
+ status = _tx_queue_prioritize(queue_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_receive.c b/common/src/txe_queue_receive.c
new file mode 100644
index 00000000..93af544d
--- /dev/null
+++ b/common/src/txe_queue_receive.c
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_receive PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue receive function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* destination_ptr Pointer to message destination */
+/* **** MUST BE LARGE ENOUGH TO */
+/* HOLD MESSAGE **** */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_PTR_ERROR Invalid destination pointer (NULL)*/
+/* TX_WAIT_ERROR Invalid wait option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_receive Actual queue receive function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for invalid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Check for an invalid destination for message. */
+ else if (destination_ptr == TX_NULL)
+ {
+
+ /* Null destination pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual queue receive function. */
+ status = _tx_queue_receive(queue_ptr, destination_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_send.c b/common/src/txe_queue_send.c
new file mode 100644
index 00000000..2a568742
--- /dev/null
+++ b/common/src/txe_queue_send.c
@@ -0,0 +1,158 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_send PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue send function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block */
+/* source_ptr Pointer to message source */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_QUEUE_ERROR Invalid queue pointer */
+/* TX_PTR_ERROR Invalid source pointer - NULL */
+/* TX_WAIT_ERROR Invalid wait option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_send Actual queue send function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for invalid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Check for an invalid source for message. */
+ else if (source_ptr == TX_NULL)
+ {
+
+ /* Null source pointer, return appropriate error. */
+ status = TX_PTR_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual queue send function. */
+ status = _tx_queue_send(queue_ptr, source_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_queue_send_notify.c b/common/src/txe_queue_send_notify.c
new file mode 100644
index 00000000..a6c0d746
--- /dev/null
+++ b/common/src/txe_queue_send_notify.c
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Queue */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_queue_send_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the queue send notify */
+/* callback function call. */
+/* */
+/* INPUT */
+/* */
+/* queue_ptr Pointer to queue control block*/
+/* queue_send_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_queue_send_notify Actual queue send notify call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr))
+{
+
+UINT status;
+
+
+ /* Check for an invalid queue pointer. */
+ if (queue_ptr == TX_NULL)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+
+ /* Now check for a valid queue ID. */
+ else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+ {
+
+ /* Queue pointer is invalid, return appropriate error code. */
+ status = TX_QUEUE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual queue send notify function. */
+ status = _tx_queue_send_notify(queue_ptr, queue_send_notify);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_ceiling_put.c b/common/src/txe_semaphore_ceiling_put.c
new file mode 100644
index 00000000..e404d4c7
--- /dev/null
+++ b/common/src/txe_semaphore_ceiling_put.c
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_ceiling_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore ceiling put */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore */
+/* ceiling Maximum value of semaphore */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* TX_INVALID_CEILING Invalid semaphore ceiling */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_ceiling_put Actual semaphore ceiling put */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling)
+{
+
+UINT status;
+
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for a valid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Determine if the ceiling is valid - must be greater than 1. */
+ else if (ceiling == ((ULONG) 0))
+ {
+
+ /* Invalid ceiling, return error. */
+ status = TX_INVALID_CEILING;
+ }
+ else
+ {
+
+ /* Call actual semaphore ceiling put function. */
+ status = _tx_semaphore_ceiling_put(semaphore_ptr, ceiling);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_create.c b/common/src/txe_semaphore_create.c
new file mode 100644
index 00000000..9cb9ac61
--- /dev/null
+++ b/common/src/txe_semaphore_create.c
@@ -0,0 +1,208 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the create semaphore function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* name_ptr Pointer to semaphore name */
+/* initial_count Initial semaphore count */
+/* semaphore_control_block_size Size of semaphore control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_create Actual create semaphore function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_SEMAPHORE *next_semaphore;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for a valid semaphore ID. */
+ else if (semaphore_control_block_size != (sizeof(TX_SEMAPHORE)))
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_semaphore = _tx_semaphore_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_semaphore_created_count; i++)
+ {
+
+ /* Determine if this semaphore matches the current semaphore in the list. */
+ if (semaphore_ptr == next_semaphore)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to next semaphore. */
+ next_semaphore = next_semaphore -> tx_semaphore_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate semaphore. */
+ if (semaphore_ptr == next_semaphore)
+ {
+
+ /* Semaphore is already created, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+#endif
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual semaphore create function. */
+ status = _tx_semaphore_create(semaphore_ptr, name_ptr, initial_count);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_delete.c b/common/src/txe_semaphore_delete.c
new file mode 100644
index 00000000..9036373d
--- /dev/null
+++ b/common/src/txe_semaphore_delete.c
@@ -0,0 +1,143 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore delete function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_delete Actual delete semaphore function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for invalid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the caller an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the caller the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+#endif
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual semaphore delete function. */
+ status = _tx_semaphore_delete(semaphore_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_get.c b/common/src/txe_semaphore_get.c
new file mode 100644
index 00000000..10f37e59
--- /dev/null
+++ b/common/src/txe_semaphore_get.c
@@ -0,0 +1,148 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore get function call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* TX_WAIT_ERROR Invalid wait option */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_get Actual get semaphore function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for invalid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Check for a wait option error. Only threads are allowed any form of
+ suspension. */
+ if (wait_option != TX_NO_WAIT)
+ {
+
+ /* Is the call from an ISR or Initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ else
+ {
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Is the current thread the timer thread? */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* A non-thread is trying to suspend, return appropriate error code. */
+ status = TX_WAIT_ERROR;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual get semaphore function. */
+ status = _tx_semaphore_get(semaphore_ptr, wait_option);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_info_get.c b/common/src/txe_semaphore_info_get.c
new file mode 100644
index 00000000..35e88f79
--- /dev/null
+++ b/common/src/txe_semaphore_info_get.c
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* name Destination for the semaphore name*/
+/* current_value Destination for current value of */
+/* the semaphore */
+/* first_suspended Destination for pointer of first */
+/* thread suspended on semaphore */
+/* suspended_count Destination for suspended count */
+/* next_semaphore Destination for pointer to next */
+/* semaphore on the created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_info_get Actual semaphore info get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
+ TX_THREAD **first_suspended, ULONG *suspended_count,
+ TX_SEMAPHORE **next_semaphore)
+{
+
+UINT status;
+
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for a valid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual semaphore information get service. */
+ status = _tx_semaphore_info_get(semaphore_ptr, name, current_value, first_suspended,
+ suspended_count, next_semaphore);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_prioritize.c b/common/src/txe_semaphore_prioritize.c
new file mode 100644
index 00000000..eb980d21
--- /dev/null
+++ b/common/src/txe_semaphore_prioritize.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_semaphore_prioritize PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore prioritize call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_prioritize Actual semaphore prioritize */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for a valid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual semaphore prioritize function. */
+ status = _tx_semaphore_prioritize(semaphore_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_put.c b/common/src/txe_semaphore_put.c
new file mode 100644
index 00000000..dd35addd
--- /dev/null
+++ b/common/src/txe_semaphore_put.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_put PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore put function call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore control block*/
+/* */
+/* OUTPUT */
+/* */
+/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_put Actual put semaphore function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_put(TX_SEMAPHORE *semaphore_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for invalid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual put semaphore function. */
+ status = _tx_semaphore_put(semaphore_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_semaphore_put_notify.c b/common/src/txe_semaphore_put_notify.c
new file mode 100644
index 00000000..d9794f5a
--- /dev/null
+++ b/common/src/txe_semaphore_put_notify.c
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Semaphore */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_semaphore.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_semaphore_put_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the semaphore put notify */
+/* callback function call. */
+/* */
+/* INPUT */
+/* */
+/* semaphore_ptr Pointer to semaphore */
+/* semaphore_put_notify Application callback function */
+/* (TX_NULL disables notify) */
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_semaphore_put_notify Actual semaphore put notify */
+/* call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr))
+{
+
+UINT status;
+
+
+ /* Check for an invalid semaphore pointer. */
+ if (semaphore_ptr == TX_NULL)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+
+ /* Now check for invalid semaphore ID. */
+ else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
+ {
+
+ /* Semaphore pointer is invalid, return appropriate error code. */
+ status = TX_SEMAPHORE_ERROR;
+ }
+ else
+ {
+
+ /* Call actual semaphore put notify function. */
+ status = _tx_semaphore_put_notify(semaphore_ptr, semaphore_put_notify);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_create.c b/common/src/txe_thread_create.c
new file mode 100644
index 00000000..12b67017
--- /dev/null
+++ b/common/src/txe_thread_create.c
@@ -0,0 +1,311 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_thread_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread create function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* name Pointer to thread name string */
+/* entry_function Entry function of the thread */
+/* entry_input 32-bit input value to thread */
+/* stack_start Pointer to start of stack */
+/* stack_size Stack size in bytes */
+/* priority Priority of thread (0-31) */
+/* preempt_threshold Preemption threshold */
+/* time_slice Thread time-slice value */
+/* auto_start Automatic start selection */
+/* thread_control_block_size Size of thread control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_PTR_ERROR Invalid entry point or stack */
+/* address */
+/* TX_SIZE_ERROR Invalid stack size -too small */
+/* TX_PRIORITY_ERROR Invalid thread priority */
+/* TX_THRESH_ERROR Invalid preemption threshold */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_create Actual thread create function */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
+ VOID (*entry_function)(ULONG id), ULONG entry_input,
+ VOID *stack_start, ULONG stack_size,
+ UINT priority, UINT preempt_threshold,
+ ULONG time_slice, UINT auto_start, UINT thread_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+UINT break_flag;
+ULONG i;
+TX_THREAD *next_thread;
+VOID *stack_end;
+UCHAR *work_ptr;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread control block size. */
+ else if (thread_control_block_size != (sizeof(TX_THREAD)))
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ break_flag = TX_FALSE;
+ next_thread = _tx_thread_created_ptr;
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (stack_size - ((ULONG) 1)));
+ stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(work_ptr);
+ for (i = ((ULONG) 0); i < _tx_thread_created_count; i++)
+ {
+
+ /* Determine if this thread matches the thread in the list. */
+ if (thread_ptr == next_thread)
+ {
+
+ /* Set the break flag. */
+ break_flag = TX_TRUE;
+ }
+
+ /* Determine if we need to break the loop. */
+ if (break_flag == TX_TRUE)
+ {
+
+ /* Yes, break out of the loop. */
+ break;
+ }
+
+ /* Check the stack pointer to see if it overlaps with this thread's stack. */
+ if (stack_start >= next_thread -> tx_thread_stack_start)
+ {
+
+ if (stack_start < next_thread -> tx_thread_stack_end)
+ {
+
+ /* This stack overlaps with an existing thread, clear the stack pointer to
+ force a stack error below. */
+ stack_start = TX_NULL;
+
+ /* Set the break flag. */
+ break_flag = TX_TRUE;
+ }
+ }
+
+ /* Check the end of the stack to see if it is inside this thread's stack area as well. */
+ if (stack_end >= next_thread -> tx_thread_stack_start)
+ {
+
+ if (stack_end < next_thread -> tx_thread_stack_end)
+ {
+
+ /* This stack overlaps with an existing thread, clear the stack pointer to
+ force a stack error below. */
+ stack_start = TX_NULL;
+
+ /* Set the break flag. */
+ break_flag = TX_TRUE;
+ }
+ }
+
+ /* Move to the next thread. */
+ next_thread = next_thread -> tx_thread_created_next;
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate thread. */
+ if (thread_ptr == next_thread)
+ {
+
+ /* Thread is already created, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for invalid starting address of stack. */
+ else if (stack_start == TX_NULL)
+ {
+
+ /* Invalid stack or entry point, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for invalid thread entry point. */
+ else if (entry_function == TX_NULL)
+ {
+
+ /* Invalid stack or entry point, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check the stack size. */
+ else if (stack_size < ((ULONG) TX_MINIMUM_STACK))
+ {
+
+ /* Stack is not big enough, return appropriate error code. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check the priority specified. */
+ else if (priority >= ((UINT) TX_MAX_PRIORITIES))
+ {
+
+ /* Invalid priority selected, return appropriate error code. */
+ status = TX_PRIORITY_ERROR;
+ }
+
+ /* Check preemption threshold. */
+ else if (preempt_threshold > priority)
+ {
+
+ /* Invalid preempt threshold, return appropriate error code. */
+ status = TX_THRESH_ERROR;
+ }
+
+ /* Check the start selection. */
+ else if (auto_start > TX_AUTO_START)
+ {
+
+ /* Invalid auto start selection, return appropriate error code. */
+ status = TX_START_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual thread create function. */
+ status = _tx_thread_create(thread_ptr, name_ptr, entry_function, entry_input,
+ stack_start, stack_size, priority, preempt_threshold,
+ time_slice, auto_start);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_delete.c b/common/src/txe_thread_delete.c
new file mode 100644
index 00000000..f85209be
--- /dev/null
+++ b/common/src/txe_thread_delete.c
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread delete function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_delete Actual thread delete function */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_delete(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+
+
+ /* Check for invalid caller of this function. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Check for an invalid thread pointer. */
+ else if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread delete function. */
+ status = _tx_thread_delete(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_entry_exit_notify.c b/common/src/txe_thread_entry_exit_notify.c
new file mode 100644
index 00000000..1f71e3ff
--- /dev/null
+++ b/common/src/txe_thread_entry_exit_notify.c
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_entry_exit_notify PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread entry/exit notify */
+/* callback function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* thread_entry_exit_notify Pointer to notify callback */
+/* function, TX_NULL to disable*/
+/* */
+/* OUTPUT */
+/* */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_entry_exit_notify Actual entry/exit notify */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type))
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread entry/exit notify function. */
+ status = _tx_thread_entry_exit_notify(thread_ptr, thread_entry_exit_notify);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_info_get.c b/common/src/txe_thread_info_get.c
new file mode 100644
index 00000000..24365329
--- /dev/null
+++ b/common/src/txe_thread_info_get.c
@@ -0,0 +1,117 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control block */
+/* name Destination for the thread name */
+/* state Destination for thread state */
+/* run_count Destination for thread run count */
+/* priority Destination for thread priority */
+/* preemption_threshold Destination for thread preemption-*/
+/* threshold */
+/* time_slice Destination for thread time-slice */
+/* next_thread Destination for next created */
+/* thread */
+/* next_suspended_thread Destination for next suspended */
+/* thread */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_info_get Actual thread information get */
+/* service */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
+ UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
+ TX_THREAD **next_thread, TX_THREAD **next_suspended_thread)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call the actual thread information get service. */
+ status = _tx_thread_info_get(thread_ptr, name, state, run_count, priority, preemption_threshold,
+ time_slice, next_thread, next_suspended_thread);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_preemption_change.c b/common/src/txe_thread_preemption_change.c
new file mode 100644
index 00000000..d3cc4fd3
--- /dev/null
+++ b/common/src/txe_thread_preemption_change.c
@@ -0,0 +1,130 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_preemption_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the preemption threshold change */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* new_threshold New preemption threshold */
+/* old_threshold Old preemption threshold */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_PTR_ERROR Invalid old threshold pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_preemption_change Actual preempt change function*/
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for a valid old threshold pointer. */
+ else if (old_threshold == TX_NULL)
+ {
+
+ /* Invalid destination pointer, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if the preemption-threshold is valid. */
+ else if (new_threshold > thread_ptr -> tx_thread_user_priority)
+ {
+
+ /* Return an error status. */
+ status = TX_THRESH_ERROR;
+ }
+ else
+ {
+
+ /* Call actual change thread preemption function. */
+ status = _tx_thread_preemption_change(thread_ptr, new_threshold, old_threshold);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_priority_change.c b/common/src/txe_thread_priority_change.c
new file mode 100644
index 00000000..f4160d13
--- /dev/null
+++ b/common/src/txe_thread_priority_change.c
@@ -0,0 +1,131 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_priority_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the change priority function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* new_priority New thread priority */
+/* old_priority Old thread priority */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_PTR_ERROR Invalid old priority pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_priority_change Actual priority change */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT *old_priority)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for a valid old priority pointer. */
+ else if (old_priority == TX_NULL)
+ {
+
+ /* Invalid destination pointer, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Determine if the priority is legal. */
+ else if (new_priority >= ((UINT) TX_MAX_PRIORITIES))
+ {
+
+ /* Return an error status. */
+ status = TX_PRIORITY_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual change thread priority function. */
+ status = _tx_thread_priority_change(thread_ptr, new_priority, old_priority);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_relinquish.c b/common/src/txe_thread_relinquish.c
new file mode 100644
index 00000000..6f7733c4
--- /dev/null
+++ b/common/src/txe_thread_relinquish.c
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_relinquish PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks to make sure a thread is executing before the */
+/* relinquish is executed. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_relinquish Actual thread relinquish call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _txe_thread_relinquish(VOID)
+{
+
+TX_THREAD *current_thread;
+
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Make sure a thread is executing. */
+ if (current_thread != TX_NULL)
+ {
+
+ /* Now make sure the call is not from an ISR or Initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
+ {
+
+ /* Okay to call the real relinquish function. */
+ _tx_thread_relinquish();
+ }
+ }
+}
+
diff --git a/common/src/txe_thread_reset.c b/common/src/txe_thread_reset.c
new file mode 100644
index 00000000..bef5fa8c
--- /dev/null
+++ b/common/src/txe_thread_reset.c
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_thread_reset PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread reset function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to reset */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Service return status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_reset Actual thread reset function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_reset(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *current_thread;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for an invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(current_thread)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (current_thread == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt or initialization call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual thread reset function. */
+ status = _tx_thread_reset(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_resume.c b/common/src/txe_thread_resume.c
new file mode 100644
index 00000000..04255304
--- /dev/null
+++ b/common/src/txe_thread_resume.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_resume PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the resume thread function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to resume */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_resume Actual thread resume function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_resume(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread resume function. */
+ status = _tx_thread_resume(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_suspend.c b/common/src/txe_thread_suspend.c
new file mode 100644
index 00000000..eb8e24c3
--- /dev/null
+++ b/common/src/txe_thread_suspend.c
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_suspend PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread suspend function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_suspend Actual thread suspension */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_suspend(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread suspend function. */
+ status = _tx_thread_suspend(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_terminate.c b/common/src/txe_thread_terminate.c
new file mode 100644
index 00000000..5531a378
--- /dev/null
+++ b/common/src/txe_thread_terminate.c
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_terminate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread terminate function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread to suspend */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_terminate Actual thread terminate */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_terminate(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread terminate function. */
+ status = _tx_thread_terminate(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_time_slice_change.c b/common/src/txe_thread_time_slice_change.c
new file mode 100644
index 00000000..e024dd13
--- /dev/null
+++ b/common/src/txe_thread_time_slice_change.c
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_time_slice_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the time slice change function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* new_time_slice New time slice */
+/* old_time_slice Old time slice */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_time_slice_change Actual time-slice change */
+/* function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for a valid old time-slice pointer. */
+ else if (old_time_slice == TX_NULL)
+ {
+
+ /* Invalid destination pointer, return appropriate error code. */
+ status = TX_PTR_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual change time slice function. */
+ status = _tx_thread_time_slice_change(thread_ptr, new_time_slice, old_time_slice);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_thread_wait_abort.c b/common/src/txe_thread_wait_abort.c
new file mode 100644
index 00000000..831b3f84
--- /dev/null
+++ b/common/src/txe_thread_wait_abort.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* _txe_thread_wait_abort PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the thread wait abort function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread to abort the wait on */
+/* */
+/* OUTPUT */
+/* */
+/* status Return completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_wait_abort Actual wait abort function */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_wait_abort(TX_THREAD *thread_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Call actual thread wait abort function. */
+ status = _tx_thread_wait_abort(thread_ptr);
+ }
+
+ /* Return status to the caller. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_activate.c b/common/src/txe_timer_activate.c
new file mode 100644
index 00000000..5938a428
--- /dev/null
+++ b/common/src/txe_timer_activate.c
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_activate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the activate application timer */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid application timer */
+/* TX_ACTIVATE_ERROR Application timer already active */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_activate Actual application timer activate */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_activate(TX_TIMER *timer_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid timer ID. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual application timer activate function. */
+ status = _tx_timer_activate(timer_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_change.c b/common/src/txe_timer_change.c
new file mode 100644
index 00000000..7be337f9
--- /dev/null
+++ b/common/src/txe_timer_change.c
@@ -0,0 +1,124 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_change PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the application timer change */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* initial_ticks Initial expiration ticks */
+/* reschedule_ticks Reschedule ticks */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid application timer pointer */
+/* TX_TICK_ERROR Invalid initial tick value of 0 */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_change Actual timer change function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks)
+{
+
+UINT status;
+
+
+ /* Check for an invalid timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid timer ID. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Check for an illegal initial tick value. */
+ else if (initial_ticks == ((ULONG) 0))
+ {
+
+ /* Invalid initial tick value, return appropriate error code. */
+ status = TX_TICK_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+ else if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual application timer function. */
+ status = _tx_timer_change(timer_ptr, initial_ticks, reschedule_ticks);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_create.c b/common/src/txe_timer_create.c
new file mode 100644
index 00000000..6397a801
--- /dev/null
+++ b/common/src/txe_timer_create.c
@@ -0,0 +1,237 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_create PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the create application timer */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* name_ptr Pointer to timer name */
+/* expiration_function Application expiration function */
+/* initial_ticks Initial expiration ticks */
+/* reschedule_ticks Reschedule ticks */
+/* auto_activate Automatic activation flag */
+/* timer_control_block_size Size of timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid timer control block */
+/* TX_TICK_ERROR Invalid initial expiration count */
+/* TX_ACTIVATE_ERROR Invalid timer activation option */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_timer_create Actual timer create function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
+ VOID (*expiration_function)(ULONG id), ULONG expiration_input,
+ ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT status;
+ULONG i;
+TX_TIMER *next_timer;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for a NULL timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid control block size. */
+ else if (timer_control_block_size != (sizeof(TX_TIMER)))
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+ else
+ {
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment the preempt disable flag. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Next see if it is already in the created list. */
+ next_timer = _tx_timer_created_ptr;
+ for (i = ((ULONG) 0); i < _tx_timer_created_count; i++)
+ {
+
+ /* Determine if this timer matches the current timer in the list. */
+ if (timer_ptr == next_timer)
+ {
+
+ break;
+ }
+ else
+ {
+
+ /* Move to next timer. */
+ next_timer = next_timer -> tx_timer_created_next;
+ }
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Decrement the preempt disable flag. */
+ _tx_thread_preempt_disable--;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* At this point, check to see if there is a duplicate timer. */
+ if (timer_ptr == next_timer)
+ {
+
+ /* Timer is already created, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Check for an illegal initial tick value. */
+ else if (initial_ticks == ((ULONG) 0))
+ {
+
+ /* Invalid initial tick value, return appropriate error code. */
+ status = TX_TICK_ERROR;
+ }
+ else
+ {
+
+ /* Check for an illegal activation. */
+ if (auto_activate != TX_AUTO_ACTIVATE)
+ {
+
+ /* And activation is not the other value. */
+ if (auto_activate != TX_NO_ACTIVATE)
+ {
+
+ /* Invalid activation selected, return appropriate error code. */
+ status = TX_ACTIVATE_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Check for invalid caller of this function. First check for a calling thread. */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+#endif
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+ }
+
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual application timer create function. */
+ status = _tx_timer_create(timer_ptr, name_ptr, expiration_function, expiration_input,
+ initial_ticks, reschedule_ticks, auto_activate);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_deactivate.c b/common/src/txe_timer_deactivate.c
new file mode 100644
index 00000000..5c1e620b
--- /dev/null
+++ b/common/src/txe_timer_deactivate.c
@@ -0,0 +1,102 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_deactivate PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the deactivate application timer */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid application timer pointer */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_deactivate Actual timer deactivation function*/
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_deactivate(TX_TIMER *timer_ptr)
+{
+
+UINT status;
+
+
+ /* Check for an invalid timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid timer ID. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+ else
+ {
+
+ /* Call actual application timer deactivate function. */
+ status = _tx_timer_deactivate(timer_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_delete.c b/common/src/txe_timer_delete.c
new file mode 100644
index 00000000..21debdf1
--- /dev/null
+++ b/common/src/txe_timer_delete.c
@@ -0,0 +1,143 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_delete PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the delete application timer */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid application timer pointer */
+/* TX_CALLER_ERROR Invalid caller of this function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_delete Actual timer delete function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_delete(TX_TIMER *timer_ptr)
+{
+
+UINT status;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD *thread_ptr;
+#endif
+
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+#endif
+
+ /* Check for an invalid timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid timer ID. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Check for invalid caller of this function. */
+
+ /* Is the caller an ISR or Initialization? */
+ else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+ /* Pickup thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr)
+
+ /* Is the caller the system timer thread? */
+ if (thread_ptr == &_tx_timer_thread)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+#endif
+
+ /* Call actual application timer delete function. */
+ status = _tx_timer_delete(timer_ptr);
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+ }
+#endif
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/common/src/txe_timer_info_get.c b/common/src/txe_timer_info_get.c
new file mode 100644
index 00000000..66d311c1
--- /dev/null
+++ b/common/src/txe_timer_info_get.c
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_timer_info_get PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the timer information get */
+/* service. */
+/* */
+/* INPUT */
+/* */
+/* timer_ptr Pointer to timer control block */
+/* name Destination for the timer name */
+/* active Destination for active flag */
+/* remaining_ticks Destination for remaining ticks */
+/* before expiration */
+/* reschedule_ticks Destination for reschedule ticks */
+/* next_timer Destination for next timer on the */
+/* created list */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TIMER_ERROR Invalid timer pointer */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_info_get Actual info get call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
+ ULONG *reschedule_ticks, TX_TIMER **next_timer)
+{
+
+UINT status;
+
+
+ /* Check for an invalid timer pointer. */
+ if (timer_ptr == TX_NULL)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+
+ /* Now check for invalid timer ID. */
+ else if (timer_ptr -> tx_timer_id != TX_TIMER_ID)
+ {
+
+ /* Timer pointer is invalid, return appropriate error code. */
+ status = TX_TIMER_ERROR;
+ }
+ else
+ {
+
+ /* Otherwise, call the actual timer information get service. */
+ status = _tx_timer_info_get(timer_ptr, name, active, remaining_ticks, reschedule_ticks, next_timer);
+ }
+
+ /* Return completion status. */
+ return(status);
+}
+
diff --git a/docs/ThreadX_User_Guide.pdf b/docs/ThreadX_User_Guide.pdf
new file mode 100755
index 00000000..90160770
--- /dev/null
+++ b/docs/ThreadX_User_Guide.pdf
Binary files differ
diff --git a/ports/cortex_m0/gnu/CMakeLists.txt b/ports/cortex_m0/gnu/CMakeLists.txt
new file mode 100644
index 00000000..0e3cc8ec
--- /dev/null
+++ b/ports/cortex_m0/gnu/CMakeLists.txt
@@ -0,0 +1,21 @@
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/ports/cortex_m0/gnu/inc/tx_port.h b/ports/cortex_m0/gnu/inc/tx_port.h
new file mode 100644
index 00000000..2f798966
--- /dev/null
+++ b/ports/cortex_m0/gnu/inc/tx_port.h
@@ -0,0 +1,371 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h Cortex-M0/GNU */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the TX_MEMSET macro to remove library reference. */
+
+#define TX_MEMSET(a,b,c) { \
+ UCHAR *ptr; \
+ UCHAR value; \
+ UINT i, size; \
+ ptr = (UCHAR *) ((VOID *) a); \
+ value = (UCHAR) b; \
+ size = (UINT) c; \
+ for (i = 0; i < size; i++) \
+ { \
+ *ptr++ = value; \
+ } \
+ }
+
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX Cortex-M0 port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+
+/* Define the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+
+unsigned int ipsr_value;
+
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+#else
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define GNU specific macros, with in-line assembly for performance. */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ __asm__ volatile (" CPSID i" : : : "memory" );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
+{
+
+ __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
+}
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+
+ __asm__ volatile (" CPSIE i": : : "memory" );
+}
+
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_primask_value();
+ __enable_interrupts();
+ __restore_interrupts(interrupt_save);
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+#endif
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M0/GNU Version 6.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S b/ports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S
new file mode 100755
index 00000000..9698d64c
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S
@@ -0,0 +1,185 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Initialize */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_initialize.h"
+@#include "tx_thread.h"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+ .global __RAM_segment_used_end__
+ .global _tx_thread_context_save
+ .global _tx_thread_context_restore
+ .global _tx_timer_interrupt
+ .global _vectors
+@
+@
+SYSTEM_CLOCK = 8000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_initialize_low_level Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for any low-level processor */
+@/* initialization, including setting up interrupt vectors, setting */
+@/* up a periodic timer interrupt source, saving the system stack */
+@/* pointer for use in ISR processing later, and finding the first */
+@/* available RAM memory address for tx_application_define. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_initialize_low_level(VOID)
+@{
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+@
+@ /* Disable interrupts during ThreadX initialization. */
+@
+ CPSID i
+@
+@ /* Set base of available memory to end of non-initialised RAM area. */
+@
+ LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ @ Build first free address
+ ADDS r1, r1, #4 @
+ STR r1, [r0] @ Setup first unused memory pointer
+@
+@ /* Enable the cycle count register. */
+@
+ LDR r0, =0xE0001000 @ Build address of DWT register
+ LDR r1, [r0] @ Pickup the current value
+ MOVS r2, #1
+ ORRS r1, r1, r2 @ Set the CYCCNTENA bit
+ STR r1, [r0] @ Enable the cycle count register
+@
+@ /* Setup Vector Table Offset Register. */
+@
+ LDR r0, =0xE000E000 @ Build address of NVIC registers
+ LDR r2, =0xD08 @ Offset to vector base register
+ ADD r0, r0, r2 @ Build vector base register
+ LDR r1, =_vectors @ Pickup address of vector table
+ STR r1, [r0] @ Set vector table address
+@
+@ /* Set system stack pointer from vector value. */
+@
+ LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
+ LDR r1, =_vectors @ Pickup address of vector table
+ LDR r1, [r1] @ Pickup reset stack pointer
+ STR r1, [r0] @ Save system stack pointer
+@
+@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
+@
+ LDR r0, =0xE000E000 @ Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] @ Setup SysTick Reload Value
+ LDR r1, =0x7 @ Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] @ Setup SysTick Control
+@
+@ /* Configure handler priorities. */
+@
+ LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
+ LDR r0, =0xE000E000 @ Build address of NVIC registers
+ LDR r2, =0xD18 @
+ ADD r0, r0, r2 @
+ STR r1, [r0] @ Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
+ LDR r0, =0xE000E000 @ Build address of NVIC registers
+ LDR r2, =0xD1C @
+ ADD r0, r0, r2 @
+ STR r1, [r0] @ Setup System Handlers 8-11 Priority Registers
+ @ Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
+ LDR r0, =0xE000E000 @ Build address of NVIC registers
+ LDR r2, =0xD20 @
+ ADD r0, r0, r2 @
+ STR r1, [r0] @ Setup System Handlers 12-15 Priority Registers
+ @ Note: PnSV must be lowest priority, which is 0xFF
+
+@
+@ /* Return to caller. */
+@
+ BX lr
+@}
+@
+@ /* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+@ VOID SysTick_Handler (VOID)
+@ {
+@
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter @ Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit @ Call the ISR exit function
+#endif
+ POP {r0, r1}
+ MOV lr, r1
+ BX lr
+@ }
diff --git a/ports/cortex_m0/gnu/src/tx_thread_context_restore.S b/ports/cortex_m0/gnu/src/tx_thread_context_restore.S
new file mode 100755
index 00000000..5581cdaf
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,96 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_thread_system_stack_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_schedule
+ .global _tx_thread_preempt_disable
+ .global _tx_execution_isr_exit
+@
+@
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_restore Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function restores the interrupt context if it is processing a */
+@/* nested interrupt. If not, it returns to the interrupt thread if no */
+@/* preemption is necessary. Otherwise, if preemption is necessary or */
+@/* if no thread was running, the function returns to the scheduler. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling routine */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs Interrupt Service Routines */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_restore(VOID)
+@{
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_context_save.S b/ports/cortex_m0/gnu/src/tx_thread_context_save.S
new file mode 100755
index 00000000..1d48d8fd
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,90 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_execution_isr_enter
+@
+@
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_save Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function saves the context of an executing thread in the */
+@/* beginning of interrupt processing. The function also ensures that */
+@/* the system stack is used upon return to the calling ISR. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_save(VOID)
+@{
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m0/gnu/src/tx_thread_interrupt_control.S
new file mode 100755
index 00000000..f609c227
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,94 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_control Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for changing the interrupt lockout */
+@/* posture of the system. */
+@/* */
+@/* INPUT */
+@/* */
+@/* new_posture New interrupt lockout posture */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* UINT _tx_thread_interrupt_control(UINT new_posture)
+{ */
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+
+@/* Pickup current interrupt lockout posture. */
+
+ MRS r1, PRIMASK @ Pickup current interrupt lockout
+
+
+@/* Apply the new interrupt posture. */
+
+ MSR PRIMASK, r0 @ Apply the new interrupt lockout
+ MOV r0, r1 @ Transfer old to return register
+ BX lr @ Return to caller
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S
new file mode 100755
index 00000000..7cea30dc
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,88 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_disable Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for disabling interrupts. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* UINT _tx_thread_interrupt_disable(VOID)
+{ */
+ .global _tx_thread_interrupt_disable
+ .thumb_func
+_tx_thread_interrupt_disable:
+
+@/* Pickup current interrupt lockout posture. */
+
+ MRS r0, PRIMASK
+ CPSID i
+ BX lr
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S
new file mode 100755
index 00000000..70d6b2eb
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,86 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_restore Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for restoring the interrupt lockout */
+@/* posture of the system. */
+@/* */
+@/* INPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* VOID _tx_thread_interrupt_restore(UINT old_posture)
+{ */
+ .global _tx_thread_interrupt_restore
+ .thumb_func
+_tx_thread_interrupt_restore:
+
+ MSR PRIMASK, r0
+ BX lr
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_schedule.S b/ports/cortex_m0/gnu/src/tx_thread_schedule.S
new file mode 100755
index 00000000..61f3b113
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,278 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_system_stack_ptr
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_schedule Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function waits for a thread control block pointer to appear in */
+@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+@/* in the variable, the corresponding thread is resumed. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* _tx_thread_system_return Return to system from thread */
+@/* _tx_thread_context_restore Restore thread's context */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_schedule(VOID)
+@{
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+@
+@ /* This function should only ever be called on Cortex-M0
+@ from the first schedule request. Subsequent scheduling occurs
+@ from the PendSV handling routines below. */
+@
+@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+@
+ MOVS r0, #0 @ Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ STR r0, [r2, #0] @ Clear preempt disable flag
+@
+@ /* Enable interrupts */
+@
+ CPSIE i
+@
+@ /* Enter the scheduler for the first time. */
+@
+ LDR r0, =#0x10000000 @ Load PENDSVSET bit
+ LDR r1, =#0xE000ED04 @ Load NVIC base
+ STR r0, [r1] @ Set PENDSVBIT in ICSR
+ DSB @ Complete all memory accesses
+ ISB @ Flush pipeline
+@
+@ /* Wait here for the PendSV to take place. */
+@
+__tx_wait_here:
+ B __tx_wait_here @ Wait for the PendSV to happen
+@}
+@
+@ /* Generic context switch-out switch-in handler... Note that this handler is
+@ common for both PendSV and SVCall. */
+@
+ .global PendSV_Handler
+.thumb_func
+.thumb_func
+PendSV_Handler:
+ .global __tx_PendSVHandler
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_PendSVHandler:
+ .thumb_func
+__tx_SVCallHandler:
+@
+@ /* Get current thread value and new thread pointer. */
+@
+ .thumb_func
+__tx_ts_handler:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread exit function to indicate the thread is no longer executing. */
+@
+ CPSID i @ Disable interrupts
+ PUSH {r0, lr} @ Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit @ Call the thread exit function
+ POP {r0, r1} @ Recover LR
+ MOV lr, r1 @
+ CPSIE i @ Enable interrupts
+#endif
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ MOVS r3, #0 @ Build NULL value
+ LDR r1, [r0] @ Pickup current thread pointer
+@
+@ /* Determine if there is a current thread to finish preserving. */
+@
+ CMP r1,#0 @ If NULL, skip preservation
+ BEQ __tx_ts_new @
+@
+@ /* Recover PSP and preserve current thread context. */
+@
+ STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
+ MRS r3, PSP @ Pickup PSP pointer (thread's stack pointer)
+ SUBS r3, r3, #16 @ Allocate stack space
+ STM r3!, {r4-r7} @ Save its remaining registers (M3 Instruction: STMDB r12!, {r4-r11})
+ MOV r4,r8 @
+ MOV r5,r9 @
+ MOV r6,r10 @
+ MOV r7,r11 @
+ SUBS r3, r3, #32 @ Allocate stack space
+ STM r3!,{r4-r7} @
+ SUBS r3, r3, #20 @ Allocate stack space
+ MOV r5, lr @ Move LR into R4
+ STR r5, [r3] @ Save LR
+ STR r3, [r1, #8] @ Save its stack pointer
+@
+@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+@
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ LDR r5, [r4] @ Pickup current time-slice
+ CMP r5, #0 @ If not active, skip processing
+ BEQ __tx_ts_new @
+@
+@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+@
+ STR r5, [r1, #24] @ Save current time-slice
+@
+@ /* Clear the global time-slice. */
+@
+ MOVS r5, #0 @ Build clear value
+ STR r5, [r4] @ Clear time-slice
+@
+@ /* Executing thread is now completely preserved!!! */
+@
+__tx_ts_new:
+@
+@ /* Now we are looking for a new thread to execute! */
+@
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Is there another thread ready to execute?
+ CMP r1, #0 @
+ BEQ __tx_ts_wait @ No, skip to the wait processing
+@
+@ /* Yes, another thread is ready for else, make the current thread the new thread. */
+@
+ STR r1, [r0] @ Setup the current thread pointer to the new thread
+ CPSIE i @ Enable interrupts
+@
+@ /* Increment the thread run count. */
+@
+__tx_ts_restore:
+ LDR r7, [r1, #4] @ Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ LDR r5, [r1, #24] @ Pickup thread's current time-slice
+ ADDS r7, r7, #1 @ Increment the thread run count
+ STR r7, [r1, #4] @ Store the new run count
+@
+@ /* Setup global time-slice with thread's current time-slice. */
+@
+ STR r5, [r4] @ Setup global time-slice
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread entry function to indicate the thread is executing. */
+@
+ PUSH {r0, r1} @ Save r0/r1
+ BL _tx_execution_thread_enter @ Call the thread execution enter function
+ POP {r0, r1} @ Recover r3
+#endif
+@
+@ /* Restore the thread context and PSP. */
+@
+ LDR r3, [r1, #8] @ Pickup thread's stack pointer
+ LDR r5, [r3] @ Recover saved LR
+ ADDS r3, r3, #4 @ Position past LR
+ MOV lr, r5 @ Restore LR
+ LDM r3!,{r4-r7} @ Recover thread's registers (r4-r11)
+ MOV r11,r7 @
+ MOV r10,r6 @
+ MOV r9,r5 @
+ MOV r8,r4 @
+ LDM r3!,{r4-r7} @
+ MSR PSP, r3 @ Setup the thread's stack pointer
+@
+@ /* Return to thread. */
+@
+ BX lr @ Return to thread!
+@
+@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+@ are disabled to allow use of WFI for waiting for a thread to arrive. */
+@
+__tx_ts_wait:
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Pickup the next thread to execute pointer
+ STR r1, [r0] @ Store it in the current pointer
+ CMP r1, #0 @ If non-NULL, a new thread is ready!
+ BNE __tx_ts_ready @
+#ifdef TX_ENABLE_WFI
+ DSB @ Ensure no outstanding memory transactions
+ WFI @ Wait for interrupt
+ ISB @ Ensure pipeline is flushed
+#endif
+ CPSIE i @ Enable interrupts
+ B __tx_ts_wait @ Loop to continue waiting
+@
+@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+@ already in the handler! */
+@
+__tx_ts_ready:
+ LDR r7, =0x08000000 @ Build clear PendSV value
+ LDR r5, =0xE000ED04 @ Build base NVIC address
+ STR r7, [r5] @ Clear any PendSV
+@
+@ /* Re-enable interrupts and restore new thread. */
+@
+ CPSIE i @ Enable interrupts
+ B __tx_ts_restore @ Restore the thread
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_stack_build.S b/ports/cortex_m0/gnu/src/tx_thread_stack_build.S
new file mode 100755
index 00000000..ca66e1d5
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,149 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_stack_build Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function builds a stack frame on the supplied thread's stack. */
+@/* The stack frame results in a fake interrupt return to the supplied */
+@/* function pointer. */
+@/* */
+@/* INPUT */
+@/* */
+@/* thread_ptr Pointer to thread control blk */
+@/* function_ptr Pointer to return function */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_thread_create Create thread service */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+@{
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+@
+@
+@ /* Build a fake interrupt frame. The form of the fake interrupt stack
+@ on the Cortex-M0 should look like the following after it is built:
+@
+@ Stack Top:
+@ LR Interrupted LR (LR at time of PENDSV)
+@ r4 Initial value for r4
+@ r5 Initial value for r5
+@ r6 Initial value for r6
+@ r7 Initial value for r7
+@ r8 Initial value for r8
+@ r9 Initial value for r9
+@ r10 (sl) Initial value for r10 (sl)
+@ r11 Initial value for r11
+@ r0 Initial value for r0 (Hardware stack starts here!!)
+@ r1 Initial value for r1
+@ r2 Initial value for r2
+@ r3 Initial value for r3
+@ r12 Initial value for r12
+@ lr Initial value for lr
+@ pc Initial value for pc
+@ xPSR Initial value for xPSR
+@
+@ Stack Bottom: (higher memory address) */
+@
+ LDR r2, [r0, #16] @ Pickup end of stack area
+ MOVS r3, #0x7 @
+ BICS r2, r2, r3 @ Align frame for 8-byte alignment
+ SUBS r2, r2, #68 @ Subtract frame size
+ LDR r3, =0xFFFFFFFD @ Build initial LR value
+ STR r3, [r2, #0] @ Save on the stack
+@
+@ /* Actually build the stack frame. */
+@
+ MOVS r3, #0 @ Build initial register value
+ STR r3, [r2, #4] @ Store initial r4
+ STR r3, [r2, #8] @ Store initial r5
+ STR r3, [r2, #12] @ Store initial r6
+ STR r3, [r2, #16] @ Store initial r7
+ STR r3, [r2, #20] @ Store initial r8
+ STR r3, [r2, #24] @ Store initial r9
+ LDR r3, [r0, #12] @ Pickup stack starting address
+ STR r3, [r2, #28] @ Store initial r10 (sl)
+ MOVS r3, #0 @ Build initial register value
+ STR r3, [r2, #32] @ Store initial r11
+@
+@ /* Hardware stack follows. */
+@
+ STR r3, [r2, #36] @ Store initial r0
+ STR r3, [r2, #40] @ Store initial r1
+ STR r3, [r2, #44] @ Store initial r2
+ STR r3, [r2, #48] @ Store initial r3
+ STR r3, [r2, #52] @ Store initial r12
+ LDR r3, =0xFFFFFFFF @ Poison EXC_RETURN value
+ STR r3, [r2, #56] @ Store initial lr
+ STR r1, [r2, #60] @ Store initial pc
+ LDR r3, =0x01000000 @ Only T-bit need be set
+ STR r3, [r2, #64] @ Store initial xPSR
+@
+@ /* Setup stack pointer. */
+@ thread_ptr -> tx_thread_stack_ptr = r2;
+@
+ STR r2, [r0, #8] @ Save stack pointer in thread's
+ @ control block
+ BX lr @ Return to caller
+@}
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_thread_system_return.S b/ports/cortex_m0/gnu/src/tx_thread_system_return.S
new file mode 100755
index 00000000..6de1b19b
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_thread_system_return.S
@@ -0,0 +1,97 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@ #include "tx_timer.h" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_system_return Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is target processor specific. It is used to transfer */
+@/* control from a thread back to the ThreadX system. Only a */
+@/* minimal context is saved since the compiler assumes temp registers */
+@/* are going to get slicked by a function call anyway. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling loop */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ThreadX components */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* VOID _tx_thread_system_return(VOID)
+@{ */
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+@
+@ /* Return to real scheduler via PendSV. Note that this routine is often
+@ replaced with in-line assembly in tx_port.h to improved performance. */
+@
+ LDR r0, =0x10000000 @ Load PENDSVSET bit
+ LDR r1, =0xE000ED04 @ Load NVIC base
+ STR r0, [r1] @ Set PENDSVBIT in ICSR
+ MRS r0, IPSR @ Pickup IPSR
+ CMP r0, #0 @ Is it a thread returning?
+ BNE _isr_context @ If ISR, skip interrupt enable
+ MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
+ CPSIE i @ Enable interrupts
+ MSR PRIMASK, r1 @ Restore original interrupt posture
+_isr_context:
+ BX lr @ Return to caller
+@/* } */
+
diff --git a/ports/cortex_m0/gnu/src/tx_timer_interrupt.S b/ports/cortex_m0/gnu/src/tx_timer_interrupt.S
new file mode 100755
index 00000000..ab85d97d
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,271 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Timer */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_timer.h"
+@#include "tx_thread.h"
+@
+@
+@Define Assembly language external references...
+@
+ .global _tx_timer_time_slice
+ .global _tx_timer_system_clock
+ .global _tx_timer_current_ptr
+ .global _tx_timer_list_start
+ .global _tx_timer_list_end
+ .global _tx_timer_expired_time_slice
+ .global _tx_timer_expired
+ .global _tx_thread_time_slice
+ .global _tx_timer_expiration_process
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_timer_interrupt Cortex-M0/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function processes the hardware timer interrupt. This */
+@/* processing includes incrementing the system clock and checking for */
+@/* time slice and/or timer expiration. If either is found, the */
+@/* interrupt context save/restore functions are called along with the */
+@/* expiration functions. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_timer_expiration_process Timer expiration processing */
+@/* _tx_thread_time_slice Time slice interrupted thread */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* interrupt vector */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_timer_interrupt(VOID)
+@{
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+@
+@ /* Upon entry to this routine, it is assumed that context save has already
+@ been called, and therefore the compiler scratch registers are available
+@ for use. */
+@
+@ /* Increment the system clock. */
+@ _tx_timer_system_clock++;
+@
+ LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
+ LDR r0, [r1, #0] @ Pickup system clock
+ ADDS r0, r0, #1 @ Increment system clock
+ STR r0, [r1, #0] @ Store new system clock
+@
+@ /* Test for time-slice expiration. */
+@ if (_tx_timer_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
+ LDR r2, [r3, #0] @ Pickup time-slice
+ CMP r2, #0 @ Is it non-active?
+ BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
+@
+@ /* Decrement the time_slice. */
+@ _tx_timer_time_slice--;
+@
+ SUBS r2, r2, #1 @ Decrement the time-slice
+ STR r2, [r3, #0] @ Store new time-slice value
+@
+@ /* Check for expiration. */
+@ if (__tx_timer_time_slice == 0)
+@
+ CMP r2, #0 @ Has it expired?
+ BNE __tx_timer_no_time_slice @ No, skip expiration processing
+@
+@ /* Set the time-slice expired flag. */
+@ _tx_timer_expired_time_slice = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
+ MOVS r0, #1 @ Build expired value
+ STR r0, [r3, #0] @ Set time-slice expiration flag
+@
+@ }
+@
+__tx_timer_no_time_slice:
+@
+@ /* Test for timer expiration. */
+@ if (*_tx_timer_current_ptr)
+@ {
+@
+ LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
+ LDR r0, [r1, #0] @ Pickup current timer
+ LDR r2, [r0, #0] @ Pickup timer list entry
+ CMP r2, #0 @ Is there anything in the list?
+ BEQ __tx_timer_no_timer @ No, just increment the timer
+@
+@ /* Set expiration flag. */
+@ _tx_timer_expired = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired @ Pickup expiration flag address
+ MOVS r2, #1 @ Build expired value
+ STR r2, [r3, #0] @ Set expired flag
+ B __tx_timer_done @ Finished timer processing
+@
+@ }
+@ else
+@ {
+__tx_timer_no_timer:
+@
+@ /* No timer expired, increment the timer pointer. */
+@ _tx_timer_current_ptr++;
+@
+ ADDS r0, r0, #4 @ Move to next timer
+@
+@ /* Check for wrap-around. */
+@ if (_tx_timer_current_ptr == _tx_timer_list_end)
+@
+ LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
+ LDR r2, [r3, #0] @ Pickup list end
+ CMP r0, r2 @ Are we at list end?
+ BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
+@
+@ /* Wrap to beginning of list. */
+@ _tx_timer_current_ptr = _tx_timer_list_start;
+@
+ LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
+ LDR r0, [r3, #0] @ Set current pointer to list start
+@
+__tx_timer_skip_wrap:
+@
+ STR r0, [r1, #0] @ Store new current timer pointer
+@ }
+@
+__tx_timer_done:
+@
+@
+@ /* See if anything has expired. */
+@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
+ LDR r2, [r3, #0] @ Pickup time-slice expired flag
+ CMP r2, #0 @ Did a time-slice expire?
+ BNE __tx_something_expired @ If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Did a timer expire?
+ BEQ __tx_timer_nothing_expired @ No, nothing expired
+@
+__tx_something_expired:
+@
+@
+ PUSH {r0, lr} @ Save the lr register on the stack
+ @ and save r0 just to keep 8-byte alignment
+@
+@ /* Did a timer expire? */
+@ if (_tx_timer_expired)
+@ {
+@
+ LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Check for timer expiration
+ BEQ __tx_timer_dont_activate @ If not set, skip timer activation
+@
+@ /* Process timer expiration. */
+@ _tx_timer_expiration_process()@
+@
+ BL _tx_timer_expiration_process @ Call the timer expiration handling routine
+@
+@ }
+__tx_timer_dont_activate:
+@
+@ /* Did time slice expire? */
+@ if (_tx_timer_expired_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
+ LDR r2, [r3, #0] @ Pickup the actual flag
+ CMP r2, #0 @ See if the flag is set
+ BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
+@
+@ /* Time slice interrupted thread. */
+@ _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice @ Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ LDR r1, [r0] @ Is the preempt disable flag set?
+ CMP r1, #0 @
+ BNE __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r1, [r0] @ Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ LDR r3, [r2] @ Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 @ Build address of control register
+ LDR r2, =0x10000000 @ Build value for PendSV bit
+ CMP r1, r3 @ Are they the same?
+ BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
+ STR r2, [r0] @ Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+@
+@ }
+@
+__tx_timer_not_ts_expiration:
+@
+ POP {r0, r1} @ Recover lr register (r0 is just there for
+ MOV lr, r1 @ the 8-byte stack alignment
+@
+@ }
+@
+__tx_timer_nothing_expired:
+
+ DSB @ Complete all memory access
+ BX lr @ Return to caller
+@
+@}
+
+
diff --git a/ports/cortex_m0/gnu/src/tx_vector_table_sample.S b/ports/cortex_m0/gnu/src/tx_vector_table_sample.S
new file mode 100644
index 00000000..55395cd1
--- /dev/null
+++ b/ports/cortex_m0/gnu/src/tx_vector_table_sample.S
@@ -0,0 +1,102 @@
+
+
+ .global reset_handler
+
+ .global __tx_NMIHandler
+ .global __tx_BadHandler
+ .global __tx_SVCallHandler
+ .global __tx_DBGHandler
+ .global __tx_PendSVHandler
+ .global __tx_SysTickHandler
+ .global __tx_BadHandler
+ .global __tx_HardfaultHandler
+
+
+ .syntax unified
+ .section .vectors, "ax"
+ .code 16
+ .align 0
+ .global _vectors
+
+_vectors:
+ .word __stack_end__
+ .word reset_handler
+ .word __tx_NMIHandler
+ .word __tx_HardfaultHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
+ .word __tx_DBGHandler
+ .word 0 // Reserved
+ .word __tx_PendSVHandler
+ .word __tx_SysTickHandler // Used by Threadx timer functionality
+ .word __tx_BadHandler // Populate with user Interrupt handler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+
+
+
+ .section .init, "ax"
+ .thumb_func
+reset_handler:
+
+// low level hardware config, such as PLL setup goes here
+
+ b _start
+
+
+
+ .text 32
+ .align 4
+ .syntax unified
+
+
+__tx_NMIHandler:
+ b __tx_NMIHandler
+
+__tx_BadHandler:
+ b __tx_BadHandler
+
+__tx_DBGHandler:
+ b __tx_DBGHandler
+
+__tx_HardfaultHandler:
+ b __tx_HardfaultHandler
+
diff --git a/ports/cortex_m3/gnu/CMakeLists.txt b/ports/cortex_m3/gnu/CMakeLists.txt
new file mode 100644
index 00000000..cb3091b9
--- /dev/null
+++ b/ports/cortex_m3/gnu/CMakeLists.txt
@@ -0,0 +1,19 @@
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h
new file mode 100644
index 00000000..76f9aea1
--- /dev/null
+++ b/ports/cortex_m3/gnu/inc/tx_port.h
@@ -0,0 +1,357 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h Cortex-M3/GNU */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX Cortex-M7 port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#define TX_INLINE_INITIALIZATION
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+
+/* Define the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+
+unsigned int ipsr_value;
+
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+#else
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+/* This ARM architecture has the CLZ instruction. This is available on
+ architectures v5 and above. If available, redefine the macro for calculating the
+ lowest bit set. */
+
+#ifndef TX_DISABLE_INLINE
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+
+#endif
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define GNU specific macros, with in-line assembly for performance. */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ __asm__ volatile (" CPSID i" : : : "memory" );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
+{
+
+ __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
+}
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+
+ __asm__ volatile (" CPSIE i": : : "memory" );
+}
+
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_primask_value();
+ __enable_interrupts();
+ __restore_interrupts(interrupt_save);
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+#endif
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/GNU Version 6.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
+
+
+
+
diff --git a/ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S b/ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S
new file mode 100644
index 00000000..bfa6e423
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S
@@ -0,0 +1,244 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Initialize */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_initialize.h"
+@#include "tx_thread.h"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+ .global __RAM_segment_used_end__
+ .global _tx_timer_interrupt
+ .global __main
+ .global __tx_SVCallHandler
+ .global __tx_PendSVHandler
+ .global _vectors
+ .global __tx_NMIHandler @ NMI
+ .global __tx_BadHandler @ HardFault
+ .global __tx_SVCallHandler @ SVCall
+ .global __tx_DBGHandler @ Monitor
+ .global __tx_PendSVHandler @ PendSV
+ .global __tx_SysTickHandler @ SysTick
+ .global __tx_IntHandler @ Int 0
+@
+@
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_initialize_low_level Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for any low-level processor */
+@/* initialization, including setting up interrupt vectors, setting */
+@/* up a periodic timer interrupt source, saving the system stack */
+@/* pointer for use in ISR processing later, and finding the first */
+@/* available RAM memory address for tx_application_define. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_initialize_low_level(VOID)
+@{
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+@
+@ /* Disable interrupts during ThreadX initialization. */
+@
+ CPSID i
+@
+@ /* Set base of available memory to end of non-initialised RAM area. */
+@
+ LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ @ Build first free address
+ ADD r1, r1, #4 @
+ STR r1, [r0] @ Setup first unused memory pointer
+@
+@ /* Setup Vector Table Offset Register. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =_vectors @ Pickup address of vector table
+ STR r1, [r0, #0xD08] @ Set vector table address
+@
+@ /* Set system stack pointer from vector value. */
+@
+ LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
+ LDR r1, =_vectors @ Pickup address of vector table
+ LDR r1, [r1] @ Pickup reset stack pointer
+ STR r1, [r0] @ Save system stack pointer
+@
+@ /* Enable the cycle count register. */
+@
+ LDR r0, =0xE0001000 @ Build address of DWT register
+ LDR r1, [r0] @ Pickup the current value
+ ORR r1, r1, #1 @ Set the CYCCNTENA bit
+ STR r1, [r0] @ Enable the cycle count register
+@
+@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] @ Setup SysTick Reload Value
+ MOV r1, #0x7 @ Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] @ Setup SysTick Control
+@
+@ /* Configure handler priorities. */
+@
+ LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
+
+ LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
+ @ Note: SVC must be lowest priority, which is 0xFF
+
+ LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
+ @ Note: PnSV must be lowest priority, which is 0xFF
+
+@
+@ /* Return to caller. */
+@
+ BX lr
+@}
+@
+
+@/* Define shells for each of the unused vectors. */
+@
+ .global __tx_BadHandler
+ .thumb_func
+__tx_BadHandler:
+ B __tx_BadHandler
+
+@ /* added to catch the hardfault */
+
+ .global __tx_HardfaultHandler
+ .thumb_func
+__tx_HardfaultHandler:
+ B __tx_HardfaultHandler
+
+
+@ /* added to catch the SVC */
+
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+
+@ /* Generic interrupt handler template */
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+@ VOID InterruptHandler (VOID)
+@ {
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+
+@ /* Do interrupt handler work here */
+@ /* BL <your C Function>.... */
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+@ /* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+@ VOID TimerInterruptHandler (VOID)
+@ {
+@
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+
+@ /* NMI, DBG handlers */
+ .global __tx_NMIHandler
+ .thumb_func
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .global __tx_DBGHandler
+ .thumb_func
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
+
+
+
+
diff --git a/ports/cortex_m3/gnu/src/tx_thread_context_restore.S b/ports/cortex_m3/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..91937893
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,96 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_thread_system_stack_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_schedule
+ .global _tx_thread_preempt_disable
+ .global _tx_execution_isr_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_restore Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function restores the interrupt context if it is processing a */
+@/* nested interrupt. If not, it returns to the interrupt thread if no */
+@/* preemption is necessary. Otherwise, if preemption is necessary or */
+@/* if no thread was running, the function returns to the scheduler. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling routine */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs Interrupt Service Routines */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_restore(VOID)
+@{
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
+
diff --git a/ports/cortex_m3/gnu/src/tx_thread_context_save.S b/ports/cortex_m3/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..29a7631a
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_execution_isr_enter
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_save Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function saves the context of an executing thread in the */
+@/* beginning of interrupt processing. The function also ensures that */
+@/* the system stack is used upon return to the calling ISR. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_save(VOID)
+@{
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
diff --git a/ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..5890a93d
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,92 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_control Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for changing the interrupt lockout */
+@/* posture of the system. */
+@/* */
+@/* INPUT */
+@/* */
+@/* new_posture New interrupt lockout posture */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* UINT _tx_thread_interrupt_control(UINT new_posture)
+{ */
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+
+@/* Pickup current interrupt lockout posture. */
+
+ MRS r1, PRIMASK @ Pickup current interrupt lockout
+
+@/* Apply the new interrupt posture. */
+
+ MSR PRIMASK, r0 @ Apply the new interrupt lockout
+ MOV r0, r1 @ Transfer old to return register
+ BX lr @ Return to caller
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m3/gnu/src/tx_thread_schedule.S b/ports/cortex_m3/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..6cf8ab54
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,252 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_system_stack_ptr
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_schedule Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function waits for a thread control block pointer to appear in */
+@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+@/* in the variable, the corresponding thread is resumed. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* _tx_thread_system_return Return to system from thread */
+@/* _tx_thread_context_restore Restore thread's context */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_schedule(VOID)
+@{
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+@
+@ /* This function should only ever be called on Cortex-M3
+@ from the first schedule request. Subsequent scheduling occurs
+@ from the PendSV handling routines below. */
+@
+@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+@
+ MOV r0, #0 @ Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ STR r0, [r2, #0] @ Clear preempt disable flag
+@
+@ /* Enable interrupts */
+@
+ CPSIE i
+@
+@ /* Enter the scheduler for the first time. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ DSB @ Complete all memory accesses
+ ISB @ Flush pipeline
+@
+@ /* Wait here for the PendSV to take place. */
+@
+__tx_wait_here:
+ B __tx_wait_here @ Wait for the PendSV to happen
+@}
+@
+@ /* Generic context switch-out switch-in handler... Note that this handler is
+@ common for both PendSV and SVCall. */
+@
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+@
+@ /* Get current thread value and new thread pointer. */
+@
+__tx_ts_handler:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread exit function to indicate the thread is no longer executing. */
+@
+ CPSID i @ Disable interrupts
+ PUSH {r0, lr} @ Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit @ Call the thread exit function
+ POP {r0, lr} @ Recover LR
+ CPSIE i @ Enable interrupts
+#endif
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ MOV r3, #0 @ Build NULL value
+ LDR r1, [r0] @ Pickup current thread pointer
+@
+@ /* Determine if there is a current thread to finish preserving. */
+@
+ CBZ r1, __tx_ts_new @ If NULL, skip preservation
+@
+@ /* Recover PSP and preserve current thread context. */
+@
+ STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP @ Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} @ Save its remaining registers
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ STMDB r12!, {LR} @ Save LR on the stack
+@
+@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+@
+ LDR r5, [r4] @ Pickup current time-slice
+ STR r12, [r1, #8] @ Save the thread stack pointer
+ CBZ r5, __tx_ts_new @ If not active, skip processing
+@
+@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+@
+ STR r5, [r1, #24] @ Save current time-slice
+@
+@ /* Clear the global time-slice. */
+@
+ STR r3, [r4] @ Clear time-slice
+@
+@
+@ /* Executing thread is now completely preserved!!! */
+@
+__tx_ts_new:
+@
+@ /* Now we are looking for a new thread to execute! */
+@
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait @ No, skip to the wait processing
+@
+@ /* Yes, another thread is ready for else, make the current thread the new thread. */
+@
+ STR r1, [r0] @ Setup the current thread pointer to the new thread
+ CPSIE i @ Enable interrupts
+@
+@ /* Increment the thread run count. */
+@
+__tx_ts_restore:
+ LDR r7, [r1, #4] @ Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ LDR r5, [r1, #24] @ Pickup thread's current time-slice
+ ADD r7, r7, #1 @ Increment the thread run count
+ STR r7, [r1, #4] @ Store the new run count
+@
+@ /* Setup global time-slice with thread's current time-slice. */
+@
+ STR r5, [r4] @ Setup global time-slice
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread entry function to indicate the thread is executing. */
+@
+ PUSH {r0, r1} @ Save r0/r1
+ BL _tx_execution_thread_enter @ Call the thread execution enter function
+ POP {r0, r1} @ Recover r3
+#endif
+@
+@ /* Restore the thread context and PSP. */
+@
+ LDR r12, [r1, #8] @ Pickup thread's stack pointer
+ LDMIA r12!, {LR} @ Pickup LR
+ LDMIA r12!, {r4-r11} @ Recover thread's registers
+ MSR PSP, r12 @ Setup the thread's stack pointer
+@
+@ /* Return to thread. */
+@
+ BX lr @ Return to thread!
+@
+@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+@ are disabled to allow use of WFI for waiting for a thread to arrive. */
+@
+__tx_ts_wait:
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Pickup the next thread to execute pointer
+ STR r1, [r0] @ Store it in the current pointer
+ CBNZ r1, __tx_ts_ready @ If non-NULL, a new thread is ready!
+#ifdef TX_ENABLE_WFI
+ DSB @ Ensure no outstanding memory transactions
+ WFI @ Wait for interrupt
+ ISB @ Ensure pipeline is flushed
+#endif
+ CPSIE i @ Enable interrupts
+ B __tx_ts_wait @ Loop to continue waiting
+@
+@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+@ already in the handler! */
+@
+__tx_ts_ready:
+ MOV r7, #0x08000000 @ Build clear PendSV value
+ MOV r8, #0xE000E000 @ Build base NVIC address
+ STR r7, [r8, #0xD04] @ Clear any PendSV
+@
+@ /* Re-enable interrupts and restore new thread. */
+@
+ CPSIE i @ Enable interrupts
+ B __tx_ts_restore @ Restore the thread
+
diff --git a/ports/cortex_m3/gnu/src/tx_thread_stack_build.S b/ports/cortex_m3/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..bec56d45
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,148 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_stack_build Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function builds a stack frame on the supplied thread's stack. */
+@/* The stack frame results in a fake interrupt return to the supplied */
+@/* function pointer. */
+@/* */
+@/* INPUT */
+@/* */
+@/* thread_ptr Pointer to thread control blk */
+@/* function_ptr Pointer to return function */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_thread_create Create thread service */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+@{
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+@
+@
+@ /* Build a fake interrupt frame. The form of the fake interrupt stack
+@ on the Cortex-M3 should look like the following after it is built:
+@
+@ Stack Top:
+@ LR Interrupted LR (LR at time of PENDSV)
+@ r4 Initial value for r4
+@ r5 Initial value for r5
+@ r6 Initial value for r6
+@ r7 Initial value for r7
+@ r8 Initial value for r8
+@ r9 Initial value for r9
+@ r10 (sl) Initial value for r10 (sl)
+@ r11 Initial value for r11
+@ r0 Initial value for r0 (Hardware stack starts here!!)
+@ r1 Initial value for r1
+@ r2 Initial value for r2
+@ r3 Initial value for r3
+@ r12 Initial value for r12
+@ lr Initial value for lr
+@ pc Initial value for pc
+@ xPSR Initial value for xPSR
+@
+@ Stack Bottom: (higher memory address) */
+@
+ LDR r2, [r0, #16] @ Pickup end of stack area
+ BIC r2, r2, #0x7 @ Align frame
+ SUB r2, r2, #68 @ Subtract frame size
+ LDR r3, =0xFFFFFFFD @ Build initial LR value
+ STR r3, [r2, #0] @ Save on the stack
+@
+@ /* Actually build the stack frame. */
+@
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #4] @ Store initial r4
+ STR r3, [r2, #8] @ Store initial r5
+ STR r3, [r2, #12] @ Store initial r6
+ STR r3, [r2, #16] @ Store initial r7
+ STR r3, [r2, #20] @ Store initial r8
+ STR r3, [r2, #24] @ Store initial r9
+ LDR r3, [r0, #12] @ Pickup stack starting address
+ STR r3, [r2, #28] @ Store initial r10 (sl)
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #32] @ Store initial r11
+@
+@ /* Hardware stack follows. */
+@
+ STR r3, [r2, #36] @ Store initial r0
+ STR r3, [r2, #40] @ Store initial r1
+ STR r3, [r2, #44] @ Store initial r2
+ STR r3, [r2, #48] @ Store initial r3
+ STR r3, [r2, #52] @ Store initial r12
+ MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value
+ STR r3, [r2, #56] @ Store initial lr
+ STR r1, [r2, #60] @ Store initial pc
+ MOV r3, #0x01000000 @ Only T-bit need be set
+ STR r3, [r2, #64] @ Store initial xPSR
+@
+@ /* Setup stack pointer. */
+@ thread_ptr -> tx_thread_stack_ptr = r2;
+@
+ STR r2, [r0, #8] @ Save stack pointer in thread's
+ @ control block
+ BX lr @ Return to caller
+@}
+
+
diff --git a/ports/cortex_m3/gnu/src/tx_thread_system_return.S b/ports/cortex_m3/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..0ac8ce08
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_thread_system_return.S
@@ -0,0 +1,98 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@ #include "tx_timer.h" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_system_return Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is target processor specific. It is used to transfer */
+@/* control from a thread back to the ThreadX system. Only a */
+@/* minimal context is saved since the compiler assumes temp registers */
+@/* are going to get slicked by a function call anyway. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling loop */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ThreadX components */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* VOID _tx_thread_system_return(VOID)
+@{ */
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+@
+@ /* Return to real scheduler via PendSV. Note that this routine is often
+@ replaced with in-line assembly in tx_port.h to improved performance. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ MRS r0, IPSR @ Pickup IPSR
+ CMP r0, #0 @ Is it a thread returning?
+ BNE _isr_context @ If ISR, skip interrupt enable
+ MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
+ CPSIE i @ Enable interrupts
+ MSR PRIMASK, r1 @ Restore original interrupt posture
+_isr_context:
+ BX lr @ Return to caller
+
+@/* } */
+
diff --git a/ports/cortex_m3/gnu/src/tx_timer_interrupt.S b/ports/cortex_m3/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..340d70e9
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,270 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Timer */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_timer.h"
+@#include "tx_thread.h"
+@
+@
+@Define Assembly language external references...
+@
+ .global _tx_timer_time_slice
+ .global _tx_timer_system_clock
+ .global _tx_timer_current_ptr
+ .global _tx_timer_list_start
+ .global _tx_timer_list_end
+ .global _tx_timer_expired_time_slice
+ .global _tx_timer_expired
+ .global _tx_thread_time_slice
+ .global _tx_timer_expiration_process
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_timer_interrupt Cortex-M3/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function processes the hardware timer interrupt. This */
+@/* processing includes incrementing the system clock and checking for */
+@/* time slice and/or timer expiration. If either is found, the */
+@/* interrupt context save/restore functions are called along with the */
+@/* expiration functions. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_timer_expiration_process Timer expiration processing */
+@/* _tx_thread_time_slice Time slice interrupted thread */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* interrupt vector */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_timer_interrupt(VOID)
+@{
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+@
+@ /* Upon entry to this routine, it is assumed that context save has already
+@ been called, and therefore the compiler scratch registers are available
+@ for use. */
+@
+@ /* Increment the system clock. */
+@ _tx_timer_system_clock++;
+@
+ LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
+ LDR r0, [r1, #0] @ Pickup system clock
+ ADD r0, r0, #1 @ Increment system clock
+ STR r0, [r1, #0] @ Store new system clock
+@
+@ /* Test for time-slice expiration. */
+@ if (_tx_timer_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
+ LDR r2, [r3, #0] @ Pickup time-slice
+ CMP r2, #0 @ Is it non-active?
+ BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
+@
+@ /* Decrement the time_slice. */
+@ _tx_timer_time_slice--;
+@
+ SUB r2, r2, #1 @ Decrement the time-slice
+ STR r2, [r3, #0] @ Store new time-slice value
+@
+@ /* Check for expiration. */
+@ if (__tx_timer_time_slice == 0)
+@
+ CMP r2, #0 @ Has it expired?
+ BNE __tx_timer_no_time_slice @ No, skip expiration processing
+@
+@ /* Set the time-slice expired flag. */
+@ _tx_timer_expired_time_slice = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
+ MOV r0, #1 @ Build expired value
+ STR r0, [r3, #0] @ Set time-slice expiration flag
+@
+@ }
+@
+__tx_timer_no_time_slice:
+@
+@ /* Test for timer expiration. */
+@ if (*_tx_timer_current_ptr)
+@ {
+@
+ LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
+ LDR r0, [r1, #0] @ Pickup current timer
+ LDR r2, [r0, #0] @ Pickup timer list entry
+ CMP r2, #0 @ Is there anything in the list?
+ BEQ __tx_timer_no_timer @ No, just increment the timer
+@
+@ /* Set expiration flag. */
+@ _tx_timer_expired = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired @ Pickup expiration flag address
+ MOV r2, #1 @ Build expired value
+ STR r2, [r3, #0] @ Set expired flag
+ B __tx_timer_done @ Finished timer processing
+@
+@ }
+@ else
+@ {
+__tx_timer_no_timer:
+@
+@ /* No timer expired, increment the timer pointer. */
+@ _tx_timer_current_ptr++;
+@
+ ADD r0, r0, #4 @ Move to next timer
+@
+@ /* Check for wrap-around. */
+@ if (_tx_timer_current_ptr == _tx_timer_list_end)
+@
+ LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
+ LDR r2, [r3, #0] @ Pickup list end
+ CMP r0, r2 @ Are we at list end?
+ BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
+@
+@ /* Wrap to beginning of list. */
+@ _tx_timer_current_ptr = _tx_timer_list_start;
+@
+ LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
+ LDR r0, [r3, #0] @ Set current pointer to list start
+@
+__tx_timer_skip_wrap:
+@
+ STR r0, [r1, #0] @ Store new current timer pointer
+@ }
+@
+__tx_timer_done:
+@
+@
+@ /* See if anything has expired. */
+@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
+ LDR r2, [r3, #0] @ Pickup time-slice expired flag
+ CMP r2, #0 @ Did a time-slice expire?
+ BNE __tx_something_expired @ If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Did a timer expire?
+ BEQ __tx_timer_nothing_expired @ No, nothing expired
+@
+__tx_something_expired:
+@
+@
+ STMDB sp!, {r0, lr} @ Save the lr register on the stack
+ @ and save r0 just to keep 8-byte alignment
+@
+@ /* Did a timer expire? */
+@ if (_tx_timer_expired)
+@ {
+@
+ LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Check for timer expiration
+ BEQ __tx_timer_dont_activate @ If not set, skip timer activation
+@
+@ /* Process timer expiration. */
+@ _tx_timer_expiration_process();
+@
+ BL _tx_timer_expiration_process @ Call the timer expiration handling routine
+@
+@ }
+__tx_timer_dont_activate:
+@
+@ /* Did time slice expire? */
+@ if (_tx_timer_expired_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
+ LDR r2, [r3, #0] @ Pickup the actual flag
+ CMP r2, #0 @ See if the flag is set
+ BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
+@
+@ /* Time slice interrupted thread. */
+@ _tx_thread_time_slice();
+@
+ BL _tx_thread_time_slice @ Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ LDR r1, [r0] @ Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r1, [r0] @ Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ LDR r3, [r2] @ Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 @ Build address of control register
+ LDR r2, =0x10000000 @ Build value for PendSV bit
+ CMP r1, r3 @ Are they the same?
+ BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
+ STR r2, [r0] @ Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+@
+@ }
+@
+__tx_timer_not_ts_expiration:
+@
+ LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for
+ @ the 8-byte stack alignment
+@
+@ }
+@
+__tx_timer_nothing_expired:
+
+ DSB @ Complete all memory access
+ BX lr @ Return to caller
+@
+@}
+
+
diff --git a/ports/cortex_m3/gnu/src/tx_vector_table_sample.S b/ports/cortex_m3/gnu/src/tx_vector_table_sample.S
new file mode 100644
index 00000000..cf0db974
--- /dev/null
+++ b/ports/cortex_m3/gnu/src/tx_vector_table_sample.S
@@ -0,0 +1,84 @@
+
+
+ .global reset_handler
+
+ .global __tx_NMIHandler
+ .global __tx_BadHandler
+ .global __tx_SVCallHandler
+ .global __tx_DBGHandler
+ .global __tx_PendSVHandler
+ .global __tx_SysTickHandler
+ .global __tx_BadHandler
+
+
+ .syntax unified
+ .section .vectors, "ax"
+ .code 16
+ .align 0
+ .global _vectors
+
+_vectors:
+ .word __stack_end__
+ .word reset_handler
+ .word __tx_NMIHandler
+ .word __tx_HardfaultHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
+ .word __tx_DBGHandler
+ .word 0 // Reserved
+ .word __tx_PendSVHandler
+ .word __tx_SysTickHandler // Used by Threadx timer functionality
+ .word __tx_BadHandler // Populate with user Interrupt handler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+
+
+
+ .section .init, "ax"
+ .thumb_func
+reset_handler:
+
+// low level hardware config, such as PLL setup goes here
+
+ b _start
+
+
+
diff --git a/ports/cortex_m4/gnu/CMakeLists.txt b/ports/cortex_m4/gnu/CMakeLists.txt
new file mode 100644
index 00000000..cb3091b9
--- /dev/null
+++ b/ports/cortex_m4/gnu/CMakeLists.txt
@@ -0,0 +1,19 @@
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h
new file mode 100644
index 00000000..bca31b3d
--- /dev/null
+++ b/ports/cortex_m4/gnu/inc/tx_port.h
@@ -0,0 +1,499 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h Cortex-M4/GNU */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX Cortex-M7 port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#define TX_INLINE_INITIALIZATION
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+
+
+#ifdef TX_ENABLE_FPU_SUPPORT
+
+
+#ifdef TX_MISRA_ENABLE
+
+ULONG _tx_misra_control_get(void);
+void _tx_misra_control_set(ULONG value);
+ULONG _tx_misra_fpccr_get(void);
+void _tx_misra_vfp_touch(void);
+
+#else
+
+__attribute__( ( always_inline ) ) static inline ULONG __get_control(void)
+{
+
+ULONG control_value;
+
+ __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
+ return(control_value);
+}
+
+
+__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value)
+{
+
+ __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
+}
+
+
+#endif
+
+
+/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
+ in order to ensure no lazy stacking will occur. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ }
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ }
+
+#endif
+
+
+/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
+ If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
+ this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
+ the lazy FPU save, then restore the CONTROL.FPCA state. */
+
+#ifndef TX_MISRA_ENABLE
+
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = *((ULONG *) 0xE000EF34); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ __asm__ volatile ("vmov.f32 s0, s0"); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#else
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = _tx_misra_fpccr_get(); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ _tx_misra_vfp_touch(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#endif
+
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#endif
+
+
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+
+/* Define the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+
+unsigned int ipsr_value;
+
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+#else
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+/* This ARM architecture has the CLZ instruction. This is available on
+ architectures v5 and above. If available, redefine the macro for calculating the
+ lowest bit set. */
+
+#ifndef TX_DISABLE_INLINE
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+
+#endif
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define GNU specific macros, with in-line assembly for performance. */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ __asm__ volatile (" CPSID i" : : : "memory" );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
+{
+
+ __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
+}
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+
+ __asm__ volatile (" CPSIE i": : : "memory" );
+}
+
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_primask_value();
+ __enable_interrupts();
+ __restore_interrupts(interrupt_save);
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+#endif
+
+
+/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
+ thread. This is for legacy only, and not needed anylonger. */
+
+void tx_thread_fpu_enable(void);
+void tx_thread_fpu_disable(void);
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/GNU Version 6.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
+
+
+
+
diff --git a/ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S b/ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S
new file mode 100644
index 00000000..ce57f6e7
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S
@@ -0,0 +1,240 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Initialize */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_initialize.h"
+@#include "tx_thread.h"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+ .global __RAM_segment_used_end__
+ .global _tx_timer_interrupt
+ .global __main
+ .global __tx_SVCallHandler
+ .global __tx_PendSVHandler
+ .global _vectors
+ .global __tx_NMIHandler @ NMI
+ .global __tx_BadHandler @ HardFault
+ .global __tx_SVCallHandler @ SVCall
+ .global __tx_DBGHandler @ Monitor
+ .global __tx_PendSVHandler @ PendSV
+ .global __tx_SysTickHandler @ SysTick
+ .global __tx_IntHandler @ Int 0
+@
+@
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_initialize_low_level Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for any low-level processor */
+@/* initialization, including setting up interrupt vectors, setting */
+@/* up a periodic timer interrupt source, saving the system stack */
+@/* pointer for use in ISR processing later, and finding the first */
+@/* available RAM memory address for tx_application_define. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_initialize_low_level(VOID)
+@{
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+@
+@ /* Disable interrupts during ThreadX initialization. */
+@
+ CPSID i
+@
+@ /* Set base of available memory to end of non-initialised RAM area. */
+@
+ LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ @ Build first free address
+ ADD r1, r1, #4 @
+ STR r1, [r0] @ Setup first unused memory pointer
+@
+@ /* Setup Vector Table Offset Register. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =_vectors @ Pickup address of vector table
+ STR r1, [r0, #0xD08] @ Set vector table address
+@
+@ /* Set system stack pointer from vector value. */
+@
+ LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
+ LDR r1, =_vectors @ Pickup address of vector table
+ LDR r1, [r1] @ Pickup reset stack pointer
+ STR r1, [r0] @ Save system stack pointer
+@
+@ /* Enable the cycle count register. */
+@
+ LDR r0, =0xE0001000 @ Build address of DWT register
+ LDR r1, [r0] @ Pickup the current value
+ ORR r1, r1, #1 @ Set the CYCCNTENA bit
+ STR r1, [r0] @ Enable the cycle count register
+@
+@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] @ Setup SysTick Reload Value
+ MOV r1, #0x7 @ Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] @ Setup SysTick Control
+@
+@ /* Configure handler priorities. */
+@
+ LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
+
+ LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
+ @ Note: SVC must be lowest priority, which is 0xFF
+
+ LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
+ @ Note: PnSV must be lowest priority, which is 0xFF
+
+@
+@ /* Return to caller. */
+@
+ BX lr
+@}
+@
+
+@/* Define shells for each of the unused vectors. */
+@
+ .global __tx_BadHandler
+ .thumb_func
+__tx_BadHandler:
+ B __tx_BadHandler
+
+@ /* added to catch the hardfault */
+
+ .global __tx_HardfaultHandler
+ .thumb_func
+__tx_HardfaultHandler:
+ B __tx_HardfaultHandler
+
+
+@ /* added to catch the SVC */
+
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+
+@ /* Generic interrupt handler template */
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+@ VOID InterruptHandler (VOID)
+@ {
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+
+@ /* Do interrupt handler work here */
+@ /* BL <your C Function>.... */
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+@ /* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+@ VOID TimerInterruptHandler (VOID)
+@ {
+@
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+
+@ /* NMI, DBG handlers */
+ .global __tx_NMIHandler
+ .thumb_func
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .global __tx_DBGHandler
+ .thumb_func
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
diff --git a/ports/cortex_m4/gnu/src/tx_thread_context_restore.S b/ports/cortex_m4/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..37e37c28
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,96 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_thread_system_stack_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_schedule
+ .global _tx_thread_preempt_disable
+ .global _tx_execution_isr_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_restore Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function restores the interrupt context if it is processing a */
+@/* nested interrupt. If not, it returns to the interrupt thread if no */
+@/* preemption is necessary. Otherwise, if preemption is necessary or */
+@/* if no thread was running, the function returns to the scheduler. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling routine */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs Interrupt Service Routines */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_restore(VOID)
+@{
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
+
diff --git a/ports/cortex_m4/gnu/src/tx_thread_context_save.S b/ports/cortex_m4/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..b2196ac4
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_execution_isr_enter
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_save Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function saves the context of an executing thread in the */
+@/* beginning of interrupt processing. The function also ensures that */
+@/* the system stack is used upon return to the calling ISR. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_save(VOID)
+@{
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
diff --git a/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..31e83f46
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,92 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_control Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for changing the interrupt lockout */
+@/* posture of the system. */
+@/* */
+@/* INPUT */
+@/* */
+@/* new_posture New interrupt lockout posture */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* UINT _tx_thread_interrupt_control(UINT new_posture)
+{ */
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+
+@/* Pickup current interrupt lockout posture. */
+
+ MRS r1, PRIMASK @ Pickup current interrupt lockout
+
+@/* Apply the new interrupt posture. */
+
+ MSR PRIMASK, r0 @ Apply the new interrupt lockout
+ MOV r0, r1 @ Transfer old to return register
+ BX lr @ Return to caller
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m4/gnu/src/tx_thread_schedule.S b/ports/cortex_m4/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..11bdbe09
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,296 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_system_stack_ptr
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_schedule Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function waits for a thread control block pointer to appear in */
+@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+@/* in the variable, the corresponding thread is resumed. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* _tx_thread_system_return Return to system from thread */
+@/* _tx_thread_context_restore Restore thread's context */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_schedule(VOID)
+@{
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+@
+@ /* This function should only ever be called on Cortex-M4
+@ from the first schedule request. Subsequent scheduling occurs
+@ from the PendSV handling routines below. */
+@
+@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+@
+ MOV r0, #0 @ Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ STR r0, [r2, #0] @ Clear preempt disable flag
+@
+@ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+@
+#ifdef TX_ENABLE_FPU_SUPPORT
+ MRS r0, CONTROL @ Pickup current CONTROL register
+ BIC r0, r0, #4 @ Clear the FPCA bit
+ MSR CONTROL, r0 @ Setup new CONTROL register
+#endif
+@
+@ /* Enable interrupts */
+@
+ CPSIE i
+@
+@ /* Enter the scheduler for the first time. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ DSB @ Complete all memory accesses
+ ISB @ Flush pipeline
+@
+@ /* Wait here for the PendSV to take place. */
+@
+__tx_wait_here:
+ B __tx_wait_here @ Wait for the PendSV to happen
+@}
+@
+@ /* Generic context switch-out switch-in handler... Note that this handler is
+@ common for both PendSV and SVCall. */
+@
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+@
+@ /* Get current thread value and new thread pointer. */
+@
+__tx_ts_handler:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread exit function to indicate the thread is no longer executing. */
+@
+ CPSID i @ Disable interrupts
+ PUSH {r0, lr} @ Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit @ Call the thread exit function
+ POP {r0, lr} @ Recover LR
+ CPSIE i @ Enable interrupts
+#endif
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ MOV r3, #0 @ Build NULL value
+ LDR r1, [r0] @ Pickup current thread pointer
+@
+@ /* Determine if there is a current thread to finish preserving. */
+@
+ CBZ r1, __tx_ts_new @ If NULL, skip preservation
+@
+@ /* Recover PSP and preserve current thread context. */
+@
+ STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP @ Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} @ Save its remaining registers
+#ifdef TX_ENABLE_FPU_SUPPORT
+ TST LR, #0x10 @ Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ STMDB r12!, {LR} @ Save LR on the stack
+@
+@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+@
+ LDR r5, [r4] @ Pickup current time-slice
+ STR r12, [r1, #8] @ Save the thread stack pointer
+ CBZ r5, __tx_ts_new @ If not active, skip processing
+@
+@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+@
+ STR r5, [r1, #24] @ Save current time-slice
+@
+@ /* Clear the global time-slice. */
+@
+ STR r3, [r4] @ Clear time-slice
+@
+@
+@ /* Executing thread is now completely preserved!!! */
+@
+__tx_ts_new:
+@
+@ /* Now we are looking for a new thread to execute! */
+@
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait @ No, skip to the wait processing
+@
+@ /* Yes, another thread is ready for else, make the current thread the new thread. */
+@
+ STR r1, [r0] @ Setup the current thread pointer to the new thread
+ CPSIE i @ Enable interrupts
+@
+@ /* Increment the thread run count. */
+@
+__tx_ts_restore:
+ LDR r7, [r1, #4] @ Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ LDR r5, [r1, #24] @ Pickup thread's current time-slice
+ ADD r7, r7, #1 @ Increment the thread run count
+ STR r7, [r1, #4] @ Store the new run count
+@
+@ /* Setup global time-slice with thread's current time-slice. */
+@
+ STR r5, [r4] @ Setup global time-slice
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread entry function to indicate the thread is executing. */
+@
+ PUSH {r0, r1} @ Save r0/r1
+ BL _tx_execution_thread_enter @ Call the thread execution enter function
+ POP {r0, r1} @ Recover r3
+#endif
+@
+@ /* Restore the thread context and PSP. */
+@
+ LDR r12, [r1, #8] @ Pickup thread's stack pointer
+ LDMIA r12!, {LR} @ Pickup LR
+#ifdef TX_ENABLE_FPU_SUPPORT
+ TST LR, #0x10 @ Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore @ If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} @ Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} @ Recover thread's registers
+ MSR PSP, r12 @ Setup the thread's stack pointer
+@
+@ /* Return to thread. */
+@
+ BX lr @ Return to thread!
+@
+@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+@ are disabled to allow use of WFI for waiting for a thread to arrive. */
+@
+__tx_ts_wait:
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Pickup the next thread to execute pointer
+ STR r1, [r0] @ Store it in the current pointer
+ CBNZ r1, __tx_ts_ready @ If non-NULL, a new thread is ready!
+#ifdef TX_ENABLE_WFI
+ DSB @ Ensure no outstanding memory transactions
+ WFI @ Wait for interrupt
+ ISB @ Ensure pipeline is flushed
+#endif
+ CPSIE i @ Enable interrupts
+ B __tx_ts_wait @ Loop to continue waiting
+@
+@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+@ already in the handler! */
+@
+__tx_ts_ready:
+ MOV r7, #0x08000000 @ Build clear PendSV value
+ MOV r8, #0xE000E000 @ Build base NVIC address
+ STR r7, [r8, #0xD04] @ Clear any PendSV
+@
+@ /* Re-enable interrupts and restore new thread. */
+@
+ CPSIE i @ Enable interrupts
+ B __tx_ts_restore @ Restore the thread
+
+
+#ifdef TX_ENABLE_FPU_SUPPORT
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+@
+@ /* Automatic VPF logic is supported, this function is present only for
+@ backward compatibility purposes and therefore simply returns. */
+@
+ BX LR @ Return to caller
+
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+@
+@ /* Automatic VPF logic is supported, this function is present only for
+@ backward compatibility purposes and therefore simply returns. */
+@
+ BX LR @ Return to caller
+
+
+#endif
+
diff --git a/ports/cortex_m4/gnu/src/tx_thread_stack_build.S b/ports/cortex_m4/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..f9ca6842
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,148 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_stack_build Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function builds a stack frame on the supplied thread's stack. */
+@/* The stack frame results in a fake interrupt return to the supplied */
+@/* function pointer. */
+@/* */
+@/* INPUT */
+@/* */
+@/* thread_ptr Pointer to thread control blk */
+@/* function_ptr Pointer to return function */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_thread_create Create thread service */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+@{
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+@
+@
+@ /* Build a fake interrupt frame. The form of the fake interrupt stack
+@ on the Cortex-M4 should look like the following after it is built:
+@
+@ Stack Top:
+@ LR Interrupted LR (LR at time of PENDSV)
+@ r4 Initial value for r4
+@ r5 Initial value for r5
+@ r6 Initial value for r6
+@ r7 Initial value for r7
+@ r8 Initial value for r8
+@ r9 Initial value for r9
+@ r10 (sl) Initial value for r10 (sl)
+@ r11 Initial value for r11
+@ r0 Initial value for r0 (Hardware stack starts here!!)
+@ r1 Initial value for r1
+@ r2 Initial value for r2
+@ r3 Initial value for r3
+@ r12 Initial value for r12
+@ lr Initial value for lr
+@ pc Initial value for pc
+@ xPSR Initial value for xPSR
+@
+@ Stack Bottom: (higher memory address) */
+@
+ LDR r2, [r0, #16] @ Pickup end of stack area
+ BIC r2, r2, #0x7 @ Align frame
+ SUB r2, r2, #68 @ Subtract frame size
+ LDR r3, =0xFFFFFFFD @ Build initial LR value
+ STR r3, [r2, #0] @ Save on the stack
+@
+@ /* Actually build the stack frame. */
+@
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #4] @ Store initial r4
+ STR r3, [r2, #8] @ Store initial r5
+ STR r3, [r2, #12] @ Store initial r6
+ STR r3, [r2, #16] @ Store initial r7
+ STR r3, [r2, #20] @ Store initial r8
+ STR r3, [r2, #24] @ Store initial r9
+ LDR r3, [r0, #12] @ Pickup stack starting address
+ STR r3, [r2, #28] @ Store initial r10 (sl)
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #32] @ Store initial r11
+@
+@ /* Hardware stack follows. */
+@
+ STR r3, [r2, #36] @ Store initial r0
+ STR r3, [r2, #40] @ Store initial r1
+ STR r3, [r2, #44] @ Store initial r2
+ STR r3, [r2, #48] @ Store initial r3
+ STR r3, [r2, #52] @ Store initial r12
+ MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value
+ STR r3, [r2, #56] @ Store initial lr
+ STR r1, [r2, #60] @ Store initial pc
+ MOV r3, #0x01000000 @ Only T-bit need be set
+ STR r3, [r2, #64] @ Store initial xPSR
+@
+@ /* Setup stack pointer. */
+@ thread_ptr -> tx_thread_stack_ptr = r2;
+@
+ STR r2, [r0, #8] @ Save stack pointer in thread's
+ @ control block
+ BX lr @ Return to caller
+@}
+
+
diff --git a/ports/cortex_m4/gnu/src/tx_thread_system_return.S b/ports/cortex_m4/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..d570bb73
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_thread_system_return.S
@@ -0,0 +1,98 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@ #include "tx_timer.h" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_system_return Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is target processor specific. It is used to transfer */
+@/* control from a thread back to the ThreadX system. Only a */
+@/* minimal context is saved since the compiler assumes temp registers */
+@/* are going to get slicked by a function call anyway. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling loop */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ThreadX components */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* VOID _tx_thread_system_return(VOID)
+@{ */
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+@
+@ /* Return to real scheduler via PendSV. Note that this routine is often
+@ replaced with in-line assembly in tx_port.h to improved performance. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ MRS r0, IPSR @ Pickup IPSR
+ CMP r0, #0 @ Is it a thread returning?
+ BNE _isr_context @ If ISR, skip interrupt enable
+ MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
+ CPSIE i @ Enable interrupts
+ MSR PRIMASK, r1 @ Restore original interrupt posture
+_isr_context:
+ BX lr @ Return to caller
+
+@/* } */
+
diff --git a/ports/cortex_m4/gnu/src/tx_timer_interrupt.S b/ports/cortex_m4/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..6d96eaf9
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,270 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Timer */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_timer.h"
+@#include "tx_thread.h"
+@
+@
+@Define Assembly language external references...
+@
+ .global _tx_timer_time_slice
+ .global _tx_timer_system_clock
+ .global _tx_timer_current_ptr
+ .global _tx_timer_list_start
+ .global _tx_timer_list_end
+ .global _tx_timer_expired_time_slice
+ .global _tx_timer_expired
+ .global _tx_thread_time_slice
+ .global _tx_timer_expiration_process
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_timer_interrupt Cortex-M4/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function processes the hardware timer interrupt. This */
+@/* processing includes incrementing the system clock and checking for */
+@/* time slice and/or timer expiration. If either is found, the */
+@/* interrupt context save/restore functions are called along with the */
+@/* expiration functions. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_timer_expiration_process Timer expiration processing */
+@/* _tx_thread_time_slice Time slice interrupted thread */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* interrupt vector */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_timer_interrupt(VOID)
+@{
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+@
+@ /* Upon entry to this routine, it is assumed that context save has already
+@ been called, and therefore the compiler scratch registers are available
+@ for use. */
+@
+@ /* Increment the system clock. */
+@ _tx_timer_system_clock++;
+@
+ LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
+ LDR r0, [r1, #0] @ Pickup system clock
+ ADD r0, r0, #1 @ Increment system clock
+ STR r0, [r1, #0] @ Store new system clock
+@
+@ /* Test for time-slice expiration. */
+@ if (_tx_timer_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
+ LDR r2, [r3, #0] @ Pickup time-slice
+ CMP r2, #0 @ Is it non-active?
+ BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
+@
+@ /* Decrement the time_slice. */
+@ _tx_timer_time_slice--;
+@
+ SUB r2, r2, #1 @ Decrement the time-slice
+ STR r2, [r3, #0] @ Store new time-slice value
+@
+@ /* Check for expiration. */
+@ if (__tx_timer_time_slice == 0)
+@
+ CMP r2, #0 @ Has it expired?
+ BNE __tx_timer_no_time_slice @ No, skip expiration processing
+@
+@ /* Set the time-slice expired flag. */
+@ _tx_timer_expired_time_slice = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
+ MOV r0, #1 @ Build expired value
+ STR r0, [r3, #0] @ Set time-slice expiration flag
+@
+@ }
+@
+__tx_timer_no_time_slice:
+@
+@ /* Test for timer expiration. */
+@ if (*_tx_timer_current_ptr)
+@ {
+@
+ LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
+ LDR r0, [r1, #0] @ Pickup current timer
+ LDR r2, [r0, #0] @ Pickup timer list entry
+ CMP r2, #0 @ Is there anything in the list?
+ BEQ __tx_timer_no_timer @ No, just increment the timer
+@
+@ /* Set expiration flag. */
+@ _tx_timer_expired = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired @ Pickup expiration flag address
+ MOV r2, #1 @ Build expired value
+ STR r2, [r3, #0] @ Set expired flag
+ B __tx_timer_done @ Finished timer processing
+@
+@ }
+@ else
+@ {
+__tx_timer_no_timer:
+@
+@ /* No timer expired, increment the timer pointer. */
+@ _tx_timer_current_ptr++;
+@
+ ADD r0, r0, #4 @ Move to next timer
+@
+@ /* Check for wrap-around. */
+@ if (_tx_timer_current_ptr == _tx_timer_list_end)
+@
+ LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
+ LDR r2, [r3, #0] @ Pickup list end
+ CMP r0, r2 @ Are we at list end?
+ BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
+@
+@ /* Wrap to beginning of list. */
+@ _tx_timer_current_ptr = _tx_timer_list_start;
+@
+ LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
+ LDR r0, [r3, #0] @ Set current pointer to list start
+@
+__tx_timer_skip_wrap:
+@
+ STR r0, [r1, #0] @ Store new current timer pointer
+@ }
+@
+__tx_timer_done:
+@
+@
+@ /* See if anything has expired. */
+@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
+ LDR r2, [r3, #0] @ Pickup time-slice expired flag
+ CMP r2, #0 @ Did a time-slice expire?
+ BNE __tx_something_expired @ If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Did a timer expire?
+ BEQ __tx_timer_nothing_expired @ No, nothing expired
+@
+__tx_something_expired:
+@
+@
+ STMDB sp!, {r0, lr} @ Save the lr register on the stack
+ @ and save r0 just to keep 8-byte alignment
+@
+@ /* Did a timer expire? */
+@ if (_tx_timer_expired)
+@ {
+@
+ LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Check for timer expiration
+ BEQ __tx_timer_dont_activate @ If not set, skip timer activation
+@
+@ /* Process timer expiration. */
+@ _tx_timer_expiration_process();
+@
+ BL _tx_timer_expiration_process @ Call the timer expiration handling routine
+@
+@ }
+__tx_timer_dont_activate:
+@
+@ /* Did time slice expire? */
+@ if (_tx_timer_expired_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
+ LDR r2, [r3, #0] @ Pickup the actual flag
+ CMP r2, #0 @ See if the flag is set
+ BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
+@
+@ /* Time slice interrupted thread. */
+@ _tx_thread_time_slice();
+@
+ BL _tx_thread_time_slice @ Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ LDR r1, [r0] @ Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r1, [r0] @ Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ LDR r3, [r2] @ Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 @ Build address of control register
+ LDR r2, =0x10000000 @ Build value for PendSV bit
+ CMP r1, r3 @ Are they the same?
+ BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
+ STR r2, [r0] @ Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+@
+@ }
+@
+__tx_timer_not_ts_expiration:
+@
+ LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for
+ @ the 8-byte stack alignment
+@
+@ }
+@
+__tx_timer_nothing_expired:
+
+ DSB @ Complete all memory access
+ BX lr @ Return to caller
+@
+@}
+
+
diff --git a/ports/cortex_m4/gnu/src/tx_vector_table_sample.S b/ports/cortex_m4/gnu/src/tx_vector_table_sample.S
new file mode 100644
index 00000000..cf0db974
--- /dev/null
+++ b/ports/cortex_m4/gnu/src/tx_vector_table_sample.S
@@ -0,0 +1,84 @@
+
+
+ .global reset_handler
+
+ .global __tx_NMIHandler
+ .global __tx_BadHandler
+ .global __tx_SVCallHandler
+ .global __tx_DBGHandler
+ .global __tx_PendSVHandler
+ .global __tx_SysTickHandler
+ .global __tx_BadHandler
+
+
+ .syntax unified
+ .section .vectors, "ax"
+ .code 16
+ .align 0
+ .global _vectors
+
+_vectors:
+ .word __stack_end__
+ .word reset_handler
+ .word __tx_NMIHandler
+ .word __tx_HardfaultHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
+ .word __tx_DBGHandler
+ .word 0 // Reserved
+ .word __tx_PendSVHandler
+ .word __tx_SysTickHandler // Used by Threadx timer functionality
+ .word __tx_BadHandler // Populate with user Interrupt handler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+
+
+
+ .section .init, "ax"
+ .thumb_func
+reset_handler:
+
+// low level hardware config, such as PLL setup goes here
+
+ b _start
+
+
+
diff --git a/ports/cortex_m7/gnu/CMakeLists.txt b/ports/cortex_m7/gnu/CMakeLists.txt
new file mode 100644
index 00000000..a361adf0
--- /dev/null
+++ b/ports/cortex_m7/gnu/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+target_sources(${PROJECT_NAME} PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME} PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h
new file mode 100644
index 00000000..95adfab4
--- /dev/null
+++ b/ports/cortex_m7/gnu/inc/tx_port.h
@@ -0,0 +1,496 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h Cortex-M7/GNU */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX Cortex-M7 port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#define TX_INLINE_INITIALIZATION
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+
+#ifdef TX_ENABLE_FPU_SUPPORT
+
+
+#ifdef TX_MISRA_ENABLE
+
+ULONG _tx_misra_control_get(void);
+void _tx_misra_control_set(ULONG value);
+ULONG _tx_misra_fpccr_get(void);
+void _tx_misra_vfp_touch(void);
+
+#else
+
+__attribute__( ( always_inline ) ) static inline ULONG __get_control(void)
+{
+
+ULONG control_value;
+
+ __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
+ return(control_value);
+}
+
+
+__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value)
+{
+
+ __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
+}
+
+
+#endif
+
+
+/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
+ in order to ensure no lazy stacking will occur. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ }
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ }
+
+#endif
+
+
+/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
+ If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
+ this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
+ the lazy FPU save, then restore the CONTROL.FPCA state. */
+
+#ifndef TX_MISRA_ENABLE
+
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = *((ULONG *) 0xE000EF34); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ __asm__ volatile ("vmov.f32 s0, s0"); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = __get_control(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#else
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = _tx_misra_fpccr_get(); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ _tx_misra_vfp_touch(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#endif
+
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#endif
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+
+/* Define the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+
+unsigned int ipsr_value;
+
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+#else
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+/* This ARM architecture has the CLZ instruction. This is available on
+ architectures v5 and above. If available, redefine the macro for calculating the
+ lowest bit set. */
+
+#ifndef TX_DISABLE_INLINE
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+
+#endif
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define GNU specific macros, with in-line assembly for performance. */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ __asm__ volatile (" CPSID i" : : : "memory" );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
+{
+
+ __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
+}
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
+{
+
+unsigned int primask_value;
+
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ return(primask_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+
+ __asm__ volatile (" CPSIE i": : : "memory" );
+}
+
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_primask_value();
+ __enable_interrupts();
+ __restore_interrupts(interrupt_save);
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+#endif
+
+
+/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
+ thread. This is for legacy only, and not needed any longer. */
+
+void tx_thread_fpu_enable(void);
+void tx_thread_fpu_disable(void);
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/GNU Version 6.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
+
+
+
+
diff --git a/ports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S b/ports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S
new file mode 100755
index 00000000..1957867c
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S
@@ -0,0 +1,239 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Initialize */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_initialize.h"
+@#include "tx_thread.h"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+ .global __RAM_segment_used_end__
+ .global _tx_timer_interrupt
+ .global __main
+ .global __tx_SVCallHandler
+ .global __tx_PendSVHandler
+ .global _vectors
+ .global __tx_NMIHandler @ NMI
+ .global __tx_BadHandler @ HardFault
+ .global __tx_SVCallHandler @ SVCall
+ .global __tx_DBGHandler @ Monitor
+ .global __tx_PendSVHandler @ PendSV
+ .global __tx_SysTickHandler @ SysTick
+ .global __tx_IntHandler @ Int 0
+@
+@
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_initialize_low_level Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for any low-level processor */
+@/* initialization, including setting up interrupt vectors, setting */
+@/* up a periodic timer interrupt source, saving the system stack */
+@/* pointer for use in ISR processing later, and finding the first */
+@/* available RAM memory address for tx_application_define. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_initialize_low_level(VOID)
+@{
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+@
+@ /* Disable interrupts during ThreadX initialization. */
+@
+ CPSID i
+@
+@ /* Set base of available memory to end of non-initialised RAM area. */
+@
+ LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ @ Build first free address
+ ADD r1, r1, #4 @
+ STR r1, [r0] @ Setup first unused memory pointer
+@
+@ /* Setup Vector Table Offset Register. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =_vectors @ Pickup address of vector table
+ STR r1, [r0, #0xD08] @ Set vector table address
+@
+@ /* Set system stack pointer from vector value. */
+@
+ LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
+ LDR r1, =_vectors @ Pickup address of vector table
+ LDR r1, [r1] @ Pickup reset stack pointer
+ STR r1, [r0] @ Save system stack pointer
+@
+@ /* Enable the cycle count register. */
+@
+ LDR r0, =0xE0001000 @ Build address of DWT register
+ LDR r1, [r0] @ Pickup the current value
+ ORR r1, r1, #1 @ Set the CYCCNTENA bit
+ STR r1, [r0] @ Enable the cycle count register
+@
+@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
+@
+ MOV r0, #0xE000E000 @ Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] @ Setup SysTick Reload Value
+ MOV r1, #0x7 @ Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] @ Setup SysTick Control
+@
+@ /* Configure handler priorities. */
+@
+ LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
+
+ LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
+ @ Note: SVC must be lowest priority, which is 0xFF
+
+ LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
+ @ Note: PnSV must be lowest priority, which is 0xFF
+
+@
+@ /* Return to caller. */
+@
+ BX lr
+@}
+@
+
+@/* Define shells for each of the unused vectors. */
+@
+ .global __tx_BadHandler
+ .thumb_func
+__tx_BadHandler:
+ B __tx_BadHandler
+
+@ /* added to catch the hardfault */
+
+ .global __tx_HardfaultHandler
+ .thumb_func
+__tx_HardfaultHandler:
+ B __tx_HardfaultHandler
+
+
+@ /* added to catch the SVC */
+
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+
+@ /* Generic interrupt handler template */
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+@ VOID InterruptHandler (VOID)
+@ {
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+
+@ /* Do interrupt handler work here */
+@ /* BL <your C Function>.... */
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+@ /* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+@ VOID TimerInterruptHandler (VOID)
+@ {
+@
+ PUSH {r0, lr}
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_enter ; Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ BL _tx_execution_isr_exit ; Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX LR
+@ }
+
+
+@ /* NMI, DBG handlers */
+ .global __tx_NMIHandler
+ .thumb_func
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .global __tx_DBGHandler
+ .thumb_func
+__tx_DBGHandler:
+ B __tx_DBGHandler
diff --git a/ports/cortex_m7/gnu/src/tx_thread_context_restore.S b/ports/cortex_m7/gnu/src/tx_thread_context_restore.S
new file mode 100755
index 00000000..53a7a18f
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,96 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_thread_system_stack_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_schedule
+ .global _tx_thread_preempt_disable
+ .global _tx_execution_isr_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_restore Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function restores the interrupt context if it is processing a */
+@/* nested interrupt. If not, it returns to the interrupt thread if no */
+@/* preemption is necessary. Otherwise, if preemption is necessary or */
+@/* if no thread was running, the function returns to the scheduler. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling routine */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs Interrupt Service Routines */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_restore(VOID)
+@{
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
+
diff --git a/ports/cortex_m7/gnu/src/tx_thread_context_save.S b/ports/cortex_m7/gnu/src/tx_thread_context_save.S
new file mode 100755
index 00000000..1c7eff9e
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+@
+ .global _tx_thread_system_state
+ .global _tx_thread_current_ptr
+ .global _tx_execution_isr_enter
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_context_save Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function saves the context of an executing thread in the */
+@/* beginning of interrupt processing. The function also ensures that */
+@/* the system stack is used upon return to the calling ISR. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ISRs */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_context_save(VOID)
+@{
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+@
+@ /* Not needed for this port - just return! */
+ BX lr
+@}
diff --git a/ports/cortex_m7/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m7/gnu/src/tx_thread_interrupt_control.S
new file mode 100755
index 00000000..f4e3f61c
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,92 @@
+@/**************************************************************************/
+@/* */
+@/* 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" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_interrupt_control Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is responsible for changing the interrupt lockout */
+@/* posture of the system. */
+@/* */
+@/* INPUT */
+@/* */
+@/* new_posture New interrupt lockout posture */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* old_posture Old interrupt lockout posture */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* Application Code */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* UINT _tx_thread_interrupt_control(UINT new_posture)
+{ */
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+
+@/* Pickup current interrupt lockout posture. */
+
+ MRS r1, PRIMASK @ Pickup current interrupt lockout
+
+@/* Apply the new interrupt posture. */
+
+ MSR PRIMASK, r0 @ Apply the new interrupt lockout
+ MOV r0, r1 @ Transfer old to return register
+ BX lr @ Return to caller
+
+@/* } */
+
+
+
diff --git a/ports/cortex_m7/gnu/src/tx_thread_schedule.S b/ports/cortex_m7/gnu/src/tx_thread_schedule.S
new file mode 100755
index 00000000..99af8be2
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,296 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@#include "tx_timer.h"
+@
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_system_stack_ptr
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_schedule Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function waits for a thread control block pointer to appear in */
+@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+@/* in the variable, the corresponding thread is resumed. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_initialize_kernel_enter ThreadX entry function */
+@/* _tx_thread_system_return Return to system from thread */
+@/* _tx_thread_context_restore Restore thread's context */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_schedule(VOID)
+@{
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+@
+@ /* This function should only ever be called on Cortex-M7
+@ from the first schedule request. Subsequent scheduling occurs
+@ from the PendSV handling routines below. */
+@
+@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+@
+ MOV r0, #0 @ Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ STR r0, [r2, #0] @ Clear preempt disable flag
+@
+@ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+@
+#ifdef TX_ENABLE_FPU_SUPPORT
+ MRS r0, CONTROL @ Pickup current CONTROL register
+ BIC r0, r0, #4 @ Clear the FPCA bit
+ MSR CONTROL, r0 @ Setup new CONTROL register
+#endif
+@
+@ /* Enable interrupts */
+@
+ CPSIE i
+@
+@ /* Enter the scheduler for the first time. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ DSB @ Complete all memory accesses
+ ISB @ Flush pipeline
+@
+@ /* Wait here for the PendSV to take place. */
+@
+__tx_wait_here:
+ B __tx_wait_here @ Wait for the PendSV to happen
+@}
+@
+@ /* Generic context switch-out switch-in handler... Note that this handler is
+@ common for both PendSV and SVCall. */
+@
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+@
+@ /* Get current thread value and new thread pointer. */
+@
+__tx_ts_handler:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread exit function to indicate the thread is no longer executing. */
+@
+ CPSID i @ Disable interrupts
+ PUSH {r0, lr} @ Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit @ Call the thread exit function
+ POP {r0, lr} @ Recover LR
+ CPSIE i @ Enable interrupts
+#endif
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ MOV r3, #0 @ Build NULL value
+ LDR r1, [r0] @ Pickup current thread pointer
+@
+@ /* Determine if there is a current thread to finish preserving. */
+@
+ CBZ r1, __tx_ts_new @ If NULL, skip preservation
+@
+@ /* Recover PSP and preserve current thread context. */
+@
+ STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP @ Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} @ Save its remaining registers
+#ifdef TX_ENABLE_FPU_SUPPORT
+ TST LR, #0x10 @ Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ STMDB r12!, {LR} @ Save LR on the stack
+@
+@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+@
+ LDR r5, [r4] @ Pickup current time-slice
+ STR r12, [r1, #8] @ Save the thread stack pointer
+ CBZ r5, __tx_ts_new @ If not active, skip processing
+@
+@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+@
+ STR r5, [r1, #24] @ Save current time-slice
+@
+@ /* Clear the global time-slice. */
+@
+ STR r3, [r4] @ Clear time-slice
+@
+@
+@ /* Executing thread is now completely preserved!!! */
+@
+__tx_ts_new:
+@
+@ /* Now we are looking for a new thread to execute! */
+@
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait @ No, skip to the wait processing
+@
+@ /* Yes, another thread is ready for else, make the current thread the new thread. */
+@
+ STR r1, [r0] @ Setup the current thread pointer to the new thread
+ CPSIE i @ Enable interrupts
+@
+@ /* Increment the thread run count. */
+@
+__tx_ts_restore:
+ LDR r7, [r1, #4] @ Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
+ LDR r5, [r1, #24] @ Pickup thread's current time-slice
+ ADD r7, r7, #1 @ Increment the thread run count
+ STR r7, [r1, #4] @ Store the new run count
+@
+@ /* Setup global time-slice with thread's current time-slice. */
+@
+ STR r5, [r4] @ Setup global time-slice
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+@
+@ /* Call the thread entry function to indicate the thread is executing. */
+@
+ PUSH {r0, r1} @ Save r0/r1
+ BL _tx_execution_thread_enter @ Call the thread execution enter function
+ POP {r0, r1} @ Recover r3
+#endif
+@
+@ /* Restore the thread context and PSP. */
+@
+ LDR r12, [r1, #8] @ Pickup thread's stack pointer
+ LDMIA r12!, {LR} @ Pickup LR
+#ifdef TX_ENABLE_FPU_SUPPORT
+ TST LR, #0x10 @ Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore @ If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} @ Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} @ Recover thread's registers
+ MSR PSP, r12 @ Setup the thread's stack pointer
+@
+@ /* Return to thread. */
+@
+ BX lr @ Return to thread!
+@
+@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+@ are disabled to allow use of WFI for waiting for a thread to arrive. */
+@
+__tx_ts_wait:
+ CPSID i @ Disable interrupts
+ LDR r1, [r2] @ Pickup the next thread to execute pointer
+ STR r1, [r0] @ Store it in the current pointer
+ CBNZ r1, __tx_ts_ready @ If non-NULL, a new thread is ready!
+#ifdef TX_ENABLE_WFI
+ DSB @ Ensure no outstanding memory transactions
+ WFI @ Wait for interrupt
+ ISB @ Ensure pipeline is flushed
+#endif
+ CPSIE i @ Enable interrupts
+ B __tx_ts_wait @ Loop to continue waiting
+@
+@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+@ already in the handler! */
+@
+__tx_ts_ready:
+ MOV r7, #0x08000000 @ Build clear PendSV value
+ MOV r8, #0xE000E000 @ Build base NVIC address
+ STR r7, [r8, #0xD04] @ Clear any PendSV
+@
+@ /* Re-enable interrupts and restore new thread. */
+@
+ CPSIE i @ Enable interrupts
+ B __tx_ts_restore @ Restore the thread
+
+
+#ifdef TX_ENABLE_FPU_SUPPORT
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+@
+@ /* Automatic VPF logic is supported, this function is present only for
+@ backward compatibility purposes and therefore simply returns. */
+@
+ BX LR @ Return to caller
+
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+@
+@ /* Automatic VPF logic is supported, this function is present only for
+@ backward compatibility purposes and therefore simply returns. */
+@
+ BX LR @ Return to caller
+
+
+#endif
+
diff --git a/ports/cortex_m7/gnu/src/tx_thread_stack_build.S b/ports/cortex_m7/gnu/src/tx_thread_stack_build.S
new file mode 100755
index 00000000..19417731
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,148 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_stack_build Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function builds a stack frame on the supplied thread's stack. */
+@/* The stack frame results in a fake interrupt return to the supplied */
+@/* function pointer. */
+@/* */
+@/* INPUT */
+@/* */
+@/* thread_ptr Pointer to thread control blk */
+@/* function_ptr Pointer to return function */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* None */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* _tx_thread_create Create thread service */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+@{
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+@
+@
+@ /* Build a fake interrupt frame. The form of the fake interrupt stack
+@ on the Cortex-M7 should look like the following after it is built:
+@
+@ Stack Top:
+@ LR Interrupted LR (LR at time of PENDSV)
+@ r4 Initial value for r4
+@ r5 Initial value for r5
+@ r6 Initial value for r6
+@ r7 Initial value for r7
+@ r8 Initial value for r8
+@ r9 Initial value for r9
+@ r10 (sl) Initial value for r10 (sl)
+@ r11 Initial value for r11
+@ r0 Initial value for r0 (Hardware stack starts here!!)
+@ r1 Initial value for r1
+@ r2 Initial value for r2
+@ r3 Initial value for r3
+@ r12 Initial value for r12
+@ lr Initial value for lr
+@ pc Initial value for pc
+@ xPSR Initial value for xPSR
+@
+@ Stack Bottom: (higher memory address) */
+@
+ LDR r2, [r0, #16] @ Pickup end of stack area
+ BIC r2, r2, #0x7 @ Align frame
+ SUB r2, r2, #68 @ Subtract frame size
+ LDR r3, =0xFFFFFFFD @ Build initial LR value
+ STR r3, [r2, #0] @ Save on the stack
+@
+@ /* Actually build the stack frame. */
+@
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #4] @ Store initial r4
+ STR r3, [r2, #8] @ Store initial r5
+ STR r3, [r2, #12] @ Store initial r6
+ STR r3, [r2, #16] @ Store initial r7
+ STR r3, [r2, #20] @ Store initial r8
+ STR r3, [r2, #24] @ Store initial r9
+ LDR r3, [r0, #12] @ Pickup stack starting address
+ STR r3, [r2, #28] @ Store initial r10 (sl)
+ MOV r3, #0 @ Build initial register value
+ STR r3, [r2, #32] @ Store initial r11
+@
+@ /* Hardware stack follows. */
+@
+ STR r3, [r2, #36] @ Store initial r0
+ STR r3, [r2, #40] @ Store initial r1
+ STR r3, [r2, #44] @ Store initial r2
+ STR r3, [r2, #48] @ Store initial r3
+ STR r3, [r2, #52] @ Store initial r12
+ MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value
+ STR r3, [r2, #56] @ Store initial lr
+ STR r1, [r2, #60] @ Store initial pc
+ MOV r3, #0x01000000 @ Only T-bit need be set
+ STR r3, [r2, #64] @ Store initial xPSR
+@
+@ /* Setup stack pointer. */
+@ thread_ptr -> tx_thread_stack_ptr = r2;
+@
+ STR r2, [r0, #8] @ Save stack pointer in thread's
+ @ control block
+ BX lr @ Return to caller
+@}
+
+
diff --git a/ports/cortex_m7/gnu/src/tx_thread_system_return.S b/ports/cortex_m7/gnu/src/tx_thread_system_return.S
new file mode 100755
index 00000000..3c609279
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_thread_system_return.S
@@ -0,0 +1,98 @@
+@/**************************************************************************/
+@/* */
+@/* 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"
+@ #include "tx_timer.h" */
+
+
+ .text 32
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_thread_system_return Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function is target processor specific. It is used to transfer */
+@/* control from a thread back to the ThreadX system. Only a */
+@/* minimal context is saved since the compiler assumes temp registers */
+@/* are going to get slicked by a function call anyway. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_thread_schedule Thread scheduling loop */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* ThreadX components */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@/* VOID _tx_thread_system_return(VOID)
+@{ */
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+@
+@ /* Return to real scheduler via PendSV. Note that this routine is often
+@ replaced with in-line assembly in tx_port.h to improved performance. */
+@
+ MOV r0, #0x10000000 @ Load PENDSVSET bit
+ MOV r1, #0xE000E000 @ Load NVIC base
+ STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
+ MRS r0, IPSR @ Pickup IPSR
+ CMP r0, #0 @ Is it a thread returning?
+ BNE _isr_context @ If ISR, skip interrupt enable
+ MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
+ CPSIE i @ Enable interrupts
+ MSR PRIMASK, r1 @ Restore original interrupt posture
+_isr_context:
+ BX lr @ Return to caller
+
+@/* } */
+
diff --git a/ports/cortex_m7/gnu/src/tx_timer_interrupt.S b/ports/cortex_m7/gnu/src/tx_timer_interrupt.S
new file mode 100755
index 00000000..b58b60b7
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,270 @@
+@/**************************************************************************/
+@/* */
+@/* 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 */
+@/** */
+@/** Timer */
+@/** */
+@/**************************************************************************/
+@/**************************************************************************/
+@
+@#define TX_SOURCE_CODE
+@
+@
+@/* Include necessary system files. */
+@
+@#include "tx_api.h"
+@#include "tx_timer.h"
+@#include "tx_thread.h"
+@
+@
+@Define Assembly language external references...
+@
+ .global _tx_timer_time_slice
+ .global _tx_timer_system_clock
+ .global _tx_timer_current_ptr
+ .global _tx_timer_list_start
+ .global _tx_timer_list_end
+ .global _tx_timer_expired_time_slice
+ .global _tx_timer_expired
+ .global _tx_thread_time_slice
+ .global _tx_timer_expiration_process
+@
+@
+ .text
+ .align 4
+ .syntax unified
+@/**************************************************************************/
+@/* */
+@/* FUNCTION RELEASE */
+@/* */
+@/* _tx_timer_interrupt Cortex-M7/GNU */
+@/* 6.0 */
+@/* AUTHOR */
+@/* */
+@/* William E. Lamie, Microsoft Corporation */
+@/* */
+@/* DESCRIPTION */
+@/* */
+@/* This function processes the hardware timer interrupt. This */
+@/* processing includes incrementing the system clock and checking for */
+@/* time slice and/or timer expiration. If either is found, the */
+@/* interrupt context save/restore functions are called along with the */
+@/* expiration functions. */
+@/* */
+@/* INPUT */
+@/* */
+@/* None */
+@/* */
+@/* OUTPUT */
+@/* */
+@/* None */
+@/* */
+@/* CALLS */
+@/* */
+@/* _tx_timer_expiration_process Timer expiration processing */
+@/* _tx_thread_time_slice Time slice interrupted thread */
+@/* */
+@/* CALLED BY */
+@/* */
+@/* interrupt vector */
+@/* */
+@/* RELEASE HISTORY */
+@/* */
+@/* DATE NAME DESCRIPTION */
+@/* */
+@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+@/* */
+@/**************************************************************************/
+@VOID _tx_timer_interrupt(VOID)
+@{
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+@
+@ /* Upon entry to this routine, it is assumed that context save has already
+@ been called, and therefore the compiler scratch registers are available
+@ for use. */
+@
+@ /* Increment the system clock. */
+@ _tx_timer_system_clock++;
+@
+ LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
+ LDR r0, [r1, #0] @ Pickup system clock
+ ADD r0, r0, #1 @ Increment system clock
+ STR r0, [r1, #0] @ Store new system clock
+@
+@ /* Test for time-slice expiration. */
+@ if (_tx_timer_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
+ LDR r2, [r3, #0] @ Pickup time-slice
+ CMP r2, #0 @ Is it non-active?
+ BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
+@
+@ /* Decrement the time_slice. */
+@ _tx_timer_time_slice--;
+@
+ SUB r2, r2, #1 @ Decrement the time-slice
+ STR r2, [r3, #0] @ Store new time-slice value
+@
+@ /* Check for expiration. */
+@ if (__tx_timer_time_slice == 0)
+@
+ CMP r2, #0 @ Has it expired?
+ BNE __tx_timer_no_time_slice @ No, skip expiration processing
+@
+@ /* Set the time-slice expired flag. */
+@ _tx_timer_expired_time_slice = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
+ MOV r0, #1 @ Build expired value
+ STR r0, [r3, #0] @ Set time-slice expiration flag
+@
+@ }
+@
+__tx_timer_no_time_slice:
+@
+@ /* Test for timer expiration. */
+@ if (*_tx_timer_current_ptr)
+@ {
+@
+ LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
+ LDR r0, [r1, #0] @ Pickup current timer
+ LDR r2, [r0, #0] @ Pickup timer list entry
+ CMP r2, #0 @ Is there anything in the list?
+ BEQ __tx_timer_no_timer @ No, just increment the timer
+@
+@ /* Set expiration flag. */
+@ _tx_timer_expired = TX_TRUE;
+@
+ LDR r3, =_tx_timer_expired @ Pickup expiration flag address
+ MOV r2, #1 @ Build expired value
+ STR r2, [r3, #0] @ Set expired flag
+ B __tx_timer_done @ Finished timer processing
+@
+@ }
+@ else
+@ {
+__tx_timer_no_timer:
+@
+@ /* No timer expired, increment the timer pointer. */
+@ _tx_timer_current_ptr++;
+@
+ ADD r0, r0, #4 @ Move to next timer
+@
+@ /* Check for wrap-around. */
+@ if (_tx_timer_current_ptr == _tx_timer_list_end)
+@
+ LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
+ LDR r2, [r3, #0] @ Pickup list end
+ CMP r0, r2 @ Are we at list end?
+ BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
+@
+@ /* Wrap to beginning of list. */
+@ _tx_timer_current_ptr = _tx_timer_list_start;
+@
+ LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
+ LDR r0, [r3, #0] @ Set current pointer to list start
+@
+__tx_timer_skip_wrap:
+@
+ STR r0, [r1, #0] @ Store new current timer pointer
+@ }
+@
+__tx_timer_done:
+@
+@
+@ /* See if anything has expired. */
+@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
+ LDR r2, [r3, #0] @ Pickup time-slice expired flag
+ CMP r2, #0 @ Did a time-slice expire?
+ BNE __tx_something_expired @ If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Did a timer expire?
+ BEQ __tx_timer_nothing_expired @ No, nothing expired
+@
+__tx_something_expired:
+@
+@
+ STMDB sp!, {r0, lr} @ Save the lr register on the stack
+ @ and save r0 just to keep 8-byte alignment
+@
+@ /* Did a timer expire? */
+@ if (_tx_timer_expired)
+@ {
+@
+ LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
+ LDR r0, [r1, #0] @ Pickup timer expired flag
+ CMP r0, #0 @ Check for timer expiration
+ BEQ __tx_timer_dont_activate @ If not set, skip timer activation
+@
+@ /* Process timer expiration. */
+@ _tx_timer_expiration_process();
+@
+ BL _tx_timer_expiration_process @ Call the timer expiration handling routine
+@
+@ }
+__tx_timer_dont_activate:
+@
+@ /* Did time slice expire? */
+@ if (_tx_timer_expired_time_slice)
+@ {
+@
+ LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
+ LDR r2, [r3, #0] @ Pickup the actual flag
+ CMP r2, #0 @ See if the flag is set
+ BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
+@
+@ /* Time slice interrupted thread. */
+@ _tx_thread_time_slice();
+@
+ BL _tx_thread_time_slice @ Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
+ LDR r1, [r0] @ Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
+ LDR r1, [r0] @ Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
+ LDR r3, [r2] @ Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 @ Build address of control register
+ LDR r2, =0x10000000 @ Build value for PendSV bit
+ CMP r1, r3 @ Are they the same?
+ BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
+ STR r2, [r0] @ Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+@
+@ }
+@
+__tx_timer_not_ts_expiration:
+@
+ LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for
+ @ the 8-byte stack alignment
+@
+@ }
+@
+__tx_timer_nothing_expired:
+
+ DSB @ Complete all memory access
+ BX lr @ Return to caller
+@
+@}
+
+
diff --git a/ports/cortex_m7/gnu/src/tx_vector_table_sample.S b/ports/cortex_m7/gnu/src/tx_vector_table_sample.S
new file mode 100644
index 00000000..cf0db974
--- /dev/null
+++ b/ports/cortex_m7/gnu/src/tx_vector_table_sample.S
@@ -0,0 +1,84 @@
+
+
+ .global reset_handler
+
+ .global __tx_NMIHandler
+ .global __tx_BadHandler
+ .global __tx_SVCallHandler
+ .global __tx_DBGHandler
+ .global __tx_PendSVHandler
+ .global __tx_SysTickHandler
+ .global __tx_BadHandler
+
+
+ .syntax unified
+ .section .vectors, "ax"
+ .code 16
+ .align 0
+ .global _vectors
+
+_vectors:
+ .word __stack_end__
+ .word reset_handler
+ .word __tx_NMIHandler
+ .word __tx_HardfaultHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
+ .word __tx_DBGHandler
+ .word 0 // Reserved
+ .word __tx_PendSVHandler
+ .word __tx_SysTickHandler // Used by Threadx timer functionality
+ .word __tx_BadHandler // Populate with user Interrupt handler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+
+
+
+ .section .init, "ax"
+ .thumb_func
+reset_handler:
+
+// low level hardware config, such as PLL setup goes here
+
+ b _start
+
+
+
diff --git a/ports/linux/gnu/CMakeLists.txt b/ports/linux/gnu/CMakeLists.txt
new file mode 100644
index 00000000..8d7ee023
--- /dev/null
+++ b/ports/linux/gnu/CMakeLists.txt
@@ -0,0 +1,25 @@
+# For this port, we need to tell the common subdirectory to not include these files
+set(TX_SRC_OVERRIDES
+ "tx_thread_delete.c"
+ "tx_thread_reset.c"
+CACHE STRING "tx source overrides")
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
+
diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h
new file mode 100644
index 00000000..05677bd9
--- /dev/null
+++ b/ports/linux/gnu/inc/tx_port.h
@@ -0,0 +1,575 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h Linux/GNU */
+/* 6.0 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+#define TX_MAX_PRIORITIES 32
+/* #define TX_MISRA_ENABLE */
+
+
+/* #define TX_INLINE_INITIALIZATION */
+
+/* #define TX_NOT_INTERRUPTABLE */
+/* #define TX_TIMER_PROCESS_IN_ISR */
+/* #define TX_REACTIVATE_INLINE */
+/* #define TX_DISABLE_STACK_FILLING */
+/* #define TX_ENABLE_STACK_CHECKING */
+/* #define TX_DISABLE_PREEMPTION_THRESHOLD */
+/* #define TX_DISABLE_REDUNDANT_CLEARING */
+/* #define TX_DISABLE_NOTIFY_CALLBACKS */
+/* #define TX_INLINE_THREAD_RESUME_SUSPEND */
+/* #define TX_ENABLE_EVENT_TRACE */
+
+
+/* For MISRA, define enable performance info. Also, for MISRA TX_DISABLE_NOTIFY_CALLBACKS should not be defined. */
+
+
+/* #define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+#define TX_MUTEX_ENABLE_PERFORMANCE_INFO
+#define TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+#define TX_THREAD_ENABLE_PERFORMANCE_INFO
+#define TX_TIMER_ENABLE_PERFORMANCE_INFO */
+
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#ifndef __USE_POSIX199309
+#define __USE_POSIX199309
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#undef __USE_POSIX199309
+#else /* __USE_POSIX199309 */
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#endif /* __USE_POSIX199309 */
+
+
+/* Define ThreadX basic types for this port. */
+
+typedef void VOID;
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+#if __x86_64__
+typedef int LONG;
+typedef unsigned int ULONG;
+#else /* __x86_64__ */
+typedef long LONG;
+typedef unsigned long ULONG;
+#endif /* __x86_64__ */
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef uint64_t ULONG64;
+
+
+/* Override the alignment type to use 64-bit alignment and storage for pointers. */
+
+#if __x86_64__
+#define ALIGN_TYPE_DEFINED
+typedef unsigned long long ALIGN_TYPE;
+
+/* Override the free block marker for byte pools to be a 64-bit constant. */
+
+#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE)
+#endif
+
+/* Define automated coverage test extensions... These are required for the
+ ThreadX regression test. */
+
+typedef unsigned int TEST_FLAG;
+extern TEST_FLAG threadx_byte_allocate_loop_test;
+extern TEST_FLAG threadx_byte_release_loop_test;
+extern TEST_FLAG threadx_mutex_suspension_put_test;
+extern TEST_FLAG threadx_mutex_suspension_priority_test;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+extern TEST_FLAG threadx_delete_timer_thread;
+#endif
+
+extern void abort_and_resume_byte_allocating_thread(void);
+extern void abort_all_threads_suspended_on_mutex(void);
+extern void suspend_lowest_priority(void);
+#ifndef TX_TIMER_PROCESS_IN_ISR
+extern void delete_timer_thread(void);
+#endif
+extern TEST_FLAG test_stack_analyze_flag;
+extern TEST_FLAG test_initialize_flag;
+extern TEST_FLAG test_forced_mutex_timeout;
+
+
+#ifdef TX_REGRESSION_TEST
+
+/* Define extension macros for automated coverage tests. */
+
+
+#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \
+ { \
+ pool_ptr -> tx_byte_pool_owner = TX_NULL; \
+ threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \
+ }
+
+#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \
+ { \
+ threadx_byte_release_loop_test = ((TEST_FLAG) 0); \
+ abort_and_resume_byte_allocating_thread(); \
+ }
+
+#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \
+ { \
+ threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \
+ abort_all_threads_suspended_on_mutex(); \
+ }
+
+
+#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \
+ { \
+ test_forced_mutex_timeout = ((TEST_FLAG) 0); \
+ _tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \
+ }
+
+
+#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \
+ { \
+ threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \
+ suspend_lowest_priority(); \
+ }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \
+ { \
+ threadx_delete_timer_thread = ((TEST_FLAG) 0); \
+ delete_timer_thread(); \
+ (a) = ((UINT) 1); \
+ }
+
+#endif
+
+#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \
+ { \
+ thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \
+ test_stack_analyze_flag = ((TEST_FLAG) 0); \
+ } \
+ else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \
+ { \
+ stack_ptr = thread_ptr -> tx_thread_stack_start; \
+ test_stack_analyze_flag = ((TEST_FLAG) 0); \
+ } \
+ else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \
+ { \
+ *stack_ptr = TX_STACK_FILL; \
+ test_stack_analyze_flag = ((TEST_FLAG) 0); \
+ } \
+ else \
+ { \
+ test_stack_analyze_flag = ((TEST_FLAG) 0); \
+ }
+
+#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \
+ { \
+ test_initialize_flag = ((TEST_FLAG) 0); \
+ return; \
+ }
+
+#endif
+
+
+
+/* Add Linux debug insert prototype. */
+
+void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long line);
+
+#ifndef TX_LINUX_DEBUG_ENABLE
+
+/* If Linux debug is not enabled, turn logging into white-space. */
+
+#define _tx_linux_debug_entry_insert(a, b, c)
+
+#endif
+
+
+
+/* Define the TX_MEMSET macro to remove library reference. */
+
+#ifndef TX_MISRA_ENABLE
+#define TX_MEMSET(a,b,c) { \
+ UCHAR *ptr; \
+ UCHAR value; \
+ UINT i, size; \
+ ptr = (UCHAR *) ((VOID *) a); \
+ value = (UCHAR) b; \
+ size = (UINT) c; \
+ for (i = 0; i < size; i++) \
+ { \
+ *ptr++ = value; \
+ } \
+ }
+#endif
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 400 /* Default timer thread stack size - Not used in Linux port! */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec));
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#endif
+
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port-specific trace extension to pickup the Windows timer. */
+
+#define TX_TRACE_PORT_EXTENSION clock_gettime(CLOCK_REALTIME, &_tx_linux_time_stamp);
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* Define the Linux-specific initialization code that is expanded in the generic source. */
+
+void _tx_initialize_start_interrupts(void);
+
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION _tx_initialize_start_interrupts();
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0 pthread_t tx_thread_linux_thread_id; \
+ sem_t tx_thread_linux_thread_run_semaphore; \
+ UINT tx_thread_linux_suspension_type; \
+ UINT tx_thread_linux_int_disabled_flag;
+
+#define TX_THREAD_EXTENSION_1 VOID *tx_thread_extension_ptr;
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+struct TX_THREAD_STRUCT;
+
+/* Define post completion processing for tx_thread_delete, so that the Linux thread resources are properly removed. */
+
+void _tx_thread_delete_port_completion(struct TX_THREAD_STRUCT *thread_ptr, UINT tx_saved_posture);
+#define TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) _tx_thread_delete_port_completion(thread_ptr, tx_saved_posture);
+
+/* Define post completion processing for tx_thread_reset, so that the Linux thread resources are properly removed. */
+
+void _tx_thread_reset_port_completion(struct TX_THREAD_STRUCT *thread_ptr, UINT tx_saved_posture);
+#define TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) _tx_thread_reset_port_completion(thread_ptr, tx_saved_posture);
+
+#if __x86_64__
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout
+ can figure out what thread timeout to process. */
+
+#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_extension_ptr;
+
+
+/* Define the thread timeout setup logic in _tx_thread_create. */
+
+#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
+ (t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \
+ (t) -> tx_thread_timer.tx_timer_internal_extension_ptr = (VOID *) (t);
+
+
+/* Define the thread timeout pointer setup in _tx_thread_timeout. */
+
+#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr;
+#endif /* __x86_64__ */
+
+
+/* Define ThreadX interrupt lockout and restore macros for protection on
+ access of critical kernel information. The restore interrupt macro must
+ restore the interrupt posture of the running thread prior to the value
+ present prior to the disable macro. In most cases, the save area macro
+ is used to define a local function save area for the disable and restore
+ macros. */
+
+UINT _tx_thread_interrupt_disable(void);
+VOID _tx_thread_interrupt_restore(UINT previous_posture);
+
+#define TX_INTERRUPT_SAVE_AREA UINT tx_saved_posture;
+
+#ifndef TX_LINUX_DEBUG_ENABLE
+#define TX_DISABLE tx_saved_posture = _tx_thread_interrupt_disable();
+#define TX_RESTORE _tx_thread_interrupt_restore(tx_saved_posture);
+#else
+#define TX_DISABLE _tx_linux_debug_entry_insert("DISABLE", __FILE__, __LINE__); \
+ tx_saved_posture = _tx_thread_interrupt_disable();
+
+#define TX_RESTORE _tx_linux_debug_entry_insert("RESTORE", __FILE__, __LINE__); \
+ _tx_thread_interrupt_restore(tx_saved_posture);
+#endif /* TX_LINUX_DEBUG_ENABLE */
+#define tx_linux_mutex_lock(p) pthread_mutex_lock(&p)
+#define tx_linux_mutex_unlock(p) pthread_mutex_unlock(&p)
+#define tx_linux_mutex_recursive_unlock(p) {\
+ int _recursive_count = tx_linux_mutex_recursive_count;\
+ while(_recursive_count)\
+ {\
+ pthread_mutex_unlock(&p);\
+ _recursive_count--;\
+ }\
+ }
+#define tx_linux_mutex_recursive_count _tx_linux_mutex.__data.__count
+#define tx_linux_sem_post(p) tx_linux_mutex_lock(_tx_linux_mutex);\
+ sem_post(p);\
+ tx_linux_mutex_unlock(_tx_linux_mutex)
+#define tx_linux_sem_post_nolock(p) sem_post(p)
+#define tx_linux_sem_wait(p) sem_wait(p)
+
+
+/* Define the interrupt lockout macros for each ThreadX object. */
+
+#define TX_BLOCK_POOL_DISABLE TX_DISABLE
+#define TX_BYTE_POOL_DISABLE TX_DISABLE
+#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
+#define TX_MUTEX_DISABLE TX_DISABLE
+#define TX_QUEUE_DISABLE TX_DISABLE
+#define TX_SEMAPHORE_DISABLE TX_DISABLE
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation * ThreadX Linux/gcc Version 6.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+/* Define externals for the Linux port of ThreadX. */
+
+extern pthread_mutex_t _tx_linux_mutex;
+extern sem_t _tx_linux_semaphore;
+extern sem_t _tx_linux_semaphore_no_idle;
+extern ULONG _tx_linux_global_int_disabled_flag;
+extern struct timespec _tx_linux_time_stamp;
+extern __thread int _tx_linux_threadx_thread;
+
+/* Define functions for linux thread. */
+void _tx_linux_thread_suspend(pthread_t thread_id);
+void _tx_linux_thread_resume(pthread_t thread_id);
+void _tx_linux_thread_init();
+
+#ifndef TX_LINUX_MEMORY_SIZE
+#define TX_LINUX_MEMORY_SIZE 64000
+#endif
+
+#define TX_TIMER_TICKS_PER_SECOND 100UL
+
+/* Define priorities of pthreads. */
+
+#define TX_LINUX_PRIORITY_SCHEDULE (3)
+#define TX_LINUX_PRIORITY_ISR (2)
+#define TX_LINUX_PRIORITY_USER_THREAD (1)
+
+#endif
+
diff --git a/ports/linux/gnu/src/tx_initialize_low_level_sample.c b/ports/linux/gnu/src/tx_initialize_low_level_sample.c
new file mode 100644
index 00000000..a4bc0c18
--- /dev/null
+++ b/ports/linux/gnu/src/tx_initialize_low_level_sample.c
@@ -0,0 +1,443 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/sysinfo.h>
+
+
+/* Define various Linux objects used by the ThreadX port. */
+
+pthread_mutex_t _tx_linux_mutex;
+sem_t _tx_linux_semaphore;
+sem_t _tx_linux_semaphore_no_idle;
+ULONG _tx_linux_global_int_disabled_flag;
+struct timespec _tx_linux_time_stamp;
+__thread int _tx_linux_threadx_thread = 0;
+
+/* Define signals for linux thread. */
+#define SUSPEND_SIG SIGUSR1
+#define RESUME_SIG SIGUSR2
+
+static sigset_t _tx_linux_thread_wait_mask;
+static __thread int _tx_linux_thread_suspended;
+static sem_t _tx_linux_thread_timer_wait;
+static sem_t _tx_linux_thread_other_wait;
+
+/* Define simulated timer interrupt. This is done inside a thread, which is
+ how other interrupts may be defined as well. See code below for an
+ example. */
+
+pthread_t _tx_linux_timer_id;
+sem_t _tx_linux_timer_semaphore;
+sem_t _tx_linux_isr_semaphore;
+void *_tx_linux_timer_interrupt(void *p);
+
+
+#ifdef TX_LINUX_DEBUG_ENABLE
+
+extern ULONG _tx_thread_system_state;
+extern UINT _tx_thread_preempt_disable;
+extern TX_THREAD *_tx_thread_current_ptr;
+extern TX_THREAD *_tx_thread_execute_ptr;
+
+
+/* Define debug log in order to debug Linux issues with this port. */
+
+typedef struct TX_LINUX_DEBUG_ENTRY_STRUCT
+{
+ char *tx_linux_debug_entry_action;
+ struct timespec tx_linux_debug_entry_timestamp;
+ char *tx_linux_debug_entry_file;
+ unsigned long tx_linux_debug_entry_line;
+ pthread_mutex_t tx_linux_debug_entry_mutex;
+ unsigned long tx_linux_debug_entry_int_disabled_flag;
+ ULONG tx_linux_debug_entry_system_state;
+ UINT tx_linux_debug_entry_preempt_disable;
+ TX_THREAD *tx_linux_debug_entry_current_thread;
+ TX_THREAD *tx_linux_debug_entry_execute_thread;
+} TX_LINUX_DEBUG_ENTRY;
+
+
+/* Define the maximum size of the Linux debug array. */
+
+#ifndef TX_LINUX_DEBUG_EVENT_SIZE
+#define TX_LINUX_DEBUG_EVENT_SIZE 400
+#endif
+
+
+/* Define the circular array of Linux debug entries. */
+
+TX_LINUX_DEBUG_ENTRY _tx_linux_debug_entry_array[TX_LINUX_DEBUG_EVENT_SIZE];
+
+
+/* Define the Linux debug index. */
+
+unsigned long _tx_linux_debug_entry_index = 0;
+
+
+/* Now define the debug entry function. */
+void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long line)
+{
+
+pthread_mutex_t temp_copy;
+
+ /* Save the current critical section value. */
+ temp_copy = _tx_linux_mutex;
+
+ /* Lock mutex. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Get the time stamp. */
+ clock_gettime(CLOCK_REALTIME, &_tx_linux_time_stamp);
+
+ /* Setup the debub entry. */
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_action = action;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_timestamp = _tx_linux_time_stamp;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_file = file;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_line = line;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_mutex = temp_copy;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_int_disabled_flag = _tx_linux_global_int_disabled_flag;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_system_state = _tx_thread_system_state;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_preempt_disable = _tx_thread_preempt_disable;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_current_thread = _tx_thread_current_ptr;
+ _tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_execute_thread = _tx_thread_execute_ptr;
+
+ /* Now move to the next entry. */
+ _tx_linux_debug_entry_index++;
+
+ /* Determine if we need to wrap the list. */
+ if (_tx_linux_debug_entry_index >= TX_LINUX_DEBUG_EVENT_SIZE)
+ {
+
+ /* Yes, wrap the list! */
+ _tx_linux_debug_entry_index = 0;
+ }
+
+ /* Unlock mutex. */
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+}
+
+#endif
+
+
+/* Define the ThreadX timer interrupt handler. */
+
+void _tx_timer_interrupt(void);
+
+
+/* Define other external function references. */
+
+VOID _tx_initialize_low_level(VOID);
+VOID _tx_thread_context_save(VOID);
+VOID _tx_thread_context_restore(VOID);
+
+
+/* Define other external variable references. */
+
+extern VOID *_tx_initialize_unused_memory;
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for any low-level processor */
+/* initialization, including setting up interrupt vectors, setting */
+/* up a periodic timer interrupt source, saving the system stack */
+/* pointer for use in ISR processing later, and finding the first */
+/* available RAM memory address for tx_application_define. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* sched_setaffinity */
+/* getpid */
+/* _tx_linux_thread_init */
+/* pthread_setschedparam */
+/* pthread_mutexattr_init */
+/* pthread_mutex_init */
+/* _tx_linux_thread_suspend */
+/* sem_init */
+/* pthread_create */
+/* printf */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_initialize_low_level(VOID)
+{
+struct sched_param sp;
+pthread_mutexattr_t attr;
+
+#ifdef TX_LINUX_MULTI_CORE
+cpu_set_t mask;
+
+ sched_getaffinity(getpid(), sizeof(mask), &mask);
+ if (CPU_COUNT(&mask) > 1)
+ {
+
+ srand((ULONG)pthread_self());
+
+ /* Limit this ThreadX simulation on Linux to a single core. */
+ CPU_ZERO(&mask);
+ CPU_SET(rand() % get_nprocs(), &mask);
+ if (sched_setaffinity(getpid(), sizeof(mask), &mask) != 0)
+ {
+
+ /* Error restricting the process to one core. */
+ printf("ThreadX Linux error restricting the process to one core!\n");
+ while(1)
+ {
+ }
+ }
+ }
+#endif
+
+ /* Pickup the first available memory address. */
+
+ /* Save the first available memory address. */
+ _tx_initialize_unused_memory = malloc(TX_LINUX_MEMORY_SIZE);
+
+ /* Init Linux thread. */
+ _tx_linux_thread_init();
+
+ /* Set priority and schedual of main thread. */
+ sp.sched_priority = TX_LINUX_PRIORITY_SCHEDULE;
+ pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp);
+
+ /* Create the system critical section. This is used by the
+ scheduler thread (which is the main thread) to block all
+ other stuff out. */
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&_tx_linux_mutex, &attr);
+ sem_init(&_tx_linux_semaphore, 0, 0);
+#ifdef TX_LINUX_NO_IDLE_ENABLE
+ sem_init(&_tx_linux_semaphore_no_idle, 0, 0);
+#endif /* TX_LINUX_NO_IDLE_ENABLE */
+
+ /* Initialize the global interrupt disabled flag. */
+ _tx_linux_global_int_disabled_flag = TX_FALSE;
+
+ /* Create semaphore for timer thread. */
+ sem_init(&_tx_linux_timer_semaphore, 0, 0);
+
+ /* Create semaphore for ISR thread. */
+ sem_init(&_tx_linux_isr_semaphore, 0, 0);
+
+ /* Setup periodic timer interrupt. */
+ if(pthread_create(&_tx_linux_timer_id, NULL, _tx_linux_timer_interrupt, NULL))
+ {
+
+ /* Error creating the timer interrupt. */
+ printf("ThreadX Linux error creating timer interrupt thread!\n");
+ while(1)
+ {
+ }
+ }
+
+ /* Otherwise, we have a good thread create. Now set the priority to
+ a level lower than the system thread but higher than the application
+ threads. */
+ sp.sched_priority = TX_LINUX_PRIORITY_ISR;
+ pthread_setschedparam(_tx_linux_timer_id, SCHED_FIFO, &sp);
+
+ /* Done, return to caller. */
+}
+
+
+/* This routine is called after initialization is complete in order to start
+ all interrupt threads. Interrupt threads in addition to the timer may
+ be added to this routine as well. */
+
+void _tx_initialize_start_interrupts(void)
+{
+
+ /* Kick the timer thread off to generate the ThreadX periodic interrupt
+ source. */
+ tx_linux_sem_post(&_tx_linux_timer_semaphore);
+}
+
+
+/* Define the ThreadX system timer interrupt. Other interrupts may be simulated
+ in a similar way. */
+
+void *_tx_linux_timer_interrupt(void *p)
+{
+struct timespec ts;
+long timer_periodic_nsec;
+int err;
+
+ /* Calculate periodic timer. */
+ timer_periodic_nsec = 1000000000 / TX_TIMER_TICKS_PER_SECOND;
+ nice(10);
+
+ /* Wait startup semaphore. */
+ tx_linux_sem_wait(&_tx_linux_timer_semaphore);
+
+ while(1)
+ {
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_nsec += timer_periodic_nsec;
+ if (ts.tv_nsec > 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ts.tv_sec++;
+ }
+ do
+ {
+ if (sem_timedwait(&_tx_linux_timer_semaphore, &ts) == 0)
+ {
+ break;
+ }
+ err = errno;
+ } while (err != ETIMEDOUT);
+
+ /* Call ThreadX context save for interrupt preparation. */
+ _tx_thread_context_save();
+
+ /* Call trace ISR enter event insert. */
+ _tx_trace_isr_enter_insert(0);
+
+ /* Call the ThreadX system timer interrupt processing. */
+ _tx_timer_interrupt();
+
+ /* Call trace ISR exit event insert. */
+ _tx_trace_isr_exit_insert(0);
+
+ /* Call ThreadX context restore for interrupt completion. */
+ _tx_thread_context_restore();
+
+#ifdef TX_LINUX_NO_IDLE_ENABLE
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Make sure semaphore is 0. */
+ while(!sem_trywait(&_tx_linux_semaphore_no_idle));
+
+ /* Wakeup the system thread by setting the system semaphore. */
+ tx_linux_sem_post(&_tx_linux_semaphore_no_idle);
+
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+#endif /* TX_LINUX_NO_IDLE_ENABLE */
+ }
+}
+
+/* Define functions for linux thread. */
+void _tx_linux_thread_resume_handler(int sig)
+{
+}
+
+void _tx_linux_thread_suspend_handler(int sig)
+{
+ if(pthread_equal(pthread_self(), _tx_linux_timer_id))
+ tx_linux_sem_post_nolock(&_tx_linux_thread_timer_wait);
+ else
+ tx_linux_sem_post_nolock(&_tx_linux_thread_other_wait);
+
+ if(_tx_linux_thread_suspended)
+ return;
+
+ _tx_linux_thread_suspended = 1;
+ sigsuspend(&_tx_linux_thread_wait_mask);
+ _tx_linux_thread_suspended = 0;
+}
+
+void _tx_linux_thread_suspend(pthread_t thread_id)
+{
+
+ /* Send signal. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+ pthread_kill(thread_id, SUSPEND_SIG);
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+
+ /* Wait until signal is received. */
+ if(pthread_equal(thread_id, _tx_linux_timer_id))
+ tx_linux_sem_wait(&_tx_linux_thread_timer_wait);
+ else
+ tx_linux_sem_wait(&_tx_linux_thread_other_wait);
+}
+
+void _tx_linux_thread_resume(pthread_t thread_id)
+{
+
+ /* Send signal. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+ pthread_kill(thread_id, RESUME_SIG);
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+}
+
+void _tx_linux_thread_init()
+{
+struct sigaction sa;
+
+ /* Create semaphore for linux thread. */
+ sem_init(&_tx_linux_thread_timer_wait, 0, 0);
+ sem_init(&_tx_linux_thread_other_wait, 0, 0);
+
+ sigfillset(&_tx_linux_thread_wait_mask);
+ sigdelset(&_tx_linux_thread_wait_mask, RESUME_SIG);
+
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = _tx_linux_thread_resume_handler;
+ sigaction(RESUME_SIG, &sa, NULL);
+
+ sa.sa_handler = _tx_linux_thread_suspend_handler;
+ sigaction(SUSPEND_SIG, &sa, NULL);
+}
+
+
diff --git a/ports/linux/gnu/src/tx_thread_context_restore.c b/ports/linux/gnu/src/tx_thread_context_restore.c
new file mode 100644
index 00000000..69a16b18
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_context_restore.c
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+
+extern sem_t _tx_linux_isr_semaphore;
+UINT _tx_linux_timer_waiting = 0;
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function restores the interrupt context if it is processing a */
+/* nested interrupt. If not, it returns to the interrupt thread if no */
+/* preemption is necessary. Otherwise, if preemption is necessary or */
+/* if no thread was running, the function returns to the scheduler. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_linux_debug_entry_insert */
+/* tx_linux_mutex_lock */
+/* sem_trywait */
+/* tx_linux_sem_post */
+/* tx_linux_sem_wait */
+/* _tx_linux_thread_resume */
+/* tx_linux_mutex_recursive_unlock */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_context_restore(VOID)
+{
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__);
+
+ /* Lock mutex to ensure other threads are not playing with
+ the core ThreadX data structures. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Decrement the nested interrupt count. */
+ _tx_thread_system_state--;
+
+ /* Determine if this is the first nested interrupt and if a ThreadX
+ application thread was running at the time. */
+ if ((!_tx_thread_system_state) && (_tx_thread_current_ptr))
+ {
+
+ /* Yes, this is the first and last interrupt processed. */
+
+ /* Check to see if preemption is required. */
+ if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr))
+ {
+
+ /* Preempt the running application thread. We don't need to suspend the
+ application thread since that is done in the context save processing. */
+
+ /* Indicate that this thread was suspended asynchronously. */
+ _tx_thread_current_ptr -> tx_thread_linux_suspension_type = 1;
+
+ /* Save the remaining time-slice and disable it. */
+ if (_tx_timer_time_slice)
+ {
+
+ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
+ _tx_timer_time_slice = 0;
+ }
+
+ /* Clear the current thread pointer. */
+ _tx_thread_current_ptr = TX_NULL;
+
+ /* Make sure semaphore is 0. */
+ while(!sem_trywait(&_tx_linux_semaphore));
+
+ /* Indicate it is in timer ISR. */
+ _tx_linux_timer_waiting = 1;
+
+ /* Wakeup the system thread by setting the system semaphore. */
+ tx_linux_sem_post(&_tx_linux_semaphore);
+
+ if(_tx_thread_execute_ptr)
+ {
+ if(_tx_thread_execute_ptr -> tx_thread_linux_suspension_type == 0)
+ {
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+
+ /* Wait until TX_THREAD start running. */
+ tx_linux_sem_wait(&_tx_linux_isr_semaphore);
+
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Make sure semaphore is 0. */
+ while(!sem_trywait(&_tx_linux_isr_semaphore));
+ }
+ }
+
+ /* Indicate it is not in timer ISR. */
+ _tx_linux_timer_waiting = 0;
+ }
+ else
+ {
+
+ /* Since preemption is not required, resume the interrupted thread. */
+ _tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
+ }
+ }
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+}
+
diff --git a/ports/linux/gnu/src/tx_thread_context_save.c b/ports/linux/gnu/src/tx_thread_context_save.c
new file mode 100644
index 00000000..90ff05f1
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_context_save.c
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves the context of an executing thread in the */
+/* beginning of interrupt processing. The function also ensures that */
+/* the system stack is used upon return to the calling ISR. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_linux_debug_entry_insert */
+/* tx_linux_mutex_lock */
+/* _tx_linux_thread_suspend */
+/* tx_linux_mutex_unlock */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_context_save(VOID)
+{
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("CONTEXT_SAVE", __FILE__, __LINE__);
+
+ /* Lock mutex to ensure other threads are not playing with
+ the core ThreadX data structures. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* If an application thread is running, suspend it to simulate preemption. */
+ if ((_tx_thread_current_ptr) && (_tx_thread_system_state == 0))
+ {
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("CONTEXT_SAVE-suspend_thread", __FILE__, __LINE__);
+
+ /* Yes, this is the first interrupt and an application thread is running...
+ suspend it! */
+ _tx_linux_thread_suspend(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
+
+ /* Indicate that this thread was suspended asynchronously. */
+ _tx_thread_current_ptr -> tx_thread_linux_suspension_type = 1;
+ }
+
+ /* Increment the nested interrupt condition. */
+ _tx_thread_system_state++;
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+}
+
diff --git a/ports/linux/gnu/src/tx_thread_interrupt_control.c b/ports/linux/gnu/src/tx_thread_interrupt_control.c
new file mode 100644
index 00000000..f1e71d2c
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_interrupt_control.c
@@ -0,0 +1,183 @@
+/**************************************************************************/
+/* */
+/* 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"
+
+/* Define small routines used for the TX_DISABLE/TX_RESTORE macros. */
+
+UINT _tx_thread_interrupt_disable(void)
+{
+
+UINT previous_value;
+
+
+ previous_value = _tx_thread_interrupt_control(TX_INT_DISABLE);
+ return(previous_value);
+}
+
+
+VOID _tx_thread_interrupt_restore(UINT previous_posture)
+{
+
+ previous_posture = _tx_thread_interrupt_control(previous_posture);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for changing the interrupt lockout */
+/* posture of the system. */
+/* */
+/* INPUT */
+/* */
+/* new_posture New interrupt lockout posture */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* tx_linux_mutex_lock */
+/* pthread_self */
+/* pthread_getschedparam */
+/* tx_linux_mutex_recursive_unlock */
+/* pthread_exit */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_thread_interrupt_control(UINT new_posture)
+{
+
+UINT old_posture;
+TX_THREAD *thread_ptr;
+pthread_t thread_id;
+int exit_code = 0;
+
+
+ /* Lock Linux mutex. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Pickup the id of the current thread. */
+ thread_id = pthread_self();
+
+ /* Pickup the current thread pointer. */
+ thread_ptr = _tx_thread_current_ptr;
+
+ /* Determine if this is a thread and it does not
+ match the current thread pointer. */
+ if ((_tx_linux_threadx_thread) &&
+ ((!thread_ptr) || (!pthread_equal(thread_ptr -> tx_thread_linux_thread_id, thread_id))))
+ {
+
+ /* This indicates the Linux thread was actually terminated by ThreadX is only
+ being allowed to run in order to cleanup its resources. */
+ /* Unlock linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+ pthread_exit((void *)&exit_code);
+ }
+
+ /* Determine the current interrupt lockout condition. */
+ if (tx_linux_mutex_recursive_count == 1)
+ {
+
+ /* Interrupts are enabled. */
+ old_posture = TX_INT_ENABLE;
+ }
+ else
+ {
+
+ /* Interrupts are disabled. */
+ old_posture = TX_INT_DISABLE;
+ }
+
+ /* First, determine if this call is from a non-thread. */
+ if (_tx_thread_system_state)
+ {
+
+ /* Determine how to apply the new posture. */
+ if (new_posture == TX_INT_ENABLE)
+ {
+
+ /* Clear the disabled flag. */
+ _tx_linux_global_int_disabled_flag = TX_FALSE;
+
+ /* Determine if the critical section is locked. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+ }
+ else if (new_posture == TX_INT_DISABLE)
+ {
+
+ /* Set the disabled flag. */
+ _tx_linux_global_int_disabled_flag = TX_TRUE;
+ }
+ }
+ else if (thread_ptr)
+ {
+
+ /* Determine how to apply the new posture. */
+ if (new_posture == TX_INT_ENABLE)
+ {
+
+ /* Clear the disabled flag. */
+ _tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag = TX_FALSE;
+
+ /* Determine if the critical section is locked. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+ }
+ else if (new_posture == TX_INT_DISABLE)
+ {
+
+ /* Set the disabled flag. */
+ _tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag = TX_TRUE;
+ }
+ }
+
+ /* Return the previous interrupt disable posture. */
+ return(old_posture);
+}
+
diff --git a/ports/linux/gnu/src/tx_thread_schedule.c b/ports/linux/gnu/src/tx_thread_schedule.c
new file mode 100644
index 00000000..2bc91228
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_schedule.c
@@ -0,0 +1,264 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+#include <stdio.h>
+#include <errno.h>
+
+extern sem_t _tx_linux_timer_semaphore;
+extern sem_t _tx_linux_isr_semaphore;
+extern UINT _tx_linux_timer_waiting;
+extern pthread_t _tx_linux_timer_id;
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function waits for a thread control block pointer to appear in */
+/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+/* in the variable, the corresponding thread is resumed. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_linux_mutex_lock */
+/* tx_linux_mutex_unlock */
+/* _tx_linux_debug_entry_insert */
+/* _tx_linux_thread_resume */
+/* tx_linux_sem_post */
+/* sem_trywait */
+/* tx_linux_sem_wait */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_schedule(VOID)
+{
+struct timespec ts;
+
+ /* Set timer. */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 200000;
+
+ /* Loop forever. */
+ while(1)
+ {
+
+ /* Wait for a thread to execute and all ISRs to complete. */
+ while(1)
+ {
+
+ /* Lock Linux mutex. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Determine if there is a thread ready to execute AND all ISRs
+ are complete. */
+ if ((_tx_thread_execute_ptr != TX_NULL) && (_tx_thread_system_state == 0))
+ {
+
+ /* Get out of this loop and schedule the thread! */
+ break;
+ }
+ else
+ {
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+
+ /* Don't waste all the processor time here in the master thread... */
+#ifdef TX_LINUX_NO_IDLE_ENABLE
+ while(!sem_trywait(&_tx_linux_timer_semaphore));
+ tx_linux_sem_post(&_tx_linux_timer_semaphore);
+ /*nanosleep(&ts, &ts);*/
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_nsec += 200000;
+ if (ts.tv_nsec > 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ts.tv_sec++;
+ }
+ sem_timedwait(&_tx_linux_semaphore_no_idle, &ts);
+#else
+ nanosleep(&ts, &ts);
+#endif /* TX_LINUX_NO_IDLE_ENABLE */
+ }
+ }
+
+ /* Yes! We have a thread to execute. Note that the critical section is already
+ active from the scheduling loop above. */
+
+ /* Setup the current thread pointer. */
+ _tx_thread_current_ptr = _tx_thread_execute_ptr;
+
+ /* Increment the run count for this thread. */
+ _tx_thread_current_ptr -> tx_thread_run_count++;
+
+ /* Setup time-slice, if present. */
+ _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
+
+ /* Determine how the thread was suspended. */
+ if (_tx_thread_current_ptr -> tx_thread_linux_suspension_type)
+ {
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SCHEDULE-resume_thread", __FILE__, __LINE__);
+
+ /* Pseudo interrupt suspension. The thread is not waiting on
+ its run semaphore. */
+ _tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
+ }
+ else
+ {
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SCHEDULE-release_sem", __FILE__, __LINE__);
+
+ /* Make sure semaphore is 0. */
+ while(!sem_trywait(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore));
+
+ /* Let the thread run again by releasing its run semaphore. */
+ tx_linux_sem_post(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore);
+
+ /* Block timer ISR. */
+ if(_tx_linux_timer_waiting)
+ {
+
+ /* It is woken up by timer ISR. */
+ /* Let ThreadX thread wake up first. */
+ tx_linux_sem_wait(&_tx_linux_semaphore);
+
+ /* Wake up timer ISR. */
+ tx_linux_sem_post_nolock(&_tx_linux_isr_semaphore);
+ }
+ else
+ {
+
+ /* It is woken up by TX_THREAD. */
+ /* Suspend timer thread and let ThreadX thread wake up first. */
+ _tx_linux_thread_suspend(_tx_linux_timer_id);
+ tx_linux_sem_wait(&_tx_linux_semaphore);
+ _tx_linux_thread_resume(_tx_linux_timer_id);
+
+ }
+ }
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SCHEDULE-self_suspend_sem", __FILE__, __LINE__);
+
+ /* Now suspend the main thread so the application thread can run. */
+ tx_linux_sem_wait(&_tx_linux_semaphore);
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SCHEDULE-wake_up", __FILE__, __LINE__);
+
+ }
+}
+
+void _tx_thread_delete_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
+{
+INT linux_status;
+sem_t *threadrunsemaphore;
+pthread_t thread_id;
+struct timespec ts;
+
+ thread_id = thread_ptr -> tx_thread_linux_thread_id;
+ threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ TX_RESTORE
+ do
+ {
+ linux_status = pthread_cancel(thread_id);
+ if(linux_status != EAGAIN)
+ {
+ break;
+ }
+ _tx_linux_thread_resume(thread_id);
+ tx_linux_sem_post(threadrunsemaphore);
+ nanosleep(&ts, &ts);
+ } while (1);
+ pthread_join(thread_id, NULL);
+ sem_destroy(threadrunsemaphore);
+ TX_DISABLE
+}
+
+void _tx_thread_reset_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
+{
+INT linux_status;
+sem_t *threadrunsemaphore;
+pthread_t thread_id;
+struct timespec ts;
+
+ thread_id = thread_ptr -> tx_thread_linux_thread_id;
+ threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ TX_RESTORE
+ do
+ {
+ linux_status = pthread_cancel(thread_id);
+ if(linux_status != EAGAIN)
+ {
+ break;
+ }
+ _tx_linux_thread_resume(thread_id);
+ tx_linux_sem_post(threadrunsemaphore);
+ nanosleep(&ts, &ts);
+ } while (1);
+ pthread_join(thread_id, NULL);
+ sem_destroy(threadrunsemaphore);
+ TX_DISABLE
+}
diff --git a/ports/linux/gnu/src/tx_thread_stack_build.c b/ports/linux/gnu/src/tx_thread_stack_build.c
new file mode 100644
index 00000000..22f49ead
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_stack_build.c
@@ -0,0 +1,153 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* Prototype for new thread entry function. */
+
+void *_tx_linux_thread_entry(void *ptr);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function builds a stack frame on the supplied thread's stack. */
+/* The stack frame results in a fake interrupt return to the supplied */
+/* function pointer. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control blk */
+/* function_ptr Pointer to return function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* pthread_create */
+/* pthread_setschedparam */
+/* _tx_linux_thread_suspend */
+/* sem_init */
+/* printf */
+/* _tx_linux_thread_resume */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* _tx_thread_reset Reset thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+{
+struct sched_param sp;
+
+ /* Create the run semaphore for the thread. This will allow the scheduler
+ control over when the thread actually runs. */
+ if(sem_init(&thread_ptr -> tx_thread_linux_thread_run_semaphore, 0, 0))
+ {
+
+ /* Display an error message. */
+ printf("ThreadX Linux error creating thread running semaphore!\n");
+ while(1)
+ {
+ }
+ }
+
+ /* Create a Linux thread for the application thread. */
+ if(pthread_create(&thread_ptr -> tx_thread_linux_thread_id, NULL, _tx_linux_thread_entry, thread_ptr))
+ {
+
+ /* Display an error message. */
+ printf("ThreadX Linux error creating thread!\n");
+ while(1)
+ {
+ }
+ }
+
+ /* Otherwise, we have a good thread create. */
+ sp.sched_priority = TX_LINUX_PRIORITY_USER_THREAD;
+ pthread_setschedparam(thread_ptr -> tx_thread_linux_thread_id, SCHED_FIFO, &sp);
+
+ /* Setup the thread suspension type to solicited thread suspension.
+ Pseudo interrupt handlers will suspend with this field set to 1. */
+ thread_ptr -> tx_thread_linux_suspension_type = 0;
+
+ /* Clear the disabled count that will keep track of the
+ tx_interrupt_control nesting. */
+ thread_ptr -> tx_thread_linux_int_disabled_flag = 0;
+
+ /* Setup a fake thread stack pointer. */
+ thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
+
+ /* Clear the first word of the stack. */
+ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;
+}
+
+
+void *_tx_linux_thread_entry(void *ptr)
+{
+
+TX_THREAD *thread_ptr;
+
+ /* Pickup the current thread pointer. */
+ thread_ptr = (TX_THREAD *) ptr;
+ _tx_linux_threadx_thread = 1;
+ nice(20);
+
+ /* Now suspend the thread initially. If the thread has already
+ been scheduled, this will return immediately. */
+ tx_linux_sem_wait(&thread_ptr -> tx_thread_linux_thread_run_semaphore);
+ tx_linux_sem_post_nolock(&_tx_linux_semaphore);
+
+ /* Call ThreadX thread entry point. */
+ _tx_thread_shell_entry();
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/ports/linux/gnu/src/tx_thread_system_return.c b/ports/linux/gnu/src/tx_thread_system_return.c
new file mode 100644
index 00000000..e7db8750
--- /dev/null
+++ b/ports/linux/gnu/src/tx_thread_system_return.c
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/* */
+/* 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"
+#include "tx_timer.h"
+#include <stdio.h>
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the system. Only a minimal context */
+/* is saved since the compiler assumes temp registers are going to get */
+/* slicked by a function call anyway. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_linux_debug_entry_insert */
+/* tx_linux_mutex_lock */
+/* pthread_self */
+/* pthread_getschedparam */
+/* pthread_equal */
+/* tx_linux_mutex_recursive_unlock */
+/* tx_linux_mutex_unlock */
+/* pthread_exit */
+/* tx_linux_sem_post */
+/* sem_trywait */
+/* tx_linux_sem_wait */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_system_return(VOID)
+{
+
+TX_THREAD *temp_thread_ptr;
+sem_t *temp_run_semaphore;
+UINT temp_thread_state;
+pthread_t thread_id;
+int exit_code = 0;
+
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SYSTEM_RETURN", __FILE__, __LINE__);
+
+ /* Lock Linux mutex. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* First, determine if the thread was terminated. */
+
+ /* Pickup the id of the current thread. */
+ thread_id = pthread_self();
+
+ /* Pickup the current thread pointer. */
+ temp_thread_ptr = _tx_thread_current_ptr;
+
+ /* Determine if this is a thread (0) and it does not
+ match the current thread pointer. */
+ if ((_tx_linux_threadx_thread) &&
+ ((!temp_thread_ptr) || (!pthread_equal(temp_thread_ptr -> tx_thread_linux_thread_id, thread_id))))
+ {
+
+ /* This indicates the Linux thread was actually terminated by ThreadX is only
+ being allowed to run in order to cleanup its resources. */
+ /* Unlock linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+ pthread_exit((void *)&exit_code);
+ }
+
+ /* Determine if the time-slice is active. */
+ if (_tx_timer_time_slice)
+ {
+
+ /* Preserve current remaining time-slice for the thread and clear the current time-slice. */
+ temp_thread_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
+ _tx_timer_time_slice = 0;
+ }
+
+ /* Save the run semaphore into a temporary variable as well. */
+ temp_run_semaphore = &temp_thread_ptr -> tx_thread_linux_thread_run_semaphore;
+
+ /* Pickup the current thread state. */
+ temp_thread_state = temp_thread_ptr -> tx_thread_state;
+
+ /* Setup the suspension type for this thread. */
+ temp_thread_ptr -> tx_thread_linux_suspension_type = 0;
+
+ /* Set the current thread pointer to NULL. */
+ _tx_thread_current_ptr = TX_NULL;
+
+ /* Unlock Linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SYSTEM_RETURN-release_sem", __FILE__, __LINE__);
+
+ /* Make sure semaphore is 0. */
+ while(!sem_trywait(&_tx_linux_semaphore));
+
+ /* Release the semaphore that the main scheduling thread is waiting
+ on. Note that the main scheduling algorithm will take care of
+ setting the current thread pointer to NULL. */
+ tx_linux_sem_post(&_tx_linux_semaphore);
+
+ /* Determine if the thread was self-terminating. */
+ if (temp_thread_state == TX_TERMINATED)
+ {
+
+ /* Exit the thread instead of waiting on the semaphore! */
+ pthread_exit((void *)&exit_code);
+ }
+
+ /* Wait on the run semaphore for this thread. This won't get set again
+ until the thread is scheduled. */
+ tx_linux_sem_wait(temp_run_semaphore);
+ tx_linux_sem_post_nolock(&_tx_linux_semaphore);
+
+ /* Lock Linux mutex. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SYSTEM_RETURN-wake_up", __FILE__, __LINE__);
+
+ /* Determine if the thread was terminated. */
+
+ /* Pickup the current thread pointer. */
+ temp_thread_ptr = _tx_thread_current_ptr;
+
+ /* Determine if this is a thread and it does not
+ match the current thread pointer. */
+ if ((_tx_linux_threadx_thread) &&
+ ((!temp_thread_ptr) || (!pthread_equal(temp_thread_ptr -> tx_thread_linux_thread_id, thread_id))))
+ {
+
+ /* Unlock Linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+
+ /* This indicates the Linux thread was actually terminated by ThreadX and is only
+ being allowed to run in order to cleanup its resources. */
+ pthread_exit((void *)&exit_code);
+ }
+
+ /* Now determine if the application thread last had interrupts disabled. */
+
+ /* Determine if this thread had interrupts disabled. */
+ if (!_tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag)
+ {
+
+ /* Unlock Linux mutex. */
+ tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
+ }
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("SYSTEM_RETURN-finish", __FILE__, __LINE__);
+}
+
diff --git a/ports/linux/gnu/src/tx_timer_interrupt.c b/ports/linux/gnu/src/tx_timer_interrupt.c
new file mode 100644
index 00000000..5461b302
--- /dev/null
+++ b/ports/linux/gnu/src/tx_timer_interrupt.c
@@ -0,0 +1,153 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Linux/GNU */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes the hardware timer interrupt. This */
+/* processing includes incrementing the system clock and checking for */
+/* time slice and/or timer expiration. If either is found, the */
+/* interrupt context save/restore functions are called along with the */
+/* expiration functions. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_linux_debug_entry_insert */
+/* tx_linux_mutex_lock */
+/* tx_linux_mutex_unlock */
+/* _tx_timer_expiration_process */
+/* _tx_thread_time_slice */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID _tx_timer_interrupt(VOID)
+{
+
+ /* Debug entry. */
+ _tx_linux_debug_entry_insert("TIMER INTERRUPT", __FILE__, __LINE__);
+
+ /* Lock mutex to ensure other threads are not playing with
+ the core ThreadX data structures. */
+ tx_linux_mutex_lock(_tx_linux_mutex);
+
+ /* Increment the system clock. */
+ _tx_timer_system_clock++;
+
+ /* Test for time-slice expiration. */
+ if (_tx_timer_time_slice)
+ {
+
+ /* Decrement the time_slice. */
+ _tx_timer_time_slice--;
+
+ /* Check for expiration. */
+ if (_tx_timer_time_slice == 0)
+ {
+
+ /* Set the time-slice expired flag. */
+ _tx_timer_expired_time_slice = TX_TRUE;
+ }
+ }
+
+ /* Test for timer expiration. */
+ if (*_tx_timer_current_ptr)
+ {
+
+ /* Set expiration flag. */
+ _tx_timer_expired = TX_TRUE;
+ }
+ else
+ {
+
+ /* No timer expired, increment the timer pointer. */
+ _tx_timer_current_ptr++;
+
+ /* Check for wrap-around. */
+ if (_tx_timer_current_ptr == _tx_timer_list_end)
+ {
+
+ /* Wrap to beginning of list. */
+ _tx_timer_current_ptr = _tx_timer_list_start;
+ }
+ }
+
+ /* See if anything has expired. */
+ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ {
+
+ /* Did a timer expire? */
+ if (_tx_timer_expired)
+ {
+
+ /* Process timer expiration. */
+ _tx_timer_expiration_process();
+ }
+
+ /* Did time slice expire? */
+ if (_tx_timer_expired_time_slice)
+ {
+
+ /* Time slice interrupted thread. */
+ _tx_thread_time_slice();
+ }
+ }
+
+ /* Unlock linux mutex. */
+ tx_linux_mutex_unlock(_tx_linux_mutex);
+}
+
diff --git a/ports/win32/gnu/CMakeLists.txt b/ports/win32/gnu/CMakeLists.txt
new file mode 100644
index 00000000..ecc3683d
--- /dev/null
+++ b/ports/win32/gnu/CMakeLists.txt
@@ -0,0 +1,18 @@
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/samples/demo_threadx.c b/samples/demo_threadx.c
new file mode 100644
index 00000000..597f373c
--- /dev/null
+++ b/samples/demo_threadx.c
@@ -0,0 +1,370 @@
+/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
+ threads of different priorities, using a message queue, semaphore, mutex, event flags group,
+ byte pool, and block pool. */
+
+#include "tx_api.h"
+
+#define DEMO_STACK_SIZE 1024
+#define DEMO_BYTE_POOL_SIZE 9120
+#define DEMO_BLOCK_POOL_SIZE 100
+#define DEMO_QUEUE_SIZE 100
+
+
+/* Define the ThreadX object control blocks... */
+
+TX_THREAD thread_0;
+TX_THREAD thread_1;
+TX_THREAD thread_2;
+TX_THREAD thread_3;
+TX_THREAD thread_4;
+TX_THREAD thread_5;
+TX_THREAD thread_6;
+TX_THREAD thread_7;
+TX_QUEUE queue_0;
+TX_SEMAPHORE semaphore_0;
+TX_MUTEX mutex_0;
+TX_EVENT_FLAGS_GROUP event_flags_0;
+TX_BYTE_POOL byte_pool_0;
+TX_BLOCK_POOL block_pool_0;
+UCHAR memory_area[DEMO_BYTE_POOL_SIZE];
+
+
+/* Define the counters used in the demo application... */
+
+ULONG thread_0_counter;
+ULONG thread_1_counter;
+ULONG thread_1_messages_sent;
+ULONG thread_2_counter;
+ULONG thread_2_messages_received;
+ULONG thread_3_counter;
+ULONG thread_4_counter;
+ULONG thread_5_counter;
+ULONG thread_6_counter;
+ULONG thread_7_counter;
+
+
+/* Define thread prototypes. */
+
+void thread_0_entry(ULONG thread_input);
+void thread_1_entry(ULONG thread_input);
+void thread_2_entry(ULONG thread_input);
+void thread_3_and_4_entry(ULONG thread_input);
+void thread_5_entry(ULONG thread_input);
+void thread_6_and_7_entry(ULONG thread_input);
+
+
+/* Define main entry point. */
+
+int main()
+{
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+CHAR *pointer = TX_NULL;
+
+
+ /* Create a byte memory pool from which to allocate the thread stacks. */
+ tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE);
+
+ /* Put system definition stuff in here, e.g. thread creates and other assorted
+ create information. */
+
+ /* Allocate the stack for thread 0. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create the main thread. */
+ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
+ pointer, DEMO_STACK_SIZE,
+ 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+
+ /* Allocate the stack for thread 1. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 1 and 2. These threads pass information through a ThreadX
+ message queue. It is also interesting to note that these threads have a time
+ slice. */
+ tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 2. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 3. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
+ An interesting thing here is that both threads share the same instruction area. */
+ tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 4. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 5. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create thread 5. This thread simply pends on an event flag which will be set
+ by thread_0. */
+ tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
+ pointer, DEMO_STACK_SIZE,
+ 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 6. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
+ tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 7. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the message queue. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
+
+ /* Create the message queue shared by threads 1 and 2. */
+ tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
+
+ /* Create the semaphore used by threads 3 and 4. */
+ tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
+
+ /* Create the event flags group used by threads 1 and 5. */
+ tx_event_flags_create(&event_flags_0, "event flags 0");
+
+ /* Create the mutex used by thread 6 and 7 without priority inheritance. */
+ tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
+
+ /* Allocate the memory for a small block pool. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
+
+ /* Create a block memory pool to allocate a message buffer from. */
+ tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
+
+ /* Allocate a block and release the block memory. */
+ tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
+
+ /* Release the block back to the pool. */
+ tx_block_release(pointer);
+}
+
+
+
+/* Define the test threads. */
+
+void thread_0_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sits in while-forever-sleep loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_0_counter++;
+
+ /* Sleep for 10 ticks. */
+ tx_thread_sleep(10);
+
+ /* Set event flag 0 to wakeup thread 5. */
+ status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
+
+
+void thread_1_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sends messages to a queue shared by thread 2. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_1_counter++;
+
+ /* Send message to queue 0. */
+ status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
+
+ /* Check completion status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Increment the message sent. */
+ thread_1_messages_sent++;
+ }
+}
+
+
+void thread_2_entry(ULONG thread_input)
+{
+
+ULONG received_message;
+UINT status;
+
+ /* This thread retrieves messages placed on the queue by thread 1. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_2_counter++;
+
+ /* Retrieve a message from the queue. */
+ status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
+
+ /* Check completion status and make sure the message is what we
+ expected. */
+ if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
+ break;
+
+ /* Otherwise, all is okay. Increment the received message count. */
+ thread_2_messages_received++;
+ }
+}
+
+
+void thread_3_and_4_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 3 and thread 4. As the loop
+ below shows, these function compete for ownership of semaphore_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 3)
+ thread_3_counter++;
+ else
+ thread_4_counter++;
+
+ /* Get the semaphore with suspension. */
+ status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the semaphore. */
+ tx_thread_sleep(2);
+
+ /* Release the semaphore. */
+ status = tx_semaphore_put(&semaphore_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
+
+
+void thread_5_entry(ULONG thread_input)
+{
+
+UINT status;
+ULONG actual_flags;
+
+
+ /* This thread simply waits for an event in a forever loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_5_counter++;
+
+ /* Wait for event flag 0. */
+ status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
+ &actual_flags, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if ((status != TX_SUCCESS) || (actual_flags != 0x1))
+ break;
+ }
+}
+
+
+void thread_6_and_7_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 6 and thread 7. As the loop
+ below shows, these function compete for ownership of mutex_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 6)
+ thread_6_counter++;
+ else
+ thread_7_counter++;
+
+ /* Get the mutex with suspension. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Get the mutex again with suspension. This shows
+ that an owning thread may retrieve the mutex it
+ owns multiple times. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the mutex. */
+ tx_thread_sleep(2);
+
+ /* Release the mutex. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Release the mutex again. This will actually
+ release ownership since it was obtained twice. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}